17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22cb5caa98Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * files/gethostent.c -- "files" backend for nsswitch "hosts" database 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <netdb.h> 317c478bd9Sstevel@tonic-gate #include "files_common.h" 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <stddef.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <sys/socket.h> 387c478bd9Sstevel@tonic-gate #include <netinet/in.h> 397c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 40cb5caa98Sdjl #include <arpa/inet.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate 43cb5caa98Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 44cb5caa98Sdjl int, const char **, int *, void *, int *); 457c478bd9Sstevel@tonic-gate static char *do_aliases(); 46cb5caa98Sdjl static char *strcasestr(const char *as1, const char *as2); 477c478bd9Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname(); 487c478bd9Sstevel@tonic-gate int __nss_files_2herrno(); 49cb5caa98Sdjl static int __nss_files_get_addr(int, const char *, int, 50cb5caa98Sdjl void *, int, int *); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static int 53cb5caa98Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 54cb5caa98Sdjl int type, const char **namep, int *namelen, 55cb5caa98Sdjl void *addrp, int *addrsize) 567c478bd9Sstevel@tonic-gate { 57cb5caa98Sdjl const char *limit, *linep, *keyp, *addrstart; 58cb5caa98Sdjl int v6flag = 0, addrlen; 59cb5caa98Sdjl 60cb5caa98Sdjl linep = line; 61cb5caa98Sdjl limit = line + linelen; 62cb5caa98Sdjl 63cb5caa98Sdjl /* Address */ 64cb5caa98Sdjl addrstart = linep; 65cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 66cb5caa98Sdjl if (*linep == ':') 67cb5caa98Sdjl v6flag++; 68cb5caa98Sdjl linep++; 697c478bd9Sstevel@tonic-gate } 70cb5caa98Sdjl addrlen = linep - addrstart; 71cb5caa98Sdjl 72cb5caa98Sdjl /* skip the delimiting spaces */ 73cb5caa98Sdjl while (linep < limit && isspace(*linep)) 74cb5caa98Sdjl linep++; 75cb5caa98Sdjl 76cb5caa98Sdjl /* Canonical name */ 77cb5caa98Sdjl keyp = argp->key.name; 78cb5caa98Sdjl *namep = linep; 79cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 80cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 81cb5caa98Sdjl keyp++; 82cb5caa98Sdjl linep++; 83cb5caa98Sdjl } 84cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 85cb5caa98Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 86cb5caa98Sdjl addrp, v6flag, addrsize)) { 87cb5caa98Sdjl *namelen = linep - *namep; 887c478bd9Sstevel@tonic-gate return (1); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate } 91cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 92cb5caa98Sdjl linep++; 93cb5caa98Sdjl *namelen = linep - *namep; 94cb5caa98Sdjl 95cb5caa98Sdjl /* Aliases */ 96cb5caa98Sdjl while (linep < limit) { 97cb5caa98Sdjl /* skip the delimiting spaces */ 98cb5caa98Sdjl while (linep < limit && isspace(*linep)) 99cb5caa98Sdjl linep++; 100cb5caa98Sdjl 101cb5caa98Sdjl /* compare name (case insensitive) */ 102cb5caa98Sdjl keyp = argp->key.name; 103cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 104cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 105cb5caa98Sdjl keyp++; 106cb5caa98Sdjl linep++; 107cb5caa98Sdjl } 108cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 109cb5caa98Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 110cb5caa98Sdjl addrp, v6flag, addrsize)); 111cb5caa98Sdjl 112cb5caa98Sdjl /* skip remainder of alias, if any */ 113cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 114cb5caa98Sdjl linep++; 115cb5caa98Sdjl } 1167c478bd9Sstevel@tonic-gate return (0); 117cb5caa98Sdjl 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static nss_status_t 1217c478bd9Sstevel@tonic-gate getbyname(be, a) 1227c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 1237c478bd9Sstevel@tonic-gate void *a; 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1267c478bd9Sstevel@tonic-gate nss_status_t res; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET); 1297c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) 1307c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 1317c478bd9Sstevel@tonic-gate return (res); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 134cb5caa98Sdjl static int 135cb5caa98Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 136cb5caa98Sdjl void *addrp, int v6flag, int *h_length) 137cb5caa98Sdjl { 138cb5caa98Sdjl struct in_addr addr_ipv4; 139cb5caa98Sdjl struct in6_addr *addrpv6; 140cb5caa98Sdjl in_addr_t *addrpv4; 141cb5caa98Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 142cb5caa98Sdjl 143cb5caa98Sdjl if (addrlen >= sizeof (addrbuf)) 144cb5caa98Sdjl return (0); 145cb5caa98Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 146cb5caa98Sdjl addrbuf[addrlen] = '\0'; 147cb5caa98Sdjl 148cb5caa98Sdjl if (af == AF_INET) { 149cb5caa98Sdjl addrpv4 = (in_addr_t *)addrp; 150cb5caa98Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 151cb5caa98Sdjl return (0); 152cb5caa98Sdjl *h_length = sizeof (in_addr_t); 153cb5caa98Sdjl } else if (af == AF_INET6) { 154cb5caa98Sdjl addrpv6 = (struct in6_addr *)addrp; 155cb5caa98Sdjl if (v6flag) { 156cb5caa98Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 157cb5caa98Sdjl return (0); 158cb5caa98Sdjl } else { 159cb5caa98Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 160cb5caa98Sdjl 0xffffffffU) 161cb5caa98Sdjl return (0); 162cb5caa98Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 163cb5caa98Sdjl } 164cb5caa98Sdjl *h_length = sizeof (struct in6_addr); 165cb5caa98Sdjl } else { 166cb5caa98Sdjl return (0); 167cb5caa98Sdjl } 168cb5caa98Sdjl return (1); 169cb5caa98Sdjl } 170cb5caa98Sdjl 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate int 173cb5caa98Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 174cb5caa98Sdjl int linelen) 1757c478bd9Sstevel@tonic-gate { 176cb5caa98Sdjl const char *limit, *linep, *addrstart; 177cb5caa98Sdjl int v6flag = 0, addrlen, h_length; 178cb5caa98Sdjl in_addr_t addr_ipv4; 179cb5caa98Sdjl struct in6_addr addr_ipv6; 180cb5caa98Sdjl char *h_addrp; 181cb5caa98Sdjl 182cb5caa98Sdjl /* Compare the address type */ 183cb5caa98Sdjl if (argp->key.hostaddr.type != af) 184cb5caa98Sdjl return (0); 1857c478bd9Sstevel@tonic-gate 186cb5caa98Sdjl /* Retrieve the address */ 187cb5caa98Sdjl if (af == AF_INET) 188cb5caa98Sdjl h_addrp = (char *)&addr_ipv4; 189cb5caa98Sdjl else 190cb5caa98Sdjl h_addrp = (char *)&addr_ipv6; 191cb5caa98Sdjl linep = line; 192cb5caa98Sdjl limit = line + linelen; 193cb5caa98Sdjl addrstart = linep; 194cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 195cb5caa98Sdjl if (*linep == ':') 196cb5caa98Sdjl v6flag++; 197cb5caa98Sdjl linep++; 198cb5caa98Sdjl } 199cb5caa98Sdjl addrlen = linep - addrstart; 200cb5caa98Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 201cb5caa98Sdjl v6flag, &h_length) == 0) 202cb5caa98Sdjl return (0); 203cb5caa98Sdjl 204cb5caa98Sdjl /* Compare the address */ 205cb5caa98Sdjl return (h_length == argp->key.hostaddr.len && 206cb5caa98Sdjl memcmp(h_addrp, argp->key.hostaddr.addr, 2077c478bd9Sstevel@tonic-gate argp->key.hostaddr.len) == 0); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 210cb5caa98Sdjl static int 211cb5caa98Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 212cb5caa98Sdjl { 213cb5caa98Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 214cb5caa98Sdjl } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate static nss_status_t 2177c478bd9Sstevel@tonic-gate getbyaddr(be, a) 2187c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 2197c478bd9Sstevel@tonic-gate void *a; 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2227c478bd9Sstevel@tonic-gate nss_status_t res; 2237c478bd9Sstevel@tonic-gate 224cb5caa98Sdjl res = _nss_files_XY_all(be, argp, 1, 0, check_addr); 2257c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) 2267c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 2277c478bd9Sstevel@tonic-gate return (res); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 230*c77e7dfdSchinlong int _inet_aton(const char *cp, struct in_addr *addr); 231*c77e7dfdSchinlong /* 232*c77e7dfdSchinlong * filter_ipv6 233*c77e7dfdSchinlong * 234*c77e7dfdSchinlong * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address 235*c77e7dfdSchinlong * NSS_STR_PARSE_PARSE: An IPv6 address or other errors 236*c77e7dfdSchinlong */ 237*c77e7dfdSchinlong static int 238*c77e7dfdSchinlong filter_ipv6(char *instr, int lenstr) { 239*c77e7dfdSchinlong char *p, *addrstart, *limit, c; 240*c77e7dfdSchinlong int rc; 241*c77e7dfdSchinlong struct in_addr addr; 242*c77e7dfdSchinlong 243*c77e7dfdSchinlong p = instr; 244*c77e7dfdSchinlong limit = p + lenstr; 245*c77e7dfdSchinlong 246*c77e7dfdSchinlong addrstart = p; 247*c77e7dfdSchinlong 248*c77e7dfdSchinlong /* parse IP address */ 249*c77e7dfdSchinlong while (p < limit && !isspace(*p)) { 250*c77e7dfdSchinlong if (*p == ':') 251*c77e7dfdSchinlong /* IPv6 */ 252*c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 253*c77e7dfdSchinlong else 254*c77e7dfdSchinlong p++; 255*c77e7dfdSchinlong } 256*c77e7dfdSchinlong 257*c77e7dfdSchinlong if (p >= limit) 258*c77e7dfdSchinlong /* invalid IP */ 259*c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 260*c77e7dfdSchinlong 261*c77e7dfdSchinlong /* extract IP address */ 262*c77e7dfdSchinlong c = *p; 263*c77e7dfdSchinlong *p = '\0'; 264*c77e7dfdSchinlong rc = _inet_aton(addrstart, &addr); 265*c77e7dfdSchinlong *p = c; 266*c77e7dfdSchinlong 267*c77e7dfdSchinlong if (rc == 0) 268*c77e7dfdSchinlong /* invalid IP */ 269*c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 270*c77e7dfdSchinlong else 271*c77e7dfdSchinlong /* IPv4 */ 272*c77e7dfdSchinlong return (NSS_STR_PARSE_SUCCESS); 273*c77e7dfdSchinlong 274*c77e7dfdSchinlong 275*c77e7dfdSchinlong } 276*c77e7dfdSchinlong static nss_status_t 277*c77e7dfdSchinlong getent_hosts(files_backend_ptr_t be, void *a) 278*c77e7dfdSchinlong { 279*c77e7dfdSchinlong nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 280*c77e7dfdSchinlong nss_status_t rc = NSS_SUCCESS; 281*c77e7dfdSchinlong 282*c77e7dfdSchinlong if (args->buf.result != NULL) { 283*c77e7dfdSchinlong return (_nss_files_XY_all(be, args, 1, 0, 0)); 284*c77e7dfdSchinlong } else { 285*c77e7dfdSchinlong /* 286*c77e7dfdSchinlong * Called by nscd 287*c77e7dfdSchinlong */ 288*c77e7dfdSchinlong /*CONSTCOND*/ 289*c77e7dfdSchinlong while (1) { 290*c77e7dfdSchinlong rc = _nss_files_XY_all(be, args, 1, 0, 0); 291*c77e7dfdSchinlong /* 292*c77e7dfdSchinlong * NSS_NOTFOUND, end of file or other errors. 293*c77e7dfdSchinlong */ 294*c77e7dfdSchinlong if (rc != NSS_SUCCESS) 295*c77e7dfdSchinlong break; 296*c77e7dfdSchinlong /* 297*c77e7dfdSchinlong * /etc/hosts and /etc/ipnodes are merged and 298*c77e7dfdSchinlong * /etc/hosts can contain IPv6 addresses. 299*c77e7dfdSchinlong * These addresses have to be filtered. 300*c77e7dfdSchinlong */ 301*c77e7dfdSchinlong if (filter_ipv6(args->returnval, args->returnlen) 302*c77e7dfdSchinlong == NSS_STR_PARSE_SUCCESS) 303*c77e7dfdSchinlong break; 304*c77e7dfdSchinlong /* 305*c77e7dfdSchinlong * The entry is an IPv6 address or other errors. 306*c77e7dfdSchinlong * Skip it and continue to find next one. 307*c77e7dfdSchinlong */ 308*c77e7dfdSchinlong args->returnval = NULL; 309*c77e7dfdSchinlong args->returnlen = 0; 310*c77e7dfdSchinlong 311*c77e7dfdSchinlong } 312*c77e7dfdSchinlong return (rc); 313*c77e7dfdSchinlong } 314*c77e7dfdSchinlong 315*c77e7dfdSchinlong } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 3187c478bd9Sstevel@tonic-gate _nss_files_destr, 3197c478bd9Sstevel@tonic-gate _nss_files_endent, 3207c478bd9Sstevel@tonic-gate _nss_files_setent, 321*c77e7dfdSchinlong getent_hosts, 3227c478bd9Sstevel@tonic-gate getbyname, 3237c478bd9Sstevel@tonic-gate getbyaddr, 3247c478bd9Sstevel@tonic-gate }; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3277c478bd9Sstevel@tonic-gate nss_backend_t * 3287c478bd9Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 3297c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate return (_nss_files_constr(host_ops, 3327c478bd9Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 3337c478bd9Sstevel@tonic-gate _PATH_HOSTS, 3347c478bd9Sstevel@tonic-gate NSS_LINELEN_HOSTS, 3357c478bd9Sstevel@tonic-gate NULL)); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 3417c478bd9Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate nss_status_t 3447c478bd9Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 3457c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 3467c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 3477c478bd9Sstevel@tonic-gate const char *filter; /* hint for name string */ 3487c478bd9Sstevel@tonic-gate int type; 3497c478bd9Sstevel@tonic-gate { 350cb5caa98Sdjl nss_status_t res; 351cb5caa98Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 352cb5caa98Sdjl char *first, *last, *buffer; 353cb5caa98Sdjl int parsestat, i, nhosts = 0, buflen; 354cb5caa98Sdjl const char *namep; 355cb5caa98Sdjl char *h_name; 356cb5caa98Sdjl int h_namelen, namelen; 357cb5caa98Sdjl struct hostent *hp; 358cb5caa98Sdjl in_addr_t *taddr = NULL; 359cb5caa98Sdjl struct in6_addr *taddr6 = NULL; 360cb5caa98Sdjl size_t ntaddr; 361cb5caa98Sdjl void *addrp; 362cb5caa98Sdjl char *alias_end = NULL; 363cb5caa98Sdjl 364cb5caa98Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 3657c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (be->f == 0) { 3697c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 3707c478bd9Sstevel@tonic-gate return (res); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 373cb5caa98Sdjl ntaddr = MAXADDRS; 374cb5caa98Sdjl if (type == AF_INET) { 375cb5caa98Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 376cb5caa98Sdjl if (taddr == NULL) 377cb5caa98Sdjl return (NSS_UNAVAIL); 378cb5caa98Sdjl } else { 379cb5caa98Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 380cb5caa98Sdjl if (taddr6 == NULL) 381cb5caa98Sdjl return (NSS_UNAVAIL); 382cb5caa98Sdjl } 383cb5caa98Sdjl 3847c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3857c478bd9Sstevel@tonic-gate args->returnval = (char *)0; 386cb5caa98Sdjl args->returnlen = 0; 387cb5caa98Sdjl hp = (struct hostent *)args->buf.result; 388cb5caa98Sdjl buffer = args->buf.buffer; 389cb5caa98Sdjl buflen = args->buf.buflen; 390cb5caa98Sdjl h_namelen = 0; 391cb5caa98Sdjl h_name = NULL; 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate for (;;) { 3947c478bd9Sstevel@tonic-gate char *instr = be->buf; 3957c478bd9Sstevel@tonic-gate int linelen; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3987c478bd9Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3997c478bd9Sstevel@tonic-gate break; /* EOF */ 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 4047c478bd9Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 4057c478bd9Sstevel@tonic-gate * already matched entry doesn't share a canonical name 4067c478bd9Sstevel@tonic-gate * with the current one, bail. 4077c478bd9Sstevel@tonic-gate */ 4087c478bd9Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 4097c478bd9Sstevel@tonic-gate continue; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 4137c478bd9Sstevel@tonic-gate last = instr + linelen; 4147c478bd9Sstevel@tonic-gate *last-- = '\0'; 4157c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 4167c478bd9Sstevel@tonic-gate ; 4177c478bd9Sstevel@tonic-gate /* Ignore blank and comment lines */ 4187c478bd9Sstevel@tonic-gate if (*first == '\0') 4197c478bd9Sstevel@tonic-gate continue; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate while (isspace(*last)) 4227c478bd9Sstevel@tonic-gate --last; 4237c478bd9Sstevel@tonic-gate linelen = last - first + 1; 4247c478bd9Sstevel@tonic-gate if (first != instr) 4257c478bd9Sstevel@tonic-gate instr = first; 4267c478bd9Sstevel@tonic-gate 427cb5caa98Sdjl /* Bail out if the canonical name does not match */ 428cb5caa98Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 4297c478bd9Sstevel@tonic-gate continue; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 4347c478bd9Sstevel@tonic-gate */ 435cb5caa98Sdjl addrp = (type == AF_INET)? 436cb5caa98Sdjl (void *)&taddr[nhosts]: 437cb5caa98Sdjl (void *)&taddr6[nhosts]; 438cb5caa98Sdjl 439cb5caa98Sdjl if (check_name(args, instr, linelen, 440cb5caa98Sdjl type, &namep, &namelen, 441cb5caa98Sdjl addrp, &i)) { 4427c478bd9Sstevel@tonic-gate 443cb5caa98Sdjl /* 444cb5caa98Sdjl * If we've already matched once and have a possible 445cb5caa98Sdjl * match on this line, copy the aliases where they're 446cb5caa98Sdjl * safe from being overwritten when we look at the 447cb5caa98Sdjl * next entry. They're saved as a string of blank 448cb5caa98Sdjl * separated names for the alias parser. On errors, 449cb5caa98Sdjl * we return failure whether or not we have already 450cb5caa98Sdjl * obtained a valid address. 451cb5caa98Sdjl */ 452cb5caa98Sdjl if (nhosts == 1 && hp) { 453cb5caa98Sdjl if (h_namelen + 1 > args->buf.buflen) { 454cb5caa98Sdjl args->erange = 1; 455cb5caa98Sdjl res = NSS_NOTFOUND; 456cb5caa98Sdjl break; 457cb5caa98Sdjl } 458cb5caa98Sdjl abuf = (char *)malloc(args->buf.buflen); 459cb5caa98Sdjl if (abuf == NULL) { 460cb5caa98Sdjl res = NSS_UNAVAIL; 461cb5caa98Sdjl break; 462cb5caa98Sdjl } 463cb5caa98Sdjl abuf_start = abuf; 464cb5caa98Sdjl abuf_end = abuf_start + args->buf.buflen; 465cb5caa98Sdjl (void) memcpy(abuf, h_name, h_namelen); 466cb5caa98Sdjl abuf += h_namelen; 467cb5caa98Sdjl *abuf = '\0'; 468cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 469cb5caa98Sdjl if (abuf == NULL) { 470cb5caa98Sdjl args->erange = 1; 471cb5caa98Sdjl res = NSS_NOTFOUND; 472cb5caa98Sdjl break; 473cb5caa98Sdjl } 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 476cb5caa98Sdjl if (hp != NULL) { 477cb5caa98Sdjl /* inside the application */ 478cb5caa98Sdjl parsestat = (*args->str2ent)(instr, linelen, 479cb5caa98Sdjl hp, buffer, buflen); 480cb5caa98Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 481cb5caa98Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 482cb5caa98Sdjl args->erange = 1; 483cb5caa98Sdjl (void) memset(buffer, 0, buflen); 484cb5caa98Sdjl continue; 485cb5caa98Sdjl } 486cb5caa98Sdjl } else { 487cb5caa98Sdjl /* inside nscd */ 488cb5caa98Sdjl int alen, cplen, erange = 0; 489cb5caa98Sdjl char *ap; 490cb5caa98Sdjl 491cb5caa98Sdjl /* Add alias to the first line if any */ 492cb5caa98Sdjl if (nhosts > 0) { 493cb5caa98Sdjl 494cb5caa98Sdjl /* get to the start of alias */ 495cb5caa98Sdjl ap = (char *)namep + namelen; 496cb5caa98Sdjl /* see if there's any alias */ 497cb5caa98Sdjl if (ap == instr + linelen) 498cb5caa98Sdjl alen = 0; 499cb5caa98Sdjl else 500cb5caa98Sdjl alen = linelen - (ap - instr); 501cb5caa98Sdjl if (alen + 1 >= buflen) 502cb5caa98Sdjl erange = 1; 503cb5caa98Sdjl if (erange == 0 && alen != 0) { 504cb5caa98Sdjl /* make room for the alias */ 505cb5caa98Sdjl if (alias_end != NULL) 506cb5caa98Sdjl (void) memmove(alias_end + 507cb5caa98Sdjl alen, alias_end, buffer - 508cb5caa98Sdjl alias_end); 509cb5caa98Sdjl /* copy in the alias */ 510cb5caa98Sdjl (void) memmove(alias_end, 511cb5caa98Sdjl ap, alen); 512cb5caa98Sdjl buffer += alen; 513cb5caa98Sdjl buflen -= alen; 514cb5caa98Sdjl alias_end += alen; 515cb5caa98Sdjl } 516cb5caa98Sdjl 517cb5caa98Sdjl /* Add delimiter to the buffer */ 518cb5caa98Sdjl *buffer++ = '\n'; 519cb5caa98Sdjl buflen--; 520cb5caa98Sdjl args->returnlen++; 521cb5caa98Sdjl } 522cb5caa98Sdjl 523cb5caa98Sdjl /* copy just the addr if not first one */ 524cb5caa98Sdjl if (alias_end == NULL) 525cb5caa98Sdjl cplen = linelen; 526cb5caa98Sdjl else 527cb5caa98Sdjl cplen = namep - instr; 528cb5caa98Sdjl 529cb5caa98Sdjl if (cplen >= buflen || erange == 1) { 530cb5caa98Sdjl args->erange = 1; 531cb5caa98Sdjl if (nhosts > 0) { 532cb5caa98Sdjl *(--buffer) = '\0'; 533cb5caa98Sdjl buflen++; 534cb5caa98Sdjl args->returnlen--; 535cb5caa98Sdjl } 536cb5caa98Sdjl continue; 537cb5caa98Sdjl } 538cb5caa98Sdjl 539cb5caa98Sdjl (void) memcpy(buffer, instr, cplen); 540cb5caa98Sdjl /* Adjust buffer */ 541cb5caa98Sdjl buffer += cplen; 542cb5caa98Sdjl *buffer = '\0'; 543cb5caa98Sdjl buflen -= cplen; 544cb5caa98Sdjl if (alias_end == NULL) 545cb5caa98Sdjl alias_end = buffer; 546cb5caa98Sdjl } 547cb5caa98Sdjl 548cb5caa98Sdjl args->returnlen += linelen; 5497c478bd9Sstevel@tonic-gate 550cb5caa98Sdjl /* 551cb5caa98Sdjl * If this is the first one, save the canonical 552cb5caa98Sdjl * name for future matches and continue. 553cb5caa98Sdjl */ 554cb5caa98Sdjl if (++nhosts == 1) { 555cb5caa98Sdjl h_name = malloc(namelen + 1); 556cb5caa98Sdjl if (h_name == NULL) { 557cb5caa98Sdjl res = NSS_UNAVAIL; 558cb5caa98Sdjl break; 559cb5caa98Sdjl } 5607c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 561cb5caa98Sdjl (void) memcpy(h_name, namep, namelen); 562cb5caa98Sdjl h_name[namelen] = '\0'; 563cb5caa98Sdjl h_namelen = namelen; 564cb5caa98Sdjl if (hp) 565cb5caa98Sdjl args->returnval = hp; 566cb5caa98Sdjl else 567cb5caa98Sdjl args->returnval = args->buf.buffer; 5687c478bd9Sstevel@tonic-gate continue; 5697c478bd9Sstevel@tonic-gate } 570cb5caa98Sdjl 571cb5caa98Sdjl 572cb5caa98Sdjl /* Extend the array */ 573cb5caa98Sdjl if (nhosts >= ntaddr) { 574cb5caa98Sdjl ntaddr *= 2; 575cb5caa98Sdjl if (type == AF_INET) { 576cb5caa98Sdjl addrp = realloc(taddr, 577cb5caa98Sdjl sizeof (*taddr) * ntaddr); 578cb5caa98Sdjl if (addrp == NULL) { 579cb5caa98Sdjl res = NSS_UNAVAIL; 580cb5caa98Sdjl break; 581cb5caa98Sdjl } 582cb5caa98Sdjl taddr = (in_addr_t *)addrp; 583cb5caa98Sdjl } else { 584cb5caa98Sdjl addrp = realloc(taddr6, 585cb5caa98Sdjl sizeof (*taddr6) * ntaddr); 586cb5caa98Sdjl if (addrp == NULL) { 587cb5caa98Sdjl res = NSS_UNAVAIL; 588cb5caa98Sdjl break; 589cb5caa98Sdjl } 590cb5caa98Sdjl taddr6 = (struct in6_addr *)addrp; 591cb5caa98Sdjl } 592cb5caa98Sdjl } 593cb5caa98Sdjl 594cb5caa98Sdjl /* 595cb5caa98Sdjl * For non-nscd, save aliases in a temporary buffer 596cb5caa98Sdjl * Don't have to do this for nscd as 'buffer' already 597cb5caa98Sdjl * contains the required data in the appropriate 598cb5caa98Sdjl * format 599cb5caa98Sdjl */ 600cb5caa98Sdjl if (hp) { 601cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 602cb5caa98Sdjl if (abuf == NULL) { 603cb5caa98Sdjl args->erange = 1; 604cb5caa98Sdjl res = NSS_NOTFOUND; 605cb5caa98Sdjl break; 606cb5caa98Sdjl } 6077c478bd9Sstevel@tonic-gate } 608cb5caa98Sdjl } else if (namep && h_namelen == namelen && 609cb5caa98Sdjl strncasecmp(h_name, namep, namelen) == 0) { 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * This line didn't have the requested name but 6127c478bd9Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 6137c478bd9Sstevel@tonic-gate * has the same canonical name as the previous 6147c478bd9Sstevel@tonic-gate * line), so march on... 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gate continue; 6177c478bd9Sstevel@tonic-gate } else if (nhosts) { 6187c478bd9Sstevel@tonic-gate break; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 622cb5caa98Sdjl if (abuf && res == NSS_SUCCESS) { 623cb5caa98Sdjl 624cb5caa98Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 625cb5caa98Sdjl 6267c478bd9Sstevel@tonic-gate struct in_addr *addrp; 6277c478bd9Sstevel@tonic-gate struct in6_addr *addrp6; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (type == AF_INET) { 6307c478bd9Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 6317c478bd9Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 6327c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 6337c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6347c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 6357c478bd9Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 6367c478bd9Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 6377c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate } else { 6407c478bd9Sstevel@tonic-gate addrp6 = (struct in6_addr *) 6417c478bd9Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 6427c478bd9Sstevel@tonic-gate sizeof (*addrp6))); 6437c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 6447c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6457c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 6467c478bd9Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 647cb5caa98Sdjl (void) memcpy(addrp6, &taddr6[i], 648cb5caa98Sdjl sizeof (struct in6_addr)); 6497c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 6547c478bd9Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 6557c478bd9Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 6567c478bd9Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 6577c478bd9Sstevel@tonic-gate if (hp->h_aliases == 0) { 6587c478bd9Sstevel@tonic-gate args->erange = 1; 659cb5caa98Sdjl res = NSS_NOTFOUND; 6607c478bd9Sstevel@tonic-gate } else { 6617c478bd9Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 6627c478bd9Sstevel@tonic-gate hp->h_aliases++; 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 6687c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate if (!args->stayopen) 6717c478bd9Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 6727c478bd9Sstevel@tonic-gate 673cb5caa98Sdjl if (taddr) 674cb5caa98Sdjl free(taddr); 675cb5caa98Sdjl if (taddr6) 676cb5caa98Sdjl free(taddr6); 677cb5caa98Sdjl if (h_name) 678cb5caa98Sdjl free(h_name); 679cb5caa98Sdjl if (abuf_start) 680cb5caa98Sdjl free(abuf_start); 681cb5caa98Sdjl 6827c478bd9Sstevel@tonic-gate return (res); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* 6867c478bd9Sstevel@tonic-gate * A case-insensitive version of strstr(). 6877c478bd9Sstevel@tonic-gate */ 6887c478bd9Sstevel@tonic-gate static char * 689cb5caa98Sdjl strcasestr(const char *as1, const char *as2) 6907c478bd9Sstevel@tonic-gate { 6917c478bd9Sstevel@tonic-gate int c2; 692cb5caa98Sdjl register const char *tptr; 693cb5caa98Sdjl register const char *s1, *s2; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate s1 = as1; 6967c478bd9Sstevel@tonic-gate s2 = as2; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 6997c478bd9Sstevel@tonic-gate return (0); 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate while (*s1) { 7027c478bd9Sstevel@tonic-gate if (tolower(*s1++) == tolower(c2 = *s2)) { 7037c478bd9Sstevel@tonic-gate tptr = s1; 7047c478bd9Sstevel@tonic-gate while ((tolower(c2 = *++s2) == 7057c478bd9Sstevel@tonic-gate tolower(*s1++)) && c2 != 0) 7067c478bd9Sstevel@tonic-gate ; 7077c478bd9Sstevel@tonic-gate if (c2 == 0) 7087c478bd9Sstevel@tonic-gate return ((char *)tptr - 1); 7097c478bd9Sstevel@tonic-gate s1 = tptr; 7107c478bd9Sstevel@tonic-gate s2 = as2; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate return (0); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate static char * 718cb5caa98Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 7197c478bd9Sstevel@tonic-gate { 720cb5caa98Sdjl char **cp; 721cb5caa98Sdjl size_t len; 7227c478bd9Sstevel@tonic-gate 723cb5caa98Sdjl if ((cp = hp->h_aliases) == NULL) 724cb5caa98Sdjl return (abuf); 7257c478bd9Sstevel@tonic-gate 726cb5caa98Sdjl for (; *cp; cp++) { 7277c478bd9Sstevel@tonic-gate len = strlen(*cp); 7287c478bd9Sstevel@tonic-gate if (abuf+len+1 >= end) { 729cb5caa98Sdjl return (NULL); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate *abuf++ = ' '; 732cb5caa98Sdjl (void) memcpy(abuf, *cp, len); 733cb5caa98Sdjl abuf += len; 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate *abuf = '\0'; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate return (abuf); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 7437c478bd9Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 7447c478bd9Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate int 7477c478bd9Sstevel@tonic-gate __nss_files_2herrno(nsstat) 7487c478bd9Sstevel@tonic-gate nss_status_t nsstat; 7497c478bd9Sstevel@tonic-gate { 7507c478bd9Sstevel@tonic-gate switch (nsstat) { 7517c478bd9Sstevel@tonic-gate case NSS_SUCCESS: 7527c478bd9Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 7537c478bd9Sstevel@tonic-gate return (0); 7547c478bd9Sstevel@tonic-gate case NSS_NOTFOUND: 7557c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND); 7567c478bd9Sstevel@tonic-gate case NSS_TRYAGAIN: 7577c478bd9Sstevel@tonic-gate return (TRY_AGAIN); 7587c478bd9Sstevel@tonic-gate case NSS_UNAVAIL: 7597c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate /* anything else */ 7627c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 7637c478bd9Sstevel@tonic-gate } 764