17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 1985, 1988, 1993 37c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 67c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 77c478bd9Sstevel@tonic-gate * are met: 87c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 97c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 107c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 117c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 127c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 137c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 147c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 157c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 167c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 177c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 187c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 197c478bd9Sstevel@tonic-gate * without specific prior written permission. 207c478bd9Sstevel@tonic-gate * 217c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 35*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 367c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 397c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 407c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 417c478bd9Sstevel@tonic-gate * 42*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 43*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 45*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 48*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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: lcl_ho.c,v 1.5 2006/03/09 23:57:56 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 <fcntl.h> 737c478bd9Sstevel@tonic-gate #include <netdb.h> 747c478bd9Sstevel@tonic-gate #include <resolv.h> 757c478bd9Sstevel@tonic-gate #include <stdio.h> 767c478bd9Sstevel@tonic-gate #include <stdlib.h> 777c478bd9Sstevel@tonic-gate #include <string.h> 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #include <irs.h> 807c478bd9Sstevel@tonic-gate #include <isc/memcluster.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 #include "lcl_p.h" 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #ifdef SPRINTF_CHAR 897c478bd9Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 907c478bd9Sstevel@tonic-gate #else 917c478bd9Sstevel@tonic-gate # define SPRINTF(x) sprintf x 927c478bd9Sstevel@tonic-gate #endif 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* Definitions. */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #define MAXALIASES 35 977c478bd9Sstevel@tonic-gate #define MAXADDRS 35 987c478bd9Sstevel@tonic-gate #define Max(a,b) ((a) > (b) ? (a) : (b)) 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #if PACKETSZ > 1024 1017c478bd9Sstevel@tonic-gate #define MAXPACKET PACKETSZ 1027c478bd9Sstevel@tonic-gate #else 1037c478bd9Sstevel@tonic-gate #define MAXPACKET 1024 1047c478bd9Sstevel@tonic-gate #endif 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate struct pvt { 1077c478bd9Sstevel@tonic-gate FILE * fp; 1087c478bd9Sstevel@tonic-gate struct hostent host; 1097c478bd9Sstevel@tonic-gate char * h_addr_ptrs[MAXADDRS + 1]; 1107c478bd9Sstevel@tonic-gate char * host_aliases[MAXALIASES]; 1117c478bd9Sstevel@tonic-gate char hostbuf[8*1024]; 112*9525b14bSRao Shoaib u_char host_addr[16]; /*%< IPv4 or IPv6 */ 1137c478bd9Sstevel@tonic-gate struct __res_state *res; 1147c478bd9Sstevel@tonic-gate void (*free_res)(void *); 1157c478bd9Sstevel@tonic-gate }; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate typedef union { 1187c478bd9Sstevel@tonic-gate int32_t al; 1197c478bd9Sstevel@tonic-gate char ac; 1207c478bd9Sstevel@tonic-gate } align; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; 1237c478bd9Sstevel@tonic-gate static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* Forward. */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate static void ho_close(struct irs_ho *this); 1287c478bd9Sstevel@tonic-gate static struct hostent * ho_byname(struct irs_ho *this, const char *name); 1297c478bd9Sstevel@tonic-gate static struct hostent * ho_byname2(struct irs_ho *this, const char *name, 1307c478bd9Sstevel@tonic-gate int af); 1317c478bd9Sstevel@tonic-gate static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, 1327c478bd9Sstevel@tonic-gate int len, int af); 1337c478bd9Sstevel@tonic-gate static struct hostent * ho_next(struct irs_ho *this); 1347c478bd9Sstevel@tonic-gate static void ho_rewind(struct irs_ho *this); 1357c478bd9Sstevel@tonic-gate static void ho_minimize(struct irs_ho *this); 1367c478bd9Sstevel@tonic-gate static struct __res_state * ho_res_get(struct irs_ho *this); 1377c478bd9Sstevel@tonic-gate static void ho_res_set(struct irs_ho *this, 1387c478bd9Sstevel@tonic-gate struct __res_state *res, 1397c478bd9Sstevel@tonic-gate void (*free_res)(void *)); 1407c478bd9Sstevel@tonic-gate static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, 1417c478bd9Sstevel@tonic-gate const struct addrinfo *pai); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate static size_t ns_namelen(const char *); 1447c478bd9Sstevel@tonic-gate static int init(struct irs_ho *this); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* Portability. */ 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate #ifndef SEEK_SET 1497c478bd9Sstevel@tonic-gate # define SEEK_SET 0 1507c478bd9Sstevel@tonic-gate #endif 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* Public. */ 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate struct irs_ho * 1557c478bd9Sstevel@tonic-gate irs_lcl_ho(struct irs_acc *this) { 1567c478bd9Sstevel@tonic-gate struct irs_ho *ho; 1577c478bd9Sstevel@tonic-gate struct pvt *pvt; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate UNUSED(this); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 1627c478bd9Sstevel@tonic-gate errno = ENOMEM; 1637c478bd9Sstevel@tonic-gate return (NULL); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 1667c478bd9Sstevel@tonic-gate if (!(ho = memget(sizeof *ho))) { 1677c478bd9Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1687c478bd9Sstevel@tonic-gate errno = ENOMEM; 1697c478bd9Sstevel@tonic-gate return (NULL); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate memset(ho, 0x5e, sizeof *ho); 1727c478bd9Sstevel@tonic-gate ho->private = pvt; 1737c478bd9Sstevel@tonic-gate ho->close = ho_close; 1747c478bd9Sstevel@tonic-gate ho->byname = ho_byname; 1757c478bd9Sstevel@tonic-gate ho->byname2 = ho_byname2; 1767c478bd9Sstevel@tonic-gate ho->byaddr = ho_byaddr; 1777c478bd9Sstevel@tonic-gate ho->next = ho_next; 1787c478bd9Sstevel@tonic-gate ho->rewind = ho_rewind; 1797c478bd9Sstevel@tonic-gate ho->minimize = ho_minimize; 1807c478bd9Sstevel@tonic-gate ho->res_get = ho_res_get; 1817c478bd9Sstevel@tonic-gate ho->res_set = ho_res_set; 1827c478bd9Sstevel@tonic-gate ho->addrinfo = ho_addrinfo; 1837c478bd9Sstevel@tonic-gate return (ho); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* Methods. */ 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate static void 1897c478bd9Sstevel@tonic-gate ho_close(struct irs_ho *this) { 1907c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate ho_minimize(this); 1937c478bd9Sstevel@tonic-gate if (pvt->fp) 1947c478bd9Sstevel@tonic-gate (void) fclose(pvt->fp); 1957c478bd9Sstevel@tonic-gate if (pvt->res && pvt->free_res) 1967c478bd9Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 1977c478bd9Sstevel@tonic-gate memput(pvt, sizeof *pvt); 1987c478bd9Sstevel@tonic-gate memput(this, sizeof *this); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate static struct hostent * 2027c478bd9Sstevel@tonic-gate ho_byname(struct irs_ho *this, const char *name) { 2037c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2047c478bd9Sstevel@tonic-gate struct hostent *hp; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (init(this) == -1) 2077c478bd9Sstevel@tonic-gate return (NULL); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 2107c478bd9Sstevel@tonic-gate hp = ho_byname2(this, name, AF_INET6); 2117c478bd9Sstevel@tonic-gate if (hp) 2127c478bd9Sstevel@tonic-gate return (hp); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate return (ho_byname2(this, name, AF_INET)); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static struct hostent * 2187c478bd9Sstevel@tonic-gate ho_byname2(struct irs_ho *this, const char *name, int af) { 2197c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2207c478bd9Sstevel@tonic-gate struct hostent *hp; 2217c478bd9Sstevel@tonic-gate char **hap; 2227c478bd9Sstevel@tonic-gate size_t n; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (init(this) == -1) 2257c478bd9Sstevel@tonic-gate return (NULL); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate ho_rewind(this); 2287c478bd9Sstevel@tonic-gate n = ns_namelen(name); 2297c478bd9Sstevel@tonic-gate while ((hp = ho_next(this)) != NULL) { 2307c478bd9Sstevel@tonic-gate size_t nn; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if (hp->h_addrtype != af) 2337c478bd9Sstevel@tonic-gate continue; 2347c478bd9Sstevel@tonic-gate nn = ns_namelen(hp->h_name); 2357c478bd9Sstevel@tonic-gate if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) 2367c478bd9Sstevel@tonic-gate goto found; 2377c478bd9Sstevel@tonic-gate for (hap = hp->h_aliases; *hap; hap++) { 2387c478bd9Sstevel@tonic-gate nn = ns_namelen(*hap); 2397c478bd9Sstevel@tonic-gate if (strncasecmp(*hap, name, Max(n, nn)) == 0) 2407c478bd9Sstevel@tonic-gate goto found; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate found: 2447c478bd9Sstevel@tonic-gate if (!hp) { 2457c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 2467c478bd9Sstevel@tonic-gate return (NULL); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 2497c478bd9Sstevel@tonic-gate return (hp); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate static struct hostent * 2537c478bd9Sstevel@tonic-gate ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { 2547c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 2557c478bd9Sstevel@tonic-gate const u_char *uaddr = addr; 2567c478bd9Sstevel@tonic-gate struct hostent *hp; 2577c478bd9Sstevel@tonic-gate int size; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate if (init(this) == -1) 2607c478bd9Sstevel@tonic-gate return (NULL); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (af == AF_INET6 && len == IN6ADDRSZ && 2637c478bd9Sstevel@tonic-gate (!memcmp(uaddr, mapped, sizeof mapped) || 2647c478bd9Sstevel@tonic-gate !memcmp(uaddr, tunnelled, sizeof tunnelled))) { 2657c478bd9Sstevel@tonic-gate /* Unmap. */ 2667c478bd9Sstevel@tonic-gate addr = (const u_char *)addr + sizeof mapped; 2677c478bd9Sstevel@tonic-gate uaddr += sizeof mapped; 2687c478bd9Sstevel@tonic-gate af = AF_INET; 2697c478bd9Sstevel@tonic-gate len = INADDRSZ; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate switch (af) { 2727c478bd9Sstevel@tonic-gate case AF_INET: 2737c478bd9Sstevel@tonic-gate size = INADDRSZ; 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate case AF_INET6: 2767c478bd9Sstevel@tonic-gate size = IN6ADDRSZ; 2777c478bd9Sstevel@tonic-gate break; 2787c478bd9Sstevel@tonic-gate default: 2797c478bd9Sstevel@tonic-gate errno = EAFNOSUPPORT; 2807c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2817c478bd9Sstevel@tonic-gate return (NULL); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate if (size > len) { 2847c478bd9Sstevel@tonic-gate errno = EINVAL; 2857c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 2867c478bd9Sstevel@tonic-gate return (NULL); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Do the search. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate ho_rewind(this); 2937c478bd9Sstevel@tonic-gate while ((hp = ho_next(this)) != NULL) { 2947c478bd9Sstevel@tonic-gate char **hap; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate for (hap = hp->h_addr_list; *hap; hap++) { 2977c478bd9Sstevel@tonic-gate const u_char *taddr = (const u_char *)*hap; 2987c478bd9Sstevel@tonic-gate int taf = hp->h_addrtype; 2997c478bd9Sstevel@tonic-gate int tlen = hp->h_length; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (taf == AF_INET6 && tlen == IN6ADDRSZ && 3027c478bd9Sstevel@tonic-gate (!memcmp(taddr, mapped, sizeof mapped) || 3037c478bd9Sstevel@tonic-gate !memcmp(taddr, tunnelled, sizeof tunnelled))) { 3047c478bd9Sstevel@tonic-gate /* Unmap. */ 3057c478bd9Sstevel@tonic-gate taddr += sizeof mapped; 3067c478bd9Sstevel@tonic-gate taf = AF_INET; 3077c478bd9Sstevel@tonic-gate tlen = INADDRSZ; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate if (taf == af && tlen == len && 3107c478bd9Sstevel@tonic-gate !memcmp(taddr, uaddr, tlen)) 3117c478bd9Sstevel@tonic-gate goto found; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate found: 3157c478bd9Sstevel@tonic-gate if (!hp) { 3167c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 3177c478bd9Sstevel@tonic-gate return (NULL); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 3207c478bd9Sstevel@tonic-gate return (hp); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate static struct hostent * 3247c478bd9Sstevel@tonic-gate ho_next(struct irs_ho *this) { 3257c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 3267c478bd9Sstevel@tonic-gate char *cp, **q, *p; 3277c478bd9Sstevel@tonic-gate char *bufp, *ndbuf, *dbuf = NULL; 3287c478bd9Sstevel@tonic-gate int c, af, len, bufsiz, offset; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (init(this) == -1) 3317c478bd9Sstevel@tonic-gate return (NULL); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate if (!pvt->fp) 3347c478bd9Sstevel@tonic-gate ho_rewind(this); 3357c478bd9Sstevel@tonic-gate if (!pvt->fp) { 3367c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 3377c478bd9Sstevel@tonic-gate return (NULL); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate bufp = pvt->hostbuf; 3407c478bd9Sstevel@tonic-gate bufsiz = sizeof pvt->hostbuf; 3417c478bd9Sstevel@tonic-gate offset = 0; 3427c478bd9Sstevel@tonic-gate again: 3437c478bd9Sstevel@tonic-gate if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { 3447c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 3457c478bd9Sstevel@tonic-gate if (dbuf) 3467c478bd9Sstevel@tonic-gate free(dbuf); 3477c478bd9Sstevel@tonic-gate return (NULL); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate if (!strchr(p, '\n') && !feof(pvt->fp)) { 3507c478bd9Sstevel@tonic-gate #define GROWBUF 1024 3517c478bd9Sstevel@tonic-gate /* allocate space for longer line */ 3527c478bd9Sstevel@tonic-gate if (dbuf == NULL) { 3537c478bd9Sstevel@tonic-gate if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) 3547c478bd9Sstevel@tonic-gate strcpy(ndbuf, bufp); 3557c478bd9Sstevel@tonic-gate } else 3567c478bd9Sstevel@tonic-gate ndbuf = realloc(dbuf, bufsiz + GROWBUF); 3577c478bd9Sstevel@tonic-gate if (ndbuf) { 3587c478bd9Sstevel@tonic-gate dbuf = ndbuf; 3597c478bd9Sstevel@tonic-gate bufp = dbuf; 3607c478bd9Sstevel@tonic-gate bufsiz += GROWBUF; 3617c478bd9Sstevel@tonic-gate offset = strlen(dbuf); 3627c478bd9Sstevel@tonic-gate } else { 3637c478bd9Sstevel@tonic-gate /* allocation failed; skip this long line */ 3647c478bd9Sstevel@tonic-gate while ((c = getc(pvt->fp)) != EOF) 3657c478bd9Sstevel@tonic-gate if (c == '\n') 3667c478bd9Sstevel@tonic-gate break; 3677c478bd9Sstevel@tonic-gate if (c != EOF) 3687c478bd9Sstevel@tonic-gate ungetc(c, pvt->fp); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate goto again; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate p -= offset; 3747c478bd9Sstevel@tonic-gate offset = 0; 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate if (*p == '#') 3777c478bd9Sstevel@tonic-gate goto again; 3787c478bd9Sstevel@tonic-gate if ((cp = strpbrk(p, "#\n")) != NULL) 3797c478bd9Sstevel@tonic-gate *cp = '\0'; 3807c478bd9Sstevel@tonic-gate if (!(cp = strpbrk(p, " \t"))) 3817c478bd9Sstevel@tonic-gate goto again; 3827c478bd9Sstevel@tonic-gate *cp++ = '\0'; 3837c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { 3847c478bd9Sstevel@tonic-gate af = AF_INET6; 3857c478bd9Sstevel@tonic-gate len = IN6ADDRSZ; 3867c478bd9Sstevel@tonic-gate } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { 3877c478bd9Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 3887c478bd9Sstevel@tonic-gate map_v4v6_address((char*)pvt->host_addr, 3897c478bd9Sstevel@tonic-gate (char*)pvt->host_addr); 3907c478bd9Sstevel@tonic-gate af = AF_INET6; 3917c478bd9Sstevel@tonic-gate len = IN6ADDRSZ; 3927c478bd9Sstevel@tonic-gate } else { 3937c478bd9Sstevel@tonic-gate af = AF_INET; 3947c478bd9Sstevel@tonic-gate len = INADDRSZ; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate } else { 3977c478bd9Sstevel@tonic-gate goto again; 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; 4007c478bd9Sstevel@tonic-gate pvt->h_addr_ptrs[1] = NULL; 4017c478bd9Sstevel@tonic-gate pvt->host.h_addr_list = pvt->h_addr_ptrs; 4027c478bd9Sstevel@tonic-gate pvt->host.h_length = len; 4037c478bd9Sstevel@tonic-gate pvt->host.h_addrtype = af; 4047c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 4057c478bd9Sstevel@tonic-gate cp++; 4067c478bd9Sstevel@tonic-gate pvt->host.h_name = cp; 4077c478bd9Sstevel@tonic-gate q = pvt->host.h_aliases = pvt->host_aliases; 4087c478bd9Sstevel@tonic-gate if ((cp = strpbrk(cp, " \t")) != NULL) 4097c478bd9Sstevel@tonic-gate *cp++ = '\0'; 4107c478bd9Sstevel@tonic-gate while (cp && *cp) { 4117c478bd9Sstevel@tonic-gate if (*cp == ' ' || *cp == '\t') { 4127c478bd9Sstevel@tonic-gate cp++; 4137c478bd9Sstevel@tonic-gate continue; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate if (q < &pvt->host_aliases[MAXALIASES - 1]) 4167c478bd9Sstevel@tonic-gate *q++ = cp; 4177c478bd9Sstevel@tonic-gate if ((cp = strpbrk(cp, " \t")) != NULL) 4187c478bd9Sstevel@tonic-gate *cp++ = '\0'; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate *q = NULL; 4217c478bd9Sstevel@tonic-gate if (dbuf) 4227c478bd9Sstevel@tonic-gate free(dbuf); 4237c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 4247c478bd9Sstevel@tonic-gate return (&pvt->host); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate static void 4287c478bd9Sstevel@tonic-gate ho_rewind(struct irs_ho *this) { 4297c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if (pvt->fp) { 4327c478bd9Sstevel@tonic-gate if (fseek(pvt->fp, 0L, SEEK_SET) == 0) 4337c478bd9Sstevel@tonic-gate return; 4347c478bd9Sstevel@tonic-gate (void)fclose(pvt->fp); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) 4377c478bd9Sstevel@tonic-gate return; 4387c478bd9Sstevel@tonic-gate if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { 4397c478bd9Sstevel@tonic-gate (void)fclose(pvt->fp); 4407c478bd9Sstevel@tonic-gate pvt->fp = NULL; 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate static void 4457c478bd9Sstevel@tonic-gate ho_minimize(struct irs_ho *this) { 4467c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate if (pvt->fp != NULL) { 4497c478bd9Sstevel@tonic-gate (void)fclose(pvt->fp); 4507c478bd9Sstevel@tonic-gate pvt->fp = NULL; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate if (pvt->res) 4537c478bd9Sstevel@tonic-gate res_nclose(pvt->res); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate static struct __res_state * 4577c478bd9Sstevel@tonic-gate ho_res_get(struct irs_ho *this) { 4587c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate if (!pvt->res) { 4617c478bd9Sstevel@tonic-gate struct __res_state *res; 4627c478bd9Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 4637c478bd9Sstevel@tonic-gate if (!res) { 4647c478bd9Sstevel@tonic-gate errno = ENOMEM; 4657c478bd9Sstevel@tonic-gate return (NULL); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate memset(res, 0, sizeof *res); 4687c478bd9Sstevel@tonic-gate ho_res_set(this, res, free); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate return (pvt->res); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate static void 4757c478bd9Sstevel@tonic-gate ho_res_set(struct irs_ho *this, struct __res_state *res, 4767c478bd9Sstevel@tonic-gate void (*free_res)(void *)) { 4777c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 4807c478bd9Sstevel@tonic-gate res_nclose(pvt->res); 4817c478bd9Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate pvt->res = res; 4857c478bd9Sstevel@tonic-gate pvt->free_res = free_res; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate struct lcl_res_target { 4897c478bd9Sstevel@tonic-gate struct lcl_res_target *next; 4907c478bd9Sstevel@tonic-gate int family; 4917c478bd9Sstevel@tonic-gate }; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* XXX */ 4947c478bd9Sstevel@tonic-gate extern struct addrinfo *hostent2addrinfo __P((struct hostent *, 4957c478bd9Sstevel@tonic-gate const struct addrinfo *pai)); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate static struct addrinfo * 4987c478bd9Sstevel@tonic-gate ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5017c478bd9Sstevel@tonic-gate struct hostent *hp; 5027c478bd9Sstevel@tonic-gate struct lcl_res_target q, q2, *p; 5037c478bd9Sstevel@tonic-gate struct addrinfo sentinel, *cur; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate memset(&q, 0, sizeof(q2)); 5067c478bd9Sstevel@tonic-gate memset(&q2, 0, sizeof(q2)); 5077c478bd9Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 5087c478bd9Sstevel@tonic-gate cur = &sentinel; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate switch(pai->ai_family) { 511*9525b14bSRao Shoaib case AF_UNSPEC: /*%< INET6 then INET4 */ 5127c478bd9Sstevel@tonic-gate q.family = AF_INET6; 5137c478bd9Sstevel@tonic-gate q.next = &q2; 5147c478bd9Sstevel@tonic-gate q2.family = AF_INET; 5157c478bd9Sstevel@tonic-gate break; 5167c478bd9Sstevel@tonic-gate case AF_INET6: 5177c478bd9Sstevel@tonic-gate q.family = AF_INET6; 5187c478bd9Sstevel@tonic-gate break; 5197c478bd9Sstevel@tonic-gate case AF_INET: 5207c478bd9Sstevel@tonic-gate q.family = AF_INET; 5217c478bd9Sstevel@tonic-gate break; 5227c478bd9Sstevel@tonic-gate default: 523*9525b14bSRao Shoaib RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /*%< ??? */ 5247c478bd9Sstevel@tonic-gate return(NULL); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate for (p = &q; p; p = p->next) { 5287c478bd9Sstevel@tonic-gate struct addrinfo *ai; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate hp = (*this->byname2)(this, name, p->family); 5317c478bd9Sstevel@tonic-gate if (hp == NULL) { 5327c478bd9Sstevel@tonic-gate /* byname2 should've set an appropriate error */ 5337c478bd9Sstevel@tonic-gate continue; 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || 5367c478bd9Sstevel@tonic-gate (hp->h_addr_list[0] == NULL)) { 5377c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 5387c478bd9Sstevel@tonic-gate continue; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate ai = hostent2addrinfo(hp, pai); 5427c478bd9Sstevel@tonic-gate if (ai) { 5437c478bd9Sstevel@tonic-gate cur->ai_next = ai; 544*9525b14bSRao Shoaib while (cur->ai_next) 5457c478bd9Sstevel@tonic-gate cur = cur->ai_next; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (sentinel.ai_next == NULL) 5507c478bd9Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate return(sentinel.ai_next); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* Private. */ 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate static size_t 5587c478bd9Sstevel@tonic-gate ns_namelen(const char *s) { 5597c478bd9Sstevel@tonic-gate int i; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) 5627c478bd9Sstevel@tonic-gate (void)NULL; 5637c478bd9Sstevel@tonic-gate return ((size_t) i); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate static int 5677c478bd9Sstevel@tonic-gate init(struct irs_ho *this) { 5687c478bd9Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (!pvt->res && !ho_res_get(this)) 5717c478bd9Sstevel@tonic-gate return (-1); 572*9525b14bSRao Shoaib if (((pvt->res->options & RES_INIT) == 0U) && 5737c478bd9Sstevel@tonic-gate res_ninit(pvt->res) == -1) 5747c478bd9Sstevel@tonic-gate return (-1); 5757c478bd9Sstevel@tonic-gate return (0); 5767c478bd9Sstevel@tonic-gate } 577*9525b14bSRao Shoaib 578*9525b14bSRao Shoaib /*! \file */ 579