1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1985, 1988, 1993 8*0Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 9*0Sstevel@tonic-gate * 10*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 11*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 12*0Sstevel@tonic-gate * are met: 13*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 14*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 15*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 16*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 17*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 18*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 19*0Sstevel@tonic-gate * must display the following acknowledgement: 20*0Sstevel@tonic-gate * This product includes software developed by the University of 21*0Sstevel@tonic-gate * California, Berkeley and its contributors. 22*0Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 23*0Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 24*0Sstevel@tonic-gate * without specific prior written permission. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*0Sstevel@tonic-gate * SUCH DAMAGE. 37*0Sstevel@tonic-gate */ 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 41*0Sstevel@tonic-gate * 42*0Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 43*0Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 44*0Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 45*0Sstevel@tonic-gate * 46*0Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 47*0Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 48*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 49*0Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 50*0Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 51*0Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 52*0Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53*0Sstevel@tonic-gate * SOFTWARE. 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ 59*0Sstevel@tonic-gate /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint) 62*0Sstevel@tonic-gate static const char rcsid[] = "$Id: lcl_ho.c,v 1.26 2001/05/29 05:49:04 marka Exp $"; 63*0Sstevel@tonic-gate #endif /* LIBC_SCCS and not lint */ 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* Imports. */ 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate #include "port_before.h" 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate #include <sys/types.h> 70*0Sstevel@tonic-gate #include <sys/param.h> 71*0Sstevel@tonic-gate #include <sys/socket.h> 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate #include <netinet/in.h> 74*0Sstevel@tonic-gate #include <arpa/inet.h> 75*0Sstevel@tonic-gate #include <arpa/nameser.h> 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate #include <ctype.h> 78*0Sstevel@tonic-gate #include <errno.h> 79*0Sstevel@tonic-gate #include <fcntl.h> 80*0Sstevel@tonic-gate #include <netdb.h> 81*0Sstevel@tonic-gate #include <resolv.h> 82*0Sstevel@tonic-gate #include <stdio.h> 83*0Sstevel@tonic-gate #include <stdlib.h> 84*0Sstevel@tonic-gate #include <string.h> 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate #include <irs.h> 87*0Sstevel@tonic-gate #include <isc/memcluster.h> 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate #include "port_after.h" 90*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 91*0Sstevel@tonic-gate #include "../../../libnsl/include/nsl_stdio_prv.h" 92*0Sstevel@tonic-gate #endif 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate #include "irs_p.h" 95*0Sstevel@tonic-gate #include "dns_p.h" 96*0Sstevel@tonic-gate #include "lcl_p.h" 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate #ifdef SPRINTF_CHAR 99*0Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 100*0Sstevel@tonic-gate #else 101*0Sstevel@tonic-gate # define SPRINTF(x) sprintf x 102*0Sstevel@tonic-gate #endif 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* Definitions. */ 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate #define MAXALIASES 35 107*0Sstevel@tonic-gate #define MAXADDRS 35 108*0Sstevel@tonic-gate #define Max(a,b) ((a) > (b) ? (a) : (b)) 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate #if PACKETSZ > 1024 111*0Sstevel@tonic-gate #define MAXPACKET PACKETSZ 112*0Sstevel@tonic-gate #else 113*0Sstevel@tonic-gate #define MAXPACKET 1024 114*0Sstevel@tonic-gate #endif 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate struct pvt { 117*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 118*0Sstevel@tonic-gate __NSL_FILE * fp; 119*0Sstevel@tonic-gate #else 120*0Sstevel@tonic-gate FILE * fp; 121*0Sstevel@tonic-gate #endif 122*0Sstevel@tonic-gate struct hostent host; 123*0Sstevel@tonic-gate char * h_addr_ptrs[MAXADDRS + 1]; 124*0Sstevel@tonic-gate char * host_aliases[MAXALIASES]; 125*0Sstevel@tonic-gate char hostbuf[8*1024]; 126*0Sstevel@tonic-gate u_char host_addr[16]; /* IPv4 or IPv6 */ 127*0Sstevel@tonic-gate struct __res_state *res; 128*0Sstevel@tonic-gate void (*free_res)(void *); 129*0Sstevel@tonic-gate }; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate typedef union { 132*0Sstevel@tonic-gate int32_t al; 133*0Sstevel@tonic-gate char ac; 134*0Sstevel@tonic-gate } align; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; 137*0Sstevel@tonic-gate static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate /* Forward. */ 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate static void ho_close(struct irs_ho *this); 142*0Sstevel@tonic-gate static struct hostent * ho_byname(struct irs_ho *this, const char *name); 143*0Sstevel@tonic-gate static struct hostent * ho_byname2(struct irs_ho *this, const char *name, 144*0Sstevel@tonic-gate int af); 145*0Sstevel@tonic-gate static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, 146*0Sstevel@tonic-gate int len, int af); 147*0Sstevel@tonic-gate static struct hostent * ho_next(struct irs_ho *this); 148*0Sstevel@tonic-gate static void ho_rewind(struct irs_ho *this); 149*0Sstevel@tonic-gate static void ho_minimize(struct irs_ho *this); 150*0Sstevel@tonic-gate static struct __res_state * ho_res_get(struct irs_ho *this); 151*0Sstevel@tonic-gate static void ho_res_set(struct irs_ho *this, 152*0Sstevel@tonic-gate struct __res_state *res, 153*0Sstevel@tonic-gate void (*free_res)(void *)); 154*0Sstevel@tonic-gate static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, 155*0Sstevel@tonic-gate const struct addrinfo *pai); 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate static size_t ns_namelen(const char *); 158*0Sstevel@tonic-gate static int init(struct irs_ho *this); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* Portability. */ 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate #ifndef SEEK_SET 163*0Sstevel@tonic-gate # define SEEK_SET 0 164*0Sstevel@tonic-gate #endif 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* Public. */ 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate struct irs_ho * 169*0Sstevel@tonic-gate irs_lcl_ho(struct irs_acc *this) { 170*0Sstevel@tonic-gate struct irs_ho *ho; 171*0Sstevel@tonic-gate struct pvt *pvt; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate UNUSED(this); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate if (!(pvt = memget(sizeof *pvt))) { 176*0Sstevel@tonic-gate errno = ENOMEM; 177*0Sstevel@tonic-gate return (NULL); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate memset(pvt, 0, sizeof *pvt); 180*0Sstevel@tonic-gate if (!(ho = memget(sizeof *ho))) { 181*0Sstevel@tonic-gate memput(pvt, sizeof *pvt); 182*0Sstevel@tonic-gate errno = ENOMEM; 183*0Sstevel@tonic-gate return (NULL); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate memset(ho, 0x5e, sizeof *ho); 186*0Sstevel@tonic-gate ho->private = pvt; 187*0Sstevel@tonic-gate ho->close = ho_close; 188*0Sstevel@tonic-gate ho->byname = ho_byname; 189*0Sstevel@tonic-gate ho->byname2 = ho_byname2; 190*0Sstevel@tonic-gate ho->byaddr = ho_byaddr; 191*0Sstevel@tonic-gate ho->next = ho_next; 192*0Sstevel@tonic-gate ho->rewind = ho_rewind; 193*0Sstevel@tonic-gate ho->minimize = ho_minimize; 194*0Sstevel@tonic-gate ho->res_get = ho_res_get; 195*0Sstevel@tonic-gate ho->res_set = ho_res_set; 196*0Sstevel@tonic-gate ho->addrinfo = ho_addrinfo; 197*0Sstevel@tonic-gate return (ho); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate /* Methods. */ 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate static void 203*0Sstevel@tonic-gate ho_close(struct irs_ho *this) { 204*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate ho_minimize(this); 207*0Sstevel@tonic-gate if (pvt->fp) 208*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 209*0Sstevel@tonic-gate (void) __nsl_fclose(pvt->fp); 210*0Sstevel@tonic-gate #else 211*0Sstevel@tonic-gate (void) fclose(pvt->fp); 212*0Sstevel@tonic-gate #endif 213*0Sstevel@tonic-gate if (pvt->res && pvt->free_res) 214*0Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 215*0Sstevel@tonic-gate memput(pvt, sizeof *pvt); 216*0Sstevel@tonic-gate memput(this, sizeof *this); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate static struct hostent * 220*0Sstevel@tonic-gate ho_byname(struct irs_ho *this, const char *name) { 221*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 222*0Sstevel@tonic-gate struct hostent *hp; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate if (init(this) == -1) 225*0Sstevel@tonic-gate return (NULL); 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 228*0Sstevel@tonic-gate hp = ho_byname2(this, name, AF_INET6); 229*0Sstevel@tonic-gate if (hp) 230*0Sstevel@tonic-gate return (hp); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate return (ho_byname2(this, name, AF_INET)); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate static struct hostent * 236*0Sstevel@tonic-gate ho_byname2(struct irs_ho *this, const char *name, int af) { 237*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 238*0Sstevel@tonic-gate struct hostent *hp; 239*0Sstevel@tonic-gate char **hap; 240*0Sstevel@tonic-gate size_t n; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (init(this) == -1) 243*0Sstevel@tonic-gate return (NULL); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate ho_rewind(this); 246*0Sstevel@tonic-gate n = ns_namelen(name); 247*0Sstevel@tonic-gate while ((hp = ho_next(this)) != NULL) { 248*0Sstevel@tonic-gate size_t nn; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate if (hp->h_addrtype != af) 251*0Sstevel@tonic-gate continue; 252*0Sstevel@tonic-gate nn = ns_namelen(hp->h_name); 253*0Sstevel@tonic-gate if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) 254*0Sstevel@tonic-gate goto found; 255*0Sstevel@tonic-gate for (hap = hp->h_aliases; *hap; hap++) { 256*0Sstevel@tonic-gate nn = ns_namelen(*hap); 257*0Sstevel@tonic-gate if (strncasecmp(*hap, name, Max(n, nn)) == 0) 258*0Sstevel@tonic-gate goto found; 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate found: 262*0Sstevel@tonic-gate if (!hp) { 263*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 264*0Sstevel@tonic-gate return (NULL); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 267*0Sstevel@tonic-gate return (hp); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate static struct hostent * 271*0Sstevel@tonic-gate ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { 272*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 273*0Sstevel@tonic-gate const u_char *uaddr = addr; 274*0Sstevel@tonic-gate struct hostent *hp; 275*0Sstevel@tonic-gate int size; 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate if (init(this) == -1) 278*0Sstevel@tonic-gate return (NULL); 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (af == AF_INET6 && len == IN6ADDRSZ && 281*0Sstevel@tonic-gate (!memcmp(uaddr, mapped, sizeof mapped) || 282*0Sstevel@tonic-gate !memcmp(uaddr, tunnelled, sizeof tunnelled))) { 283*0Sstevel@tonic-gate /* Unmap. */ 284*0Sstevel@tonic-gate addr = (const u_char *)addr + sizeof mapped; 285*0Sstevel@tonic-gate uaddr += sizeof mapped; 286*0Sstevel@tonic-gate af = AF_INET; 287*0Sstevel@tonic-gate len = INADDRSZ; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate switch (af) { 290*0Sstevel@tonic-gate case AF_INET: 291*0Sstevel@tonic-gate size = INADDRSZ; 292*0Sstevel@tonic-gate break; 293*0Sstevel@tonic-gate case AF_INET6: 294*0Sstevel@tonic-gate size = IN6ADDRSZ; 295*0Sstevel@tonic-gate break; 296*0Sstevel@tonic-gate default: 297*0Sstevel@tonic-gate errno = EAFNOSUPPORT; 298*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 299*0Sstevel@tonic-gate return (NULL); 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate if (size > len) { 302*0Sstevel@tonic-gate errno = EINVAL; 303*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 304*0Sstevel@tonic-gate return (NULL); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * Do the search. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate ho_rewind(this); 311*0Sstevel@tonic-gate while ((hp = ho_next(this)) != NULL) { 312*0Sstevel@tonic-gate char **hap; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate for (hap = hp->h_addr_list; *hap; hap++) { 315*0Sstevel@tonic-gate const u_char *taddr = (const u_char *)*hap; 316*0Sstevel@tonic-gate int taf = hp->h_addrtype; 317*0Sstevel@tonic-gate int tlen = hp->h_length; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if (taf == AF_INET6 && tlen == IN6ADDRSZ && 320*0Sstevel@tonic-gate (!memcmp(taddr, mapped, sizeof mapped) || 321*0Sstevel@tonic-gate !memcmp(taddr, tunnelled, sizeof tunnelled))) { 322*0Sstevel@tonic-gate /* Unmap. */ 323*0Sstevel@tonic-gate taddr += sizeof mapped; 324*0Sstevel@tonic-gate taf = AF_INET; 325*0Sstevel@tonic-gate tlen = INADDRSZ; 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate if (taf == af && tlen == len && 328*0Sstevel@tonic-gate !memcmp(taddr, uaddr, tlen)) 329*0Sstevel@tonic-gate goto found; 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate found: 333*0Sstevel@tonic-gate if (!hp) { 334*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 335*0Sstevel@tonic-gate return (NULL); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 338*0Sstevel@tonic-gate return (hp); 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate static struct hostent * 342*0Sstevel@tonic-gate ho_next(struct irs_ho *this) { 343*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 344*0Sstevel@tonic-gate char *cp, **q, *p; 345*0Sstevel@tonic-gate char *bufp, *ndbuf, *dbuf = NULL; 346*0Sstevel@tonic-gate int c, af, len, bufsiz, offset; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate if (init(this) == -1) 349*0Sstevel@tonic-gate return (NULL); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate if (!pvt->fp) 352*0Sstevel@tonic-gate ho_rewind(this); 353*0Sstevel@tonic-gate if (!pvt->fp) { 354*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 355*0Sstevel@tonic-gate return (NULL); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate bufp = pvt->hostbuf; 358*0Sstevel@tonic-gate bufsiz = sizeof pvt->hostbuf; 359*0Sstevel@tonic-gate offset = 0; 360*0Sstevel@tonic-gate again: 361*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 362*0Sstevel@tonic-gate if (!(p = __nsl_fgets(bufp + offset, bufsiz - offset, pvt->fp))) { 363*0Sstevel@tonic-gate #else 364*0Sstevel@tonic-gate if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { 365*0Sstevel@tonic-gate #endif 366*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 367*0Sstevel@tonic-gate if (dbuf) 368*0Sstevel@tonic-gate free(dbuf); 369*0Sstevel@tonic-gate return (NULL); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 372*0Sstevel@tonic-gate if (!strchr(p, '\n') && !__nsl_feof(pvt->fp)) { 373*0Sstevel@tonic-gate #else 374*0Sstevel@tonic-gate if (!strchr(p, '\n') && !feof(pvt->fp)) { 375*0Sstevel@tonic-gate #endif 376*0Sstevel@tonic-gate #define GROWBUF 1024 377*0Sstevel@tonic-gate /* allocate space for longer line */ 378*0Sstevel@tonic-gate if (dbuf == NULL) { 379*0Sstevel@tonic-gate if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) 380*0Sstevel@tonic-gate strcpy(ndbuf, bufp); 381*0Sstevel@tonic-gate } else 382*0Sstevel@tonic-gate ndbuf = realloc(dbuf, bufsiz + GROWBUF); 383*0Sstevel@tonic-gate if (ndbuf) { 384*0Sstevel@tonic-gate dbuf = ndbuf; 385*0Sstevel@tonic-gate bufp = dbuf; 386*0Sstevel@tonic-gate bufsiz += GROWBUF; 387*0Sstevel@tonic-gate offset = strlen(dbuf); 388*0Sstevel@tonic-gate } else { 389*0Sstevel@tonic-gate /* allocation failed; skip this long line */ 390*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 391*0Sstevel@tonic-gate while ((c = __nsl_getc(pvt->fp)) != EOF) 392*0Sstevel@tonic-gate #else 393*0Sstevel@tonic-gate while ((c = getc(pvt->fp)) != EOF) 394*0Sstevel@tonic-gate #endif 395*0Sstevel@tonic-gate if (c == '\n') 396*0Sstevel@tonic-gate break; 397*0Sstevel@tonic-gate if (c != EOF) 398*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 399*0Sstevel@tonic-gate __nsl_ungetc(c, pvt->fp); 400*0Sstevel@tonic-gate #else 401*0Sstevel@tonic-gate ungetc(c, pvt->fp); 402*0Sstevel@tonic-gate #endif 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate goto again; 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate p -= offset; 408*0Sstevel@tonic-gate offset = 0; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate if (*p == '#') 411*0Sstevel@tonic-gate goto again; 412*0Sstevel@tonic-gate if ((cp = strpbrk(p, "#\n")) != NULL) 413*0Sstevel@tonic-gate *cp = '\0'; 414*0Sstevel@tonic-gate if (!(cp = strpbrk(p, " \t"))) 415*0Sstevel@tonic-gate goto again; 416*0Sstevel@tonic-gate *cp++ = '\0'; 417*0Sstevel@tonic-gate if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { 418*0Sstevel@tonic-gate af = AF_INET6; 419*0Sstevel@tonic-gate len = IN6ADDRSZ; 420*0Sstevel@tonic-gate } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { 421*0Sstevel@tonic-gate if (pvt->res->options & RES_USE_INET6) { 422*0Sstevel@tonic-gate map_v4v6_address((char*)pvt->host_addr, 423*0Sstevel@tonic-gate (char*)pvt->host_addr); 424*0Sstevel@tonic-gate af = AF_INET6; 425*0Sstevel@tonic-gate len = IN6ADDRSZ; 426*0Sstevel@tonic-gate } else { 427*0Sstevel@tonic-gate af = AF_INET; 428*0Sstevel@tonic-gate len = INADDRSZ; 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate } else { 431*0Sstevel@tonic-gate goto again; 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; 434*0Sstevel@tonic-gate pvt->h_addr_ptrs[1] = NULL; 435*0Sstevel@tonic-gate pvt->host.h_addr_list = pvt->h_addr_ptrs; 436*0Sstevel@tonic-gate pvt->host.h_length = len; 437*0Sstevel@tonic-gate pvt->host.h_addrtype = af; 438*0Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 439*0Sstevel@tonic-gate cp++; 440*0Sstevel@tonic-gate pvt->host.h_name = cp; 441*0Sstevel@tonic-gate q = pvt->host.h_aliases = pvt->host_aliases; 442*0Sstevel@tonic-gate if ((cp = strpbrk(cp, " \t")) != NULL) 443*0Sstevel@tonic-gate *cp++ = '\0'; 444*0Sstevel@tonic-gate while (cp && *cp) { 445*0Sstevel@tonic-gate if (*cp == ' ' || *cp == '\t') { 446*0Sstevel@tonic-gate cp++; 447*0Sstevel@tonic-gate continue; 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate if (q < &pvt->host_aliases[MAXALIASES - 1]) 450*0Sstevel@tonic-gate *q++ = cp; 451*0Sstevel@tonic-gate if ((cp = strpbrk(cp, " \t")) != NULL) 452*0Sstevel@tonic-gate *cp++ = '\0'; 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate *q = NULL; 455*0Sstevel@tonic-gate if (dbuf) 456*0Sstevel@tonic-gate free(dbuf); 457*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); 458*0Sstevel@tonic-gate return (&pvt->host); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate static void 462*0Sstevel@tonic-gate ho_rewind(struct irs_ho *this) { 463*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 466*0Sstevel@tonic-gate if (pvt->fp) { 467*0Sstevel@tonic-gate if (__nsl_fseek(pvt->fp, 0L, SEEK_SET) == 0) 468*0Sstevel@tonic-gate return; 469*0Sstevel@tonic-gate (void)__nsl_fclose(pvt->fp); 470*0Sstevel@tonic-gate } 471*0Sstevel@tonic-gate if (!(pvt->fp = __nsl_fopen(_PATH_HOSTS, "r"))) 472*0Sstevel@tonic-gate return; 473*0Sstevel@tonic-gate if (fcntl(__nsl_fileno(pvt->fp), F_SETFD, 1) < 0) { 474*0Sstevel@tonic-gate (void)__nsl_fclose(pvt->fp); 475*0Sstevel@tonic-gate pvt->fp = NULL; 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate #else 478*0Sstevel@tonic-gate if (pvt->fp) { 479*0Sstevel@tonic-gate if (fseek(pvt->fp, 0L, SEEK_SET) == 0) 480*0Sstevel@tonic-gate return; 481*0Sstevel@tonic-gate (void)fclose(pvt->fp); 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) 484*0Sstevel@tonic-gate return; 485*0Sstevel@tonic-gate if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { 486*0Sstevel@tonic-gate (void)fclose(pvt->fp); 487*0Sstevel@tonic-gate pvt->fp = NULL; 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate #endif 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate static void 494*0Sstevel@tonic-gate ho_minimize(struct irs_ho *this) { 495*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate if (pvt->fp != NULL) { 498*0Sstevel@tonic-gate #ifdef SUNW_AVOIDSTDIO_FDLIMIT 499*0Sstevel@tonic-gate (void)__nsl_fclose(pvt->fp); 500*0Sstevel@tonic-gate #else 501*0Sstevel@tonic-gate (void)fclose(pvt->fp); 502*0Sstevel@tonic-gate #endif 503*0Sstevel@tonic-gate pvt->fp = NULL; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate if (pvt->res) 506*0Sstevel@tonic-gate res_nclose(pvt->res); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate static struct __res_state * 510*0Sstevel@tonic-gate ho_res_get(struct irs_ho *this) { 511*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate if (!pvt->res) { 514*0Sstevel@tonic-gate struct __res_state *res; 515*0Sstevel@tonic-gate res = (struct __res_state *)malloc(sizeof *res); 516*0Sstevel@tonic-gate if (!res) { 517*0Sstevel@tonic-gate errno = ENOMEM; 518*0Sstevel@tonic-gate return (NULL); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate memset(res, 0, sizeof *res); 521*0Sstevel@tonic-gate ho_res_set(this, res, free); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate return (pvt->res); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate static void 528*0Sstevel@tonic-gate ho_res_set(struct irs_ho *this, struct __res_state *res, 529*0Sstevel@tonic-gate void (*free_res)(void *)) { 530*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate if (pvt->res && pvt->free_res) { 533*0Sstevel@tonic-gate res_nclose(pvt->res); 534*0Sstevel@tonic-gate (*pvt->free_res)(pvt->res); 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate pvt->res = res; 538*0Sstevel@tonic-gate pvt->free_res = free_res; 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate struct lcl_res_target { 542*0Sstevel@tonic-gate struct lcl_res_target *next; 543*0Sstevel@tonic-gate int family; 544*0Sstevel@tonic-gate }; 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate /* XXX */ 547*0Sstevel@tonic-gate extern struct addrinfo *hostent2addrinfo __P((struct hostent *, 548*0Sstevel@tonic-gate const struct addrinfo *pai)); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate static struct addrinfo * 551*0Sstevel@tonic-gate ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 554*0Sstevel@tonic-gate struct hostent *hp; 555*0Sstevel@tonic-gate struct lcl_res_target q, q2, *p; 556*0Sstevel@tonic-gate struct addrinfo sentinel, *cur; 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate memset(&q, 0, sizeof(q2)); 559*0Sstevel@tonic-gate memset(&q2, 0, sizeof(q2)); 560*0Sstevel@tonic-gate memset(&sentinel, 0, sizeof(sentinel)); 561*0Sstevel@tonic-gate cur = &sentinel; 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate switch(pai->ai_family) { 564*0Sstevel@tonic-gate case AF_UNSPEC: /* INET6 then INET4 */ 565*0Sstevel@tonic-gate q.family = AF_INET6; 566*0Sstevel@tonic-gate q.next = &q2; 567*0Sstevel@tonic-gate q2.family = AF_INET; 568*0Sstevel@tonic-gate break; 569*0Sstevel@tonic-gate case AF_INET6: 570*0Sstevel@tonic-gate q.family = AF_INET6; 571*0Sstevel@tonic-gate break; 572*0Sstevel@tonic-gate case AF_INET: 573*0Sstevel@tonic-gate q.family = AF_INET; 574*0Sstevel@tonic-gate break; 575*0Sstevel@tonic-gate default: 576*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ 577*0Sstevel@tonic-gate return(NULL); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate for (p = &q; p; p = p->next) { 581*0Sstevel@tonic-gate struct addrinfo *ai; 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate hp = (*this->byname2)(this, name, p->family); 584*0Sstevel@tonic-gate if (hp == NULL) { 585*0Sstevel@tonic-gate /* byname2 should've set an appropriate error */ 586*0Sstevel@tonic-gate continue; 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || 589*0Sstevel@tonic-gate (hp->h_addr_list[0] == NULL)) { 590*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); 591*0Sstevel@tonic-gate continue; 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate ai = hostent2addrinfo(hp, pai); 595*0Sstevel@tonic-gate if (ai) { 596*0Sstevel@tonic-gate cur->ai_next = ai; 597*0Sstevel@tonic-gate while (cur && cur->ai_next) 598*0Sstevel@tonic-gate cur = cur->ai_next; 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate if (sentinel.ai_next == NULL) 603*0Sstevel@tonic-gate RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate return(sentinel.ai_next); 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate /* Private. */ 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate static size_t 611*0Sstevel@tonic-gate ns_namelen(const char *s) { 612*0Sstevel@tonic-gate int i; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) 615*0Sstevel@tonic-gate (void)NULL; 616*0Sstevel@tonic-gate return ((size_t) i); 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate static int 620*0Sstevel@tonic-gate init(struct irs_ho *this) { 621*0Sstevel@tonic-gate struct pvt *pvt = (struct pvt *)this->private; 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate if (!pvt->res && !ho_res_get(this)) 624*0Sstevel@tonic-gate return (-1); 625*0Sstevel@tonic-gate if (((pvt->res->options & RES_INIT) == 0) && 626*0Sstevel@tonic-gate res_ninit(pvt->res) == -1) 627*0Sstevel@tonic-gate return (-1); 628*0Sstevel@tonic-gate return (0); 629*0Sstevel@tonic-gate } 630