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 */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <netdb.h> 277c478bd9Sstevel@tonic-gate #include "files_common.h" 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <stddef.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/socket.h> 347c478bd9Sstevel@tonic-gate #include <netinet/in.h> 357c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 36cb5caa98Sdjl #include <arpa/inet.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate 39cb5caa98Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 40cb5caa98Sdjl int, const char **, int *, void *, int *); 417c478bd9Sstevel@tonic-gate static char *do_aliases(); 427c478bd9Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname(); 437c478bd9Sstevel@tonic-gate int __nss_files_2herrno(); 44cb5caa98Sdjl static int __nss_files_get_addr(int, const char *, int, 45cb5caa98Sdjl void *, int, int *); 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static int 48cb5caa98Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 49cb5caa98Sdjl int type, const char **namep, int *namelen, 50cb5caa98Sdjl void *addrp, int *addrsize) 517c478bd9Sstevel@tonic-gate { 52cb5caa98Sdjl const char *limit, *linep, *keyp, *addrstart; 53cb5caa98Sdjl int v6flag = 0, addrlen; 547c478bd9Sstevel@tonic-gate 55cb5caa98Sdjl linep = line; 56cb5caa98Sdjl limit = line + linelen; 57cb5caa98Sdjl 58cb5caa98Sdjl /* Address */ 59cb5caa98Sdjl addrstart = linep; 60cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 61cb5caa98Sdjl if (*linep == ':') 62cb5caa98Sdjl v6flag++; 63cb5caa98Sdjl linep++; 647c478bd9Sstevel@tonic-gate } 65cb5caa98Sdjl addrlen = linep - addrstart; 66cb5caa98Sdjl 67cb5caa98Sdjl /* skip the delimiting spaces */ 68cb5caa98Sdjl while (linep < limit && isspace(*linep)) 69cb5caa98Sdjl linep++; 70cb5caa98Sdjl 71cb5caa98Sdjl /* Canonical name */ 72cb5caa98Sdjl keyp = argp->key.name; 73cb5caa98Sdjl *namep = linep; 74cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 75cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 76cb5caa98Sdjl keyp++; 77cb5caa98Sdjl linep++; 78cb5caa98Sdjl } 79cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 80cb5caa98Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 81cb5caa98Sdjl addrp, v6flag, addrsize)) { 82cb5caa98Sdjl *namelen = linep - *namep; 837c478bd9Sstevel@tonic-gate return (1); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate } 86cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 87cb5caa98Sdjl linep++; 88cb5caa98Sdjl *namelen = linep - *namep; 89cb5caa98Sdjl 90cb5caa98Sdjl /* Aliases */ 91cb5caa98Sdjl while (linep < limit) { 92cb5caa98Sdjl /* skip the delimiting spaces */ 93cb5caa98Sdjl while (linep < limit && isspace(*linep)) 94cb5caa98Sdjl linep++; 95cb5caa98Sdjl 96cb5caa98Sdjl /* compare name (case insensitive) */ 97cb5caa98Sdjl keyp = argp->key.name; 98cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 99cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 100cb5caa98Sdjl keyp++; 101cb5caa98Sdjl linep++; 102cb5caa98Sdjl } 103cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 104cb5caa98Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 105cb5caa98Sdjl addrp, v6flag, addrsize)); 106cb5caa98Sdjl 107cb5caa98Sdjl /* skip remainder of alias, if any */ 108cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 109cb5caa98Sdjl linep++; 110cb5caa98Sdjl } 1117c478bd9Sstevel@tonic-gate return (0); 112cb5caa98Sdjl 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static nss_status_t 1167c478bd9Sstevel@tonic-gate getbyname(be, a) 1177c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 1187c478bd9Sstevel@tonic-gate void *a; 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1217c478bd9Sstevel@tonic-gate nss_status_t res; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET); 1247c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) 1257c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 1267c478bd9Sstevel@tonic-gate return (res); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 129cb5caa98Sdjl static int 130cb5caa98Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 131cb5caa98Sdjl void *addrp, int v6flag, int *h_length) 132cb5caa98Sdjl { 133cb5caa98Sdjl struct in_addr addr_ipv4; 134cb5caa98Sdjl struct in6_addr *addrpv6; 135cb5caa98Sdjl in_addr_t *addrpv4; 136cb5caa98Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 137cb5caa98Sdjl 138cb5caa98Sdjl if (addrlen >= sizeof (addrbuf)) 139cb5caa98Sdjl return (0); 140cb5caa98Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 141cb5caa98Sdjl addrbuf[addrlen] = '\0'; 142cb5caa98Sdjl 143cb5caa98Sdjl if (af == AF_INET) { 144cb5caa98Sdjl addrpv4 = (in_addr_t *)addrp; 145cb5caa98Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 146cb5caa98Sdjl return (0); 147cb5caa98Sdjl *h_length = sizeof (in_addr_t); 148cb5caa98Sdjl } else if (af == AF_INET6) { 149cb5caa98Sdjl addrpv6 = (struct in6_addr *)addrp; 150cb5caa98Sdjl if (v6flag) { 151cb5caa98Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 152cb5caa98Sdjl return (0); 153cb5caa98Sdjl } else { 154cb5caa98Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 155cb5caa98Sdjl 0xffffffffU) 156cb5caa98Sdjl return (0); 157cb5caa98Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 158cb5caa98Sdjl } 159cb5caa98Sdjl *h_length = sizeof (struct in6_addr); 160cb5caa98Sdjl } else { 161cb5caa98Sdjl return (0); 162cb5caa98Sdjl } 163cb5caa98Sdjl return (1); 164cb5caa98Sdjl } 165cb5caa98Sdjl 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate int 168cb5caa98Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 169cb5caa98Sdjl int linelen) 1707c478bd9Sstevel@tonic-gate { 171cb5caa98Sdjl const char *limit, *linep, *addrstart; 172cb5caa98Sdjl int v6flag = 0, addrlen, h_length; 173cb5caa98Sdjl in_addr_t addr_ipv4; 174cb5caa98Sdjl struct in6_addr addr_ipv6; 175cb5caa98Sdjl char *h_addrp; 1767c478bd9Sstevel@tonic-gate 177cb5caa98Sdjl /* Compare the address type */ 178cb5caa98Sdjl if (argp->key.hostaddr.type != af) 179cb5caa98Sdjl return (0); 180cb5caa98Sdjl 181cb5caa98Sdjl /* Retrieve the address */ 182cb5caa98Sdjl if (af == AF_INET) 183cb5caa98Sdjl h_addrp = (char *)&addr_ipv4; 184cb5caa98Sdjl else 185cb5caa98Sdjl h_addrp = (char *)&addr_ipv6; 186cb5caa98Sdjl linep = line; 187cb5caa98Sdjl limit = line + linelen; 188cb5caa98Sdjl addrstart = linep; 189cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 190cb5caa98Sdjl if (*linep == ':') 191cb5caa98Sdjl v6flag++; 192cb5caa98Sdjl linep++; 193cb5caa98Sdjl } 194cb5caa98Sdjl addrlen = linep - addrstart; 195cb5caa98Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 196cb5caa98Sdjl v6flag, &h_length) == 0) 197cb5caa98Sdjl return (0); 198cb5caa98Sdjl 199cb5caa98Sdjl /* Compare the address */ 200cb5caa98Sdjl return (h_length == argp->key.hostaddr.len && 201cb5caa98Sdjl memcmp(h_addrp, argp->key.hostaddr.addr, 2027c478bd9Sstevel@tonic-gate argp->key.hostaddr.len) == 0); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 205cb5caa98Sdjl static int 206cb5caa98Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 207cb5caa98Sdjl { 208cb5caa98Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 209cb5caa98Sdjl } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static nss_status_t 2127c478bd9Sstevel@tonic-gate getbyaddr(be, a) 2137c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 2147c478bd9Sstevel@tonic-gate void *a; 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2177c478bd9Sstevel@tonic-gate nss_status_t res; 2187c478bd9Sstevel@tonic-gate 219cb5caa98Sdjl res = _nss_files_XY_all(be, argp, 1, 0, check_addr); 2207c478bd9Sstevel@tonic-gate if (res != NSS_SUCCESS) 2217c478bd9Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 2227c478bd9Sstevel@tonic-gate return (res); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 225c77e7dfdSchinlong /* 226c77e7dfdSchinlong * filter_ipv6 227c77e7dfdSchinlong * 228c77e7dfdSchinlong * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address 229c77e7dfdSchinlong * NSS_STR_PARSE_PARSE: An IPv6 address or other errors 230c77e7dfdSchinlong */ 231c77e7dfdSchinlong static int 232c77e7dfdSchinlong filter_ipv6(char *instr, int lenstr) { 233c77e7dfdSchinlong char *p, *addrstart, *limit, c; 234c77e7dfdSchinlong int rc; 235c77e7dfdSchinlong struct in_addr addr; 236c77e7dfdSchinlong 237c77e7dfdSchinlong p = instr; 238c77e7dfdSchinlong limit = p + lenstr; 239c77e7dfdSchinlong 240c77e7dfdSchinlong addrstart = p; 241c77e7dfdSchinlong 242c77e7dfdSchinlong /* parse IP address */ 243c77e7dfdSchinlong while (p < limit && !isspace(*p)) { 244c77e7dfdSchinlong if (*p == ':') 245c77e7dfdSchinlong /* IPv6 */ 246c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 247c77e7dfdSchinlong else 248c77e7dfdSchinlong p++; 249c77e7dfdSchinlong } 250c77e7dfdSchinlong 251c77e7dfdSchinlong if (p >= limit) 252c77e7dfdSchinlong /* invalid IP */ 253c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 254c77e7dfdSchinlong 255c77e7dfdSchinlong /* extract IP address */ 256c77e7dfdSchinlong c = *p; 257c77e7dfdSchinlong *p = '\0'; 2587257d1b4Sraf rc = inet_aton(addrstart, &addr); 259c77e7dfdSchinlong *p = c; 260c77e7dfdSchinlong 261c77e7dfdSchinlong if (rc == 0) 262c77e7dfdSchinlong /* invalid IP */ 263c77e7dfdSchinlong return (NSS_STR_PARSE_PARSE); 264c77e7dfdSchinlong else 265c77e7dfdSchinlong /* IPv4 */ 266c77e7dfdSchinlong return (NSS_STR_PARSE_SUCCESS); 267c77e7dfdSchinlong 268c77e7dfdSchinlong 269c77e7dfdSchinlong } 270c77e7dfdSchinlong static nss_status_t 271c77e7dfdSchinlong getent_hosts(files_backend_ptr_t be, void *a) 272c77e7dfdSchinlong { 273c77e7dfdSchinlong nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 274c77e7dfdSchinlong nss_status_t rc = NSS_SUCCESS; 275c77e7dfdSchinlong 276c77e7dfdSchinlong if (args->buf.result != NULL) { 277c77e7dfdSchinlong return (_nss_files_XY_all(be, args, 1, 0, 0)); 278c77e7dfdSchinlong } else { 279c77e7dfdSchinlong /* 280c77e7dfdSchinlong * Called by nscd 281c77e7dfdSchinlong */ 282c77e7dfdSchinlong /*CONSTCOND*/ 283c77e7dfdSchinlong while (1) { 284c77e7dfdSchinlong rc = _nss_files_XY_all(be, args, 1, 0, 0); 285c77e7dfdSchinlong /* 286c77e7dfdSchinlong * NSS_NOTFOUND, end of file or other errors. 287c77e7dfdSchinlong */ 288c77e7dfdSchinlong if (rc != NSS_SUCCESS) 289c77e7dfdSchinlong break; 290c77e7dfdSchinlong /* 291c77e7dfdSchinlong * /etc/hosts and /etc/ipnodes are merged and 292c77e7dfdSchinlong * /etc/hosts can contain IPv6 addresses. 293c77e7dfdSchinlong * These addresses have to be filtered. 294c77e7dfdSchinlong */ 295c77e7dfdSchinlong if (filter_ipv6(args->returnval, args->returnlen) 296c77e7dfdSchinlong == NSS_STR_PARSE_SUCCESS) 297c77e7dfdSchinlong break; 298c77e7dfdSchinlong /* 299c77e7dfdSchinlong * The entry is an IPv6 address or other errors. 300c77e7dfdSchinlong * Skip it and continue to find next one. 301c77e7dfdSchinlong */ 302c77e7dfdSchinlong args->returnval = NULL; 303c77e7dfdSchinlong args->returnlen = 0; 304c77e7dfdSchinlong 305c77e7dfdSchinlong } 306c77e7dfdSchinlong return (rc); 307c77e7dfdSchinlong } 308c77e7dfdSchinlong 309c77e7dfdSchinlong } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 3127c478bd9Sstevel@tonic-gate _nss_files_destr, 3137c478bd9Sstevel@tonic-gate _nss_files_endent, 3147c478bd9Sstevel@tonic-gate _nss_files_setent, 315c77e7dfdSchinlong getent_hosts, 3167c478bd9Sstevel@tonic-gate getbyname, 3177c478bd9Sstevel@tonic-gate getbyaddr, 3187c478bd9Sstevel@tonic-gate }; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3217c478bd9Sstevel@tonic-gate nss_backend_t * 3227c478bd9Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 3237c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3247c478bd9Sstevel@tonic-gate { 3257c478bd9Sstevel@tonic-gate return (_nss_files_constr(host_ops, 3267c478bd9Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 3277c478bd9Sstevel@tonic-gate _PATH_HOSTS, 3287c478bd9Sstevel@tonic-gate NSS_LINELEN_HOSTS, 3297c478bd9Sstevel@tonic-gate NULL)); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 3357c478bd9Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate nss_status_t 3387c478bd9Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 3397c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 3407c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 3417c478bd9Sstevel@tonic-gate const char *filter; /* hint for name string */ 3427c478bd9Sstevel@tonic-gate int type; 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate nss_status_t res; 345cb5caa98Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 346cb5caa98Sdjl char *first, *last, *buffer; 347cb5caa98Sdjl int parsestat, i, nhosts = 0, buflen; 348cb5caa98Sdjl const char *namep; 349cb5caa98Sdjl char *h_name; 350cb5caa98Sdjl int h_namelen, namelen; 351cb5caa98Sdjl struct hostent *hp; 352cb5caa98Sdjl in_addr_t *taddr = NULL; 353cb5caa98Sdjl struct in6_addr *taddr6 = NULL; 354cb5caa98Sdjl size_t ntaddr; 355cb5caa98Sdjl void *addrp; 356cb5caa98Sdjl char *alias_end = NULL; 3577c478bd9Sstevel@tonic-gate 358cb5caa98Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 3597c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (be->f == 0) { 3637c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 3647c478bd9Sstevel@tonic-gate return (res); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 367cb5caa98Sdjl ntaddr = MAXADDRS; 368cb5caa98Sdjl if (type == AF_INET) { 369cb5caa98Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 370cb5caa98Sdjl if (taddr == NULL) 371cb5caa98Sdjl return (NSS_UNAVAIL); 372cb5caa98Sdjl } else { 373cb5caa98Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 374cb5caa98Sdjl if (taddr6 == NULL) 375cb5caa98Sdjl return (NSS_UNAVAIL); 376cb5caa98Sdjl } 377cb5caa98Sdjl 3787c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 3797c478bd9Sstevel@tonic-gate args->returnval = (char *)0; 380cb5caa98Sdjl args->returnlen = 0; 381cb5caa98Sdjl hp = (struct hostent *)args->buf.result; 382cb5caa98Sdjl buffer = args->buf.buffer; 383cb5caa98Sdjl buflen = args->buf.buflen; 384cb5caa98Sdjl h_namelen = 0; 385cb5caa98Sdjl h_name = NULL; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate for (;;) { 3887c478bd9Sstevel@tonic-gate char *instr = be->buf; 3897c478bd9Sstevel@tonic-gate int linelen; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3927c478bd9Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3937c478bd9Sstevel@tonic-gate break; /* EOF */ 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 3987c478bd9Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 3997c478bd9Sstevel@tonic-gate * already matched entry doesn't share a canonical name 4007c478bd9Sstevel@tonic-gate * with the current one, bail. 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 4037c478bd9Sstevel@tonic-gate continue; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 4077c478bd9Sstevel@tonic-gate last = instr + linelen; 4087c478bd9Sstevel@tonic-gate *last-- = '\0'; 4097c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 4107c478bd9Sstevel@tonic-gate ; 4117c478bd9Sstevel@tonic-gate /* Ignore blank and comment lines */ 4127c478bd9Sstevel@tonic-gate if (*first == '\0') 4137c478bd9Sstevel@tonic-gate continue; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate while (isspace(*last)) 4167c478bd9Sstevel@tonic-gate --last; 4177c478bd9Sstevel@tonic-gate linelen = last - first + 1; 4187c478bd9Sstevel@tonic-gate if (first != instr) 4197c478bd9Sstevel@tonic-gate instr = first; 4207c478bd9Sstevel@tonic-gate 421cb5caa98Sdjl /* Bail out if the canonical name does not match */ 422cb5caa98Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 4237c478bd9Sstevel@tonic-gate continue; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 4287c478bd9Sstevel@tonic-gate */ 429cb5caa98Sdjl addrp = (type == AF_INET)? 430cb5caa98Sdjl (void *)&taddr[nhosts]: 431cb5caa98Sdjl (void *)&taddr6[nhosts]; 4327c478bd9Sstevel@tonic-gate 433cb5caa98Sdjl if (check_name(args, instr, linelen, 434cb5caa98Sdjl type, &namep, &namelen, 435cb5caa98Sdjl addrp, &i)) { 4367c478bd9Sstevel@tonic-gate 437cb5caa98Sdjl /* 438cb5caa98Sdjl * If we've already matched once and have a possible 439cb5caa98Sdjl * match on this line, copy the aliases where they're 440cb5caa98Sdjl * safe from being overwritten when we look at the 441cb5caa98Sdjl * next entry. They're saved as a string of blank 442cb5caa98Sdjl * separated names for the alias parser. On errors, 443cb5caa98Sdjl * we return failure whether or not we have already 444cb5caa98Sdjl * obtained a valid address. 445cb5caa98Sdjl */ 446cb5caa98Sdjl if (nhosts == 1 && hp) { 447cb5caa98Sdjl if (h_namelen + 1 > args->buf.buflen) { 448cb5caa98Sdjl args->erange = 1; 449cb5caa98Sdjl res = NSS_NOTFOUND; 4507c478bd9Sstevel@tonic-gate break; 451cb5caa98Sdjl } 452cb5caa98Sdjl abuf = (char *)malloc(args->buf.buflen); 453cb5caa98Sdjl if (abuf == NULL) { 454cb5caa98Sdjl res = NSS_UNAVAIL; 455cb5caa98Sdjl break; 456cb5caa98Sdjl } 457cb5caa98Sdjl abuf_start = abuf; 458cb5caa98Sdjl abuf_end = abuf_start + args->buf.buflen; 459cb5caa98Sdjl (void) memcpy(abuf, h_name, h_namelen); 460cb5caa98Sdjl abuf += h_namelen; 461cb5caa98Sdjl *abuf = '\0'; 462cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 4637c478bd9Sstevel@tonic-gate if (abuf == NULL) { 4647c478bd9Sstevel@tonic-gate args->erange = 1; 4657c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 4667c478bd9Sstevel@tonic-gate break; 4677c478bd9Sstevel@tonic-gate } 468cb5caa98Sdjl } 469cb5caa98Sdjl 470cb5caa98Sdjl if (hp != NULL) { 471cb5caa98Sdjl /* inside the application */ 472cb5caa98Sdjl parsestat = (*args->str2ent)(instr, linelen, 473cb5caa98Sdjl hp, buffer, buflen); 474cb5caa98Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 475cb5caa98Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 476cb5caa98Sdjl args->erange = 1; 477cb5caa98Sdjl (void) memset(buffer, 0, buflen); 478cb5caa98Sdjl continue; 479cb5caa98Sdjl } 480cb5caa98Sdjl } else { 481cb5caa98Sdjl /* inside nscd */ 482cb5caa98Sdjl int alen, cplen, erange = 0; 483cb5caa98Sdjl char *ap; 484cb5caa98Sdjl 485cb5caa98Sdjl /* Add alias to the first line if any */ 486cb5caa98Sdjl if (nhosts > 0) { 487cb5caa98Sdjl 488cb5caa98Sdjl /* get to the start of alias */ 489cb5caa98Sdjl ap = (char *)namep + namelen; 490cb5caa98Sdjl /* see if there's any alias */ 491cb5caa98Sdjl if (ap == instr + linelen) 492cb5caa98Sdjl alen = 0; 493cb5caa98Sdjl else 494cb5caa98Sdjl alen = linelen - (ap - instr); 495cb5caa98Sdjl if (alen + 1 >= buflen) 496cb5caa98Sdjl erange = 1; 497cb5caa98Sdjl if (erange == 0 && alen != 0) { 498cb5caa98Sdjl /* make room for the alias */ 499cb5caa98Sdjl if (alias_end != NULL) 500cb5caa98Sdjl (void) memmove(alias_end + 501cb5caa98Sdjl alen, alias_end, buffer - 502cb5caa98Sdjl alias_end); 503cb5caa98Sdjl /* copy in the alias */ 504cb5caa98Sdjl (void) memmove(alias_end, 505cb5caa98Sdjl ap, alen); 506cb5caa98Sdjl buffer += alen; 507cb5caa98Sdjl buflen -= alen; 508c70a8a3bSmichen args->returnlen += alen; 509cb5caa98Sdjl alias_end += alen; 510cb5caa98Sdjl } 511cb5caa98Sdjl 512cb5caa98Sdjl /* Add delimiter to the buffer */ 513cb5caa98Sdjl *buffer++ = '\n'; 514cb5caa98Sdjl buflen--; 515cb5caa98Sdjl args->returnlen++; 516cb5caa98Sdjl } 517cb5caa98Sdjl 518cb5caa98Sdjl /* copy just the addr if not first one */ 519cb5caa98Sdjl if (alias_end == NULL) 520cb5caa98Sdjl cplen = linelen; 521cb5caa98Sdjl else 522cb5caa98Sdjl cplen = namep - instr; 523cb5caa98Sdjl 524cb5caa98Sdjl if (cplen >= buflen || erange == 1) { 525cb5caa98Sdjl args->erange = 1; 526cb5caa98Sdjl if (nhosts > 0) { 527cb5caa98Sdjl *(--buffer) = '\0'; 528cb5caa98Sdjl buflen++; 529cb5caa98Sdjl args->returnlen--; 530cb5caa98Sdjl } 531cb5caa98Sdjl continue; 532cb5caa98Sdjl } 533cb5caa98Sdjl 534cb5caa98Sdjl (void) memcpy(buffer, instr, cplen); 535cb5caa98Sdjl /* Adjust buffer */ 536cb5caa98Sdjl buffer += cplen; 537cb5caa98Sdjl *buffer = '\0'; 538cb5caa98Sdjl buflen -= cplen; 539c70a8a3bSmichen args->returnlen += cplen; 540cb5caa98Sdjl if (alias_end == NULL) 541cb5caa98Sdjl alias_end = buffer; 542cb5caa98Sdjl } 543cb5caa98Sdjl 544cb5caa98Sdjl /* 545cb5caa98Sdjl * If this is the first one, save the canonical 546cb5caa98Sdjl * name for future matches and continue. 547cb5caa98Sdjl */ 548cb5caa98Sdjl if (++nhosts == 1) { 549cb5caa98Sdjl h_name = malloc(namelen + 1); 550cb5caa98Sdjl if (h_name == NULL) { 551cb5caa98Sdjl res = NSS_UNAVAIL; 552cb5caa98Sdjl break; 553cb5caa98Sdjl } 554cb5caa98Sdjl res = NSS_SUCCESS; 555cb5caa98Sdjl (void) memcpy(h_name, namep, namelen); 556cb5caa98Sdjl h_name[namelen] = '\0'; 557cb5caa98Sdjl h_namelen = namelen; 558cb5caa98Sdjl if (hp) 559cb5caa98Sdjl args->returnval = hp; 560cb5caa98Sdjl else 561cb5caa98Sdjl args->returnval = args->buf.buffer; 562cb5caa98Sdjl continue; 563cb5caa98Sdjl } 564cb5caa98Sdjl 565cb5caa98Sdjl 566cb5caa98Sdjl /* Extend the array */ 567cb5caa98Sdjl if (nhosts >= ntaddr) { 568cb5caa98Sdjl ntaddr *= 2; 569cb5caa98Sdjl if (type == AF_INET) { 570cb5caa98Sdjl addrp = realloc(taddr, 571cb5caa98Sdjl sizeof (*taddr) * ntaddr); 572cb5caa98Sdjl if (addrp == NULL) { 573cb5caa98Sdjl res = NSS_UNAVAIL; 574cb5caa98Sdjl break; 575cb5caa98Sdjl } 576cb5caa98Sdjl taddr = (in_addr_t *)addrp; 577cb5caa98Sdjl } else { 578cb5caa98Sdjl addrp = realloc(taddr6, 579cb5caa98Sdjl sizeof (*taddr6) * ntaddr); 580cb5caa98Sdjl if (addrp == NULL) { 581cb5caa98Sdjl res = NSS_UNAVAIL; 582cb5caa98Sdjl break; 583cb5caa98Sdjl } 584cb5caa98Sdjl taddr6 = (struct in6_addr *)addrp; 585cb5caa98Sdjl } 586cb5caa98Sdjl } 587cb5caa98Sdjl 588cb5caa98Sdjl /* 589cb5caa98Sdjl * For non-nscd, save aliases in a temporary buffer 590cb5caa98Sdjl * Don't have to do this for nscd as 'buffer' already 591cb5caa98Sdjl * contains the required data in the appropriate 592cb5caa98Sdjl * format 593cb5caa98Sdjl */ 594cb5caa98Sdjl if (hp) { 595cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 596cb5caa98Sdjl if (abuf == NULL) { 597cb5caa98Sdjl args->erange = 1; 598cb5caa98Sdjl res = NSS_NOTFOUND; 599cb5caa98Sdjl break; 600cb5caa98Sdjl } 601cb5caa98Sdjl } 602cb5caa98Sdjl } else if (namep && h_namelen == namelen && 603cb5caa98Sdjl strncasecmp(h_name, namep, namelen) == 0) { 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * This line didn't have the requested name but 6067c478bd9Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 6077c478bd9Sstevel@tonic-gate * has the same canonical name as the previous 6087c478bd9Sstevel@tonic-gate * line), so march on... 6097c478bd9Sstevel@tonic-gate */ 6107c478bd9Sstevel@tonic-gate continue; 6117c478bd9Sstevel@tonic-gate } else if (nhosts) { 612e37190e5Smichen continue; 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate 616cb5caa98Sdjl if (abuf && res == NSS_SUCCESS) { 617cb5caa98Sdjl 618cb5caa98Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 619cb5caa98Sdjl 6207c478bd9Sstevel@tonic-gate struct in_addr *addrp; 6217c478bd9Sstevel@tonic-gate struct in6_addr *addrp6; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (type == AF_INET) { 6247c478bd9Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 6257c478bd9Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 6267c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 6277c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6287c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 6297c478bd9Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 6307c478bd9Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 6317c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate } else { 6347c478bd9Sstevel@tonic-gate addrp6 = (struct in6_addr *) 6357c478bd9Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 6367c478bd9Sstevel@tonic-gate sizeof (*addrp6))); 6377c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 6387c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6397c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 6407c478bd9Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 641cb5caa98Sdjl (void) memcpy(addrp6, &taddr6[i], 6427c478bd9Sstevel@tonic-gate sizeof (struct in6_addr)); 6437c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 6487c478bd9Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 6497c478bd9Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 6507c478bd9Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 6517c478bd9Sstevel@tonic-gate if (hp->h_aliases == 0) { 6527c478bd9Sstevel@tonic-gate args->erange = 1; 653cb5caa98Sdjl res = NSS_NOTFOUND; 6547c478bd9Sstevel@tonic-gate } else { 6557c478bd9Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 6567c478bd9Sstevel@tonic-gate hp->h_aliases++; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate /* 6617c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 6627c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate if (!args->stayopen) 6657c478bd9Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 6667c478bd9Sstevel@tonic-gate 667cb5caa98Sdjl if (taddr) 668cb5caa98Sdjl free(taddr); 669cb5caa98Sdjl if (taddr6) 670cb5caa98Sdjl free(taddr6); 671cb5caa98Sdjl if (h_name) 672cb5caa98Sdjl free(h_name); 673cb5caa98Sdjl if (abuf_start) 674cb5caa98Sdjl free(abuf_start); 675cb5caa98Sdjl 6767c478bd9Sstevel@tonic-gate return (res); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate static char * 681cb5caa98Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 6827c478bd9Sstevel@tonic-gate { 6837c478bd9Sstevel@tonic-gate char **cp; 6847c478bd9Sstevel@tonic-gate size_t len; 6857c478bd9Sstevel@tonic-gate 686cb5caa98Sdjl if ((cp = hp->h_aliases) == NULL) 687cb5caa98Sdjl return (abuf); 688cb5caa98Sdjl 689cb5caa98Sdjl for (; *cp; cp++) { 6907c478bd9Sstevel@tonic-gate len = strlen(*cp); 6917c478bd9Sstevel@tonic-gate if (abuf+len+1 >= end) { 692cb5caa98Sdjl return (NULL); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate *abuf++ = ' '; 695cb5caa98Sdjl (void) memcpy(abuf, *cp, len); 696cb5caa98Sdjl abuf += len; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate *abuf = '\0'; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate return (abuf); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 7067c478bd9Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 7077c478bd9Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 7087c478bd9Sstevel@tonic-gate */ 7097c478bd9Sstevel@tonic-gate int 7107c478bd9Sstevel@tonic-gate __nss_files_2herrno(nsstat) 7117c478bd9Sstevel@tonic-gate nss_status_t nsstat; 7127c478bd9Sstevel@tonic-gate { 7137c478bd9Sstevel@tonic-gate switch (nsstat) { 7147c478bd9Sstevel@tonic-gate case NSS_SUCCESS: 7157c478bd9Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 7167c478bd9Sstevel@tonic-gate return (0); 7177c478bd9Sstevel@tonic-gate case NSS_NOTFOUND: 7187c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND); 7197c478bd9Sstevel@tonic-gate case NSS_TRYAGAIN: 7207c478bd9Sstevel@tonic-gate return (TRY_AGAIN); 7217c478bd9Sstevel@tonic-gate case NSS_UNAVAIL: 7227c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate /* anything else */ 7257c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 7267c478bd9Sstevel@tonic-gate } 727