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 5*cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6*cb5caa98Sdjl * 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 /* 22*cb5caa98Sdjl * 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> 40*cb5caa98Sdjl #include <arpa/inet.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate 43*cb5caa98Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 44*cb5caa98Sdjl int, const char **, int *, void *, int *); 457c478bd9Sstevel@tonic-gate static char *do_aliases(); 46*cb5caa98Sdjl 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(); 49*cb5caa98Sdjl static int __nss_files_get_addr(int, const char *, int, 50*cb5caa98Sdjl void *, int, int *); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static int 53*cb5caa98Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 54*cb5caa98Sdjl int type, const char **namep, int *namelen, 55*cb5caa98Sdjl void *addrp, int *addrsize) 567c478bd9Sstevel@tonic-gate { 57*cb5caa98Sdjl const char *limit, *linep, *keyp, *addrstart; 58*cb5caa98Sdjl int v6flag = 0, addrlen; 59*cb5caa98Sdjl 60*cb5caa98Sdjl linep = line; 61*cb5caa98Sdjl limit = line + linelen; 62*cb5caa98Sdjl 63*cb5caa98Sdjl /* Address */ 64*cb5caa98Sdjl addrstart = linep; 65*cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 66*cb5caa98Sdjl if (*linep == ':') 67*cb5caa98Sdjl v6flag++; 68*cb5caa98Sdjl linep++; 697c478bd9Sstevel@tonic-gate } 70*cb5caa98Sdjl addrlen = linep - addrstart; 71*cb5caa98Sdjl 72*cb5caa98Sdjl /* skip the delimiting spaces */ 73*cb5caa98Sdjl while (linep < limit && isspace(*linep)) 74*cb5caa98Sdjl linep++; 75*cb5caa98Sdjl 76*cb5caa98Sdjl /* Canonical name */ 77*cb5caa98Sdjl keyp = argp->key.name; 78*cb5caa98Sdjl *namep = linep; 79*cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 80*cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 81*cb5caa98Sdjl keyp++; 82*cb5caa98Sdjl linep++; 83*cb5caa98Sdjl } 84*cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 85*cb5caa98Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 86*cb5caa98Sdjl addrp, v6flag, addrsize)) { 87*cb5caa98Sdjl *namelen = linep - *namep; 887c478bd9Sstevel@tonic-gate return (1); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate } 91*cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 92*cb5caa98Sdjl linep++; 93*cb5caa98Sdjl *namelen = linep - *namep; 94*cb5caa98Sdjl 95*cb5caa98Sdjl /* Aliases */ 96*cb5caa98Sdjl while (linep < limit) { 97*cb5caa98Sdjl /* skip the delimiting spaces */ 98*cb5caa98Sdjl while (linep < limit && isspace(*linep)) 99*cb5caa98Sdjl linep++; 100*cb5caa98Sdjl 101*cb5caa98Sdjl /* compare name (case insensitive) */ 102*cb5caa98Sdjl keyp = argp->key.name; 103*cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && 104*cb5caa98Sdjl tolower(*keyp) == tolower(*linep)) { 105*cb5caa98Sdjl keyp++; 106*cb5caa98Sdjl linep++; 107*cb5caa98Sdjl } 108*cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 109*cb5caa98Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 110*cb5caa98Sdjl addrp, v6flag, addrsize)); 111*cb5caa98Sdjl 112*cb5caa98Sdjl /* skip remainder of alias, if any */ 113*cb5caa98Sdjl while (linep < limit && !isspace(*linep)) 114*cb5caa98Sdjl linep++; 115*cb5caa98Sdjl } 1167c478bd9Sstevel@tonic-gate return (0); 117*cb5caa98Sdjl 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 134*cb5caa98Sdjl static int 135*cb5caa98Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 136*cb5caa98Sdjl void *addrp, int v6flag, int *h_length) 137*cb5caa98Sdjl { 138*cb5caa98Sdjl struct in_addr addr_ipv4; 139*cb5caa98Sdjl struct in6_addr *addrpv6; 140*cb5caa98Sdjl in_addr_t *addrpv4; 141*cb5caa98Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 142*cb5caa98Sdjl 143*cb5caa98Sdjl if (addrlen >= sizeof (addrbuf)) 144*cb5caa98Sdjl return (0); 145*cb5caa98Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 146*cb5caa98Sdjl addrbuf[addrlen] = '\0'; 147*cb5caa98Sdjl 148*cb5caa98Sdjl if (af == AF_INET) { 149*cb5caa98Sdjl addrpv4 = (in_addr_t *)addrp; 150*cb5caa98Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 151*cb5caa98Sdjl return (0); 152*cb5caa98Sdjl *h_length = sizeof (in_addr_t); 153*cb5caa98Sdjl } else if (af == AF_INET6) { 154*cb5caa98Sdjl addrpv6 = (struct in6_addr *)addrp; 155*cb5caa98Sdjl if (v6flag) { 156*cb5caa98Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 157*cb5caa98Sdjl return (0); 158*cb5caa98Sdjl } else { 159*cb5caa98Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 160*cb5caa98Sdjl 0xffffffffU) 161*cb5caa98Sdjl return (0); 162*cb5caa98Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 163*cb5caa98Sdjl } 164*cb5caa98Sdjl *h_length = sizeof (struct in6_addr); 165*cb5caa98Sdjl } else { 166*cb5caa98Sdjl return (0); 167*cb5caa98Sdjl } 168*cb5caa98Sdjl return (1); 169*cb5caa98Sdjl } 170*cb5caa98Sdjl 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate int 173*cb5caa98Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 174*cb5caa98Sdjl int linelen) 1757c478bd9Sstevel@tonic-gate { 176*cb5caa98Sdjl const char *limit, *linep, *addrstart; 177*cb5caa98Sdjl int v6flag = 0, addrlen, h_length; 178*cb5caa98Sdjl in_addr_t addr_ipv4; 179*cb5caa98Sdjl struct in6_addr addr_ipv6; 180*cb5caa98Sdjl char *h_addrp; 181*cb5caa98Sdjl 182*cb5caa98Sdjl /* Compare the address type */ 183*cb5caa98Sdjl if (argp->key.hostaddr.type != af) 184*cb5caa98Sdjl return (0); 1857c478bd9Sstevel@tonic-gate 186*cb5caa98Sdjl /* Retrieve the address */ 187*cb5caa98Sdjl if (af == AF_INET) 188*cb5caa98Sdjl h_addrp = (char *)&addr_ipv4; 189*cb5caa98Sdjl else 190*cb5caa98Sdjl h_addrp = (char *)&addr_ipv6; 191*cb5caa98Sdjl linep = line; 192*cb5caa98Sdjl limit = line + linelen; 193*cb5caa98Sdjl addrstart = linep; 194*cb5caa98Sdjl while (linep < limit && !isspace(*linep)) { 195*cb5caa98Sdjl if (*linep == ':') 196*cb5caa98Sdjl v6flag++; 197*cb5caa98Sdjl linep++; 198*cb5caa98Sdjl } 199*cb5caa98Sdjl addrlen = linep - addrstart; 200*cb5caa98Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 201*cb5caa98Sdjl v6flag, &h_length) == 0) 202*cb5caa98Sdjl return (0); 203*cb5caa98Sdjl 204*cb5caa98Sdjl /* Compare the address */ 205*cb5caa98Sdjl return (h_length == argp->key.hostaddr.len && 206*cb5caa98Sdjl memcmp(h_addrp, argp->key.hostaddr.addr, 2077c478bd9Sstevel@tonic-gate argp->key.hostaddr.len) == 0); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 210*cb5caa98Sdjl static int 211*cb5caa98Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 212*cb5caa98Sdjl { 213*cb5caa98Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 214*cb5caa98Sdjl } 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 224*cb5caa98Sdjl 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 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 2327c478bd9Sstevel@tonic-gate _nss_files_destr, 2337c478bd9Sstevel@tonic-gate _nss_files_endent, 2347c478bd9Sstevel@tonic-gate _nss_files_setent, 2357c478bd9Sstevel@tonic-gate _nss_files_getent_netdb, 2367c478bd9Sstevel@tonic-gate getbyname, 2377c478bd9Sstevel@tonic-gate getbyaddr, 2387c478bd9Sstevel@tonic-gate }; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2417c478bd9Sstevel@tonic-gate nss_backend_t * 2427c478bd9Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 2437c478bd9Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate return (_nss_files_constr(host_ops, 2467c478bd9Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 2477c478bd9Sstevel@tonic-gate _PATH_HOSTS, 2487c478bd9Sstevel@tonic-gate NSS_LINELEN_HOSTS, 2497c478bd9Sstevel@tonic-gate NULL)); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 2557c478bd9Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate nss_status_t 2587c478bd9Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 2597c478bd9Sstevel@tonic-gate files_backend_ptr_t be; 2607c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args; 2617c478bd9Sstevel@tonic-gate const char *filter; /* hint for name string */ 2627c478bd9Sstevel@tonic-gate int type; 2637c478bd9Sstevel@tonic-gate { 264*cb5caa98Sdjl nss_status_t res; 265*cb5caa98Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 266*cb5caa98Sdjl char *first, *last, *buffer; 267*cb5caa98Sdjl int parsestat, i, nhosts = 0, buflen; 268*cb5caa98Sdjl const char *namep; 269*cb5caa98Sdjl char *h_name; 270*cb5caa98Sdjl int h_namelen, namelen; 271*cb5caa98Sdjl struct hostent *hp; 272*cb5caa98Sdjl in_addr_t *taddr = NULL; 273*cb5caa98Sdjl struct in6_addr *taddr6 = NULL; 274*cb5caa98Sdjl size_t ntaddr; 275*cb5caa98Sdjl void *addrp; 276*cb5caa98Sdjl char *alias_end = NULL; 277*cb5caa98Sdjl 278*cb5caa98Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 2797c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (be->f == 0) { 2837c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 2847c478bd9Sstevel@tonic-gate return (res); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 287*cb5caa98Sdjl ntaddr = MAXADDRS; 288*cb5caa98Sdjl if (type == AF_INET) { 289*cb5caa98Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 290*cb5caa98Sdjl if (taddr == NULL) 291*cb5caa98Sdjl return (NSS_UNAVAIL); 292*cb5caa98Sdjl } else { 293*cb5caa98Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 294*cb5caa98Sdjl if (taddr6 == NULL) 295*cb5caa98Sdjl return (NSS_UNAVAIL); 296*cb5caa98Sdjl } 297*cb5caa98Sdjl 2987c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND; 2997c478bd9Sstevel@tonic-gate args->returnval = (char *)0; 300*cb5caa98Sdjl args->returnlen = 0; 301*cb5caa98Sdjl hp = (struct hostent *)args->buf.result; 302*cb5caa98Sdjl buffer = args->buf.buffer; 303*cb5caa98Sdjl buflen = args->buf.buflen; 304*cb5caa98Sdjl h_namelen = 0; 305*cb5caa98Sdjl h_name = NULL; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate for (;;) { 3087c478bd9Sstevel@tonic-gate char *instr = be->buf; 3097c478bd9Sstevel@tonic-gate int linelen; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3127c478bd9Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3137c478bd9Sstevel@tonic-gate break; /* EOF */ 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 3187c478bd9Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 3197c478bd9Sstevel@tonic-gate * already matched entry doesn't share a canonical name 3207c478bd9Sstevel@tonic-gate * with the current one, bail. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 3237c478bd9Sstevel@tonic-gate continue; 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 3277c478bd9Sstevel@tonic-gate last = instr + linelen; 3287c478bd9Sstevel@tonic-gate *last-- = '\0'; 3297c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 3307c478bd9Sstevel@tonic-gate ; 3317c478bd9Sstevel@tonic-gate /* Ignore blank and comment lines */ 3327c478bd9Sstevel@tonic-gate if (*first == '\0') 3337c478bd9Sstevel@tonic-gate continue; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate while (isspace(*last)) 3367c478bd9Sstevel@tonic-gate --last; 3377c478bd9Sstevel@tonic-gate linelen = last - first + 1; 3387c478bd9Sstevel@tonic-gate if (first != instr) 3397c478bd9Sstevel@tonic-gate instr = first; 3407c478bd9Sstevel@tonic-gate 341*cb5caa98Sdjl /* Bail out if the canonical name does not match */ 342*cb5caa98Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 3437c478bd9Sstevel@tonic-gate continue; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* 3477c478bd9Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 3487c478bd9Sstevel@tonic-gate */ 349*cb5caa98Sdjl addrp = (type == AF_INET)? 350*cb5caa98Sdjl (void *)&taddr[nhosts]: 351*cb5caa98Sdjl (void *)&taddr6[nhosts]; 352*cb5caa98Sdjl 353*cb5caa98Sdjl if (check_name(args, instr, linelen, 354*cb5caa98Sdjl type, &namep, &namelen, 355*cb5caa98Sdjl addrp, &i)) { 3567c478bd9Sstevel@tonic-gate 357*cb5caa98Sdjl /* 358*cb5caa98Sdjl * If we've already matched once and have a possible 359*cb5caa98Sdjl * match on this line, copy the aliases where they're 360*cb5caa98Sdjl * safe from being overwritten when we look at the 361*cb5caa98Sdjl * next entry. They're saved as a string of blank 362*cb5caa98Sdjl * separated names for the alias parser. On errors, 363*cb5caa98Sdjl * we return failure whether or not we have already 364*cb5caa98Sdjl * obtained a valid address. 365*cb5caa98Sdjl */ 366*cb5caa98Sdjl if (nhosts == 1 && hp) { 367*cb5caa98Sdjl if (h_namelen + 1 > args->buf.buflen) { 368*cb5caa98Sdjl args->erange = 1; 369*cb5caa98Sdjl res = NSS_NOTFOUND; 370*cb5caa98Sdjl break; 371*cb5caa98Sdjl } 372*cb5caa98Sdjl abuf = (char *)malloc(args->buf.buflen); 373*cb5caa98Sdjl if (abuf == NULL) { 374*cb5caa98Sdjl res = NSS_UNAVAIL; 375*cb5caa98Sdjl break; 376*cb5caa98Sdjl } 377*cb5caa98Sdjl abuf_start = abuf; 378*cb5caa98Sdjl abuf_end = abuf_start + args->buf.buflen; 379*cb5caa98Sdjl (void) memcpy(abuf, h_name, h_namelen); 380*cb5caa98Sdjl abuf += h_namelen; 381*cb5caa98Sdjl *abuf = '\0'; 382*cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 383*cb5caa98Sdjl if (abuf == NULL) { 384*cb5caa98Sdjl args->erange = 1; 385*cb5caa98Sdjl res = NSS_NOTFOUND; 386*cb5caa98Sdjl break; 387*cb5caa98Sdjl } 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 390*cb5caa98Sdjl if (hp != NULL) { 391*cb5caa98Sdjl /* inside the application */ 392*cb5caa98Sdjl parsestat = (*args->str2ent)(instr, linelen, 393*cb5caa98Sdjl hp, buffer, buflen); 394*cb5caa98Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 395*cb5caa98Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 396*cb5caa98Sdjl args->erange = 1; 397*cb5caa98Sdjl (void) memset(buffer, 0, buflen); 398*cb5caa98Sdjl continue; 399*cb5caa98Sdjl } 400*cb5caa98Sdjl } else { 401*cb5caa98Sdjl /* inside nscd */ 402*cb5caa98Sdjl int alen, cplen, erange = 0; 403*cb5caa98Sdjl char *ap; 404*cb5caa98Sdjl 405*cb5caa98Sdjl /* Add alias to the first line if any */ 406*cb5caa98Sdjl if (nhosts > 0) { 407*cb5caa98Sdjl 408*cb5caa98Sdjl /* get to the start of alias */ 409*cb5caa98Sdjl ap = (char *)namep + namelen; 410*cb5caa98Sdjl /* see if there's any alias */ 411*cb5caa98Sdjl if (ap == instr + linelen) 412*cb5caa98Sdjl alen = 0; 413*cb5caa98Sdjl else 414*cb5caa98Sdjl alen = linelen - (ap - instr); 415*cb5caa98Sdjl if (alen + 1 >= buflen) 416*cb5caa98Sdjl erange = 1; 417*cb5caa98Sdjl if (erange == 0 && alen != 0) { 418*cb5caa98Sdjl /* make room for the alias */ 419*cb5caa98Sdjl if (alias_end != NULL) 420*cb5caa98Sdjl (void) memmove(alias_end + 421*cb5caa98Sdjl alen, alias_end, buffer - 422*cb5caa98Sdjl alias_end); 423*cb5caa98Sdjl /* copy in the alias */ 424*cb5caa98Sdjl (void) memmove(alias_end, 425*cb5caa98Sdjl ap, alen); 426*cb5caa98Sdjl buffer += alen; 427*cb5caa98Sdjl buflen -= alen; 428*cb5caa98Sdjl alias_end += alen; 429*cb5caa98Sdjl } 430*cb5caa98Sdjl 431*cb5caa98Sdjl /* Add delimiter to the buffer */ 432*cb5caa98Sdjl *buffer++ = '\n'; 433*cb5caa98Sdjl buflen--; 434*cb5caa98Sdjl args->returnlen++; 435*cb5caa98Sdjl } 436*cb5caa98Sdjl 437*cb5caa98Sdjl /* copy just the addr if not first one */ 438*cb5caa98Sdjl if (alias_end == NULL) 439*cb5caa98Sdjl cplen = linelen; 440*cb5caa98Sdjl else 441*cb5caa98Sdjl cplen = namep - instr; 442*cb5caa98Sdjl 443*cb5caa98Sdjl if (cplen >= buflen || erange == 1) { 444*cb5caa98Sdjl args->erange = 1; 445*cb5caa98Sdjl if (nhosts > 0) { 446*cb5caa98Sdjl *(--buffer) = '\0'; 447*cb5caa98Sdjl buflen++; 448*cb5caa98Sdjl args->returnlen--; 449*cb5caa98Sdjl } 450*cb5caa98Sdjl continue; 451*cb5caa98Sdjl } 452*cb5caa98Sdjl 453*cb5caa98Sdjl (void) memcpy(buffer, instr, cplen); 454*cb5caa98Sdjl /* Adjust buffer */ 455*cb5caa98Sdjl buffer += cplen; 456*cb5caa98Sdjl *buffer = '\0'; 457*cb5caa98Sdjl buflen -= cplen; 458*cb5caa98Sdjl if (alias_end == NULL) 459*cb5caa98Sdjl alias_end = buffer; 460*cb5caa98Sdjl } 461*cb5caa98Sdjl 462*cb5caa98Sdjl args->returnlen += linelen; 4637c478bd9Sstevel@tonic-gate 464*cb5caa98Sdjl /* 465*cb5caa98Sdjl * If this is the first one, save the canonical 466*cb5caa98Sdjl * name for future matches and continue. 467*cb5caa98Sdjl */ 468*cb5caa98Sdjl if (++nhosts == 1) { 469*cb5caa98Sdjl h_name = malloc(namelen + 1); 470*cb5caa98Sdjl if (h_name == NULL) { 471*cb5caa98Sdjl res = NSS_UNAVAIL; 472*cb5caa98Sdjl break; 473*cb5caa98Sdjl } 4747c478bd9Sstevel@tonic-gate res = NSS_SUCCESS; 475*cb5caa98Sdjl (void) memcpy(h_name, namep, namelen); 476*cb5caa98Sdjl h_name[namelen] = '\0'; 477*cb5caa98Sdjl h_namelen = namelen; 478*cb5caa98Sdjl if (hp) 479*cb5caa98Sdjl args->returnval = hp; 480*cb5caa98Sdjl else 481*cb5caa98Sdjl args->returnval = args->buf.buffer; 4827c478bd9Sstevel@tonic-gate continue; 4837c478bd9Sstevel@tonic-gate } 484*cb5caa98Sdjl 485*cb5caa98Sdjl 486*cb5caa98Sdjl /* Extend the array */ 487*cb5caa98Sdjl if (nhosts >= ntaddr) { 488*cb5caa98Sdjl ntaddr *= 2; 489*cb5caa98Sdjl if (type == AF_INET) { 490*cb5caa98Sdjl addrp = realloc(taddr, 491*cb5caa98Sdjl sizeof (*taddr) * ntaddr); 492*cb5caa98Sdjl if (addrp == NULL) { 493*cb5caa98Sdjl res = NSS_UNAVAIL; 494*cb5caa98Sdjl break; 495*cb5caa98Sdjl } 496*cb5caa98Sdjl taddr = (in_addr_t *)addrp; 497*cb5caa98Sdjl } else { 498*cb5caa98Sdjl addrp = realloc(taddr6, 499*cb5caa98Sdjl sizeof (*taddr6) * ntaddr); 500*cb5caa98Sdjl if (addrp == NULL) { 501*cb5caa98Sdjl res = NSS_UNAVAIL; 502*cb5caa98Sdjl break; 503*cb5caa98Sdjl } 504*cb5caa98Sdjl taddr6 = (struct in6_addr *)addrp; 505*cb5caa98Sdjl } 506*cb5caa98Sdjl } 507*cb5caa98Sdjl 508*cb5caa98Sdjl /* 509*cb5caa98Sdjl * For non-nscd, save aliases in a temporary buffer 510*cb5caa98Sdjl * Don't have to do this for nscd as 'buffer' already 511*cb5caa98Sdjl * contains the required data in the appropriate 512*cb5caa98Sdjl * format 513*cb5caa98Sdjl */ 514*cb5caa98Sdjl if (hp) { 515*cb5caa98Sdjl abuf = do_aliases(hp, abuf, abuf_end); 516*cb5caa98Sdjl if (abuf == NULL) { 517*cb5caa98Sdjl args->erange = 1; 518*cb5caa98Sdjl res = NSS_NOTFOUND; 519*cb5caa98Sdjl break; 520*cb5caa98Sdjl } 5217c478bd9Sstevel@tonic-gate } 522*cb5caa98Sdjl } else if (namep && h_namelen == namelen && 523*cb5caa98Sdjl strncasecmp(h_name, namep, namelen) == 0) { 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * This line didn't have the requested name but 5267c478bd9Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 5277c478bd9Sstevel@tonic-gate * has the same canonical name as the previous 5287c478bd9Sstevel@tonic-gate * line), so march on... 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate continue; 5317c478bd9Sstevel@tonic-gate } else if (nhosts) { 5327c478bd9Sstevel@tonic-gate break; 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 536*cb5caa98Sdjl if (abuf && res == NSS_SUCCESS) { 537*cb5caa98Sdjl 538*cb5caa98Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 539*cb5caa98Sdjl 5407c478bd9Sstevel@tonic-gate struct in_addr *addrp; 5417c478bd9Sstevel@tonic-gate struct in6_addr *addrp6; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (type == AF_INET) { 5447c478bd9Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 5457c478bd9Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 5467c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 5477c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 5487c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 5497c478bd9Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 5507c478bd9Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 5517c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate } else { 5547c478bd9Sstevel@tonic-gate addrp6 = (struct in6_addr *) 5557c478bd9Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 5567c478bd9Sstevel@tonic-gate sizeof (*addrp6))); 5577c478bd9Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 5587c478bd9Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 5597c478bd9Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 5607c478bd9Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 561*cb5caa98Sdjl (void) memcpy(addrp6, &taddr6[i], 562*cb5caa98Sdjl sizeof (struct in6_addr)); 5637c478bd9Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 5687c478bd9Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 5697c478bd9Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 5707c478bd9Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 5717c478bd9Sstevel@tonic-gate if (hp->h_aliases == 0) { 5727c478bd9Sstevel@tonic-gate args->erange = 1; 573*cb5caa98Sdjl res = NSS_NOTFOUND; 5747c478bd9Sstevel@tonic-gate } else { 5757c478bd9Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 5767c478bd9Sstevel@tonic-gate hp->h_aliases++; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* 5817c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 5827c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 5837c478bd9Sstevel@tonic-gate */ 5847c478bd9Sstevel@tonic-gate if (!args->stayopen) 5857c478bd9Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 5867c478bd9Sstevel@tonic-gate 587*cb5caa98Sdjl if (taddr) 588*cb5caa98Sdjl free(taddr); 589*cb5caa98Sdjl if (taddr6) 590*cb5caa98Sdjl free(taddr6); 591*cb5caa98Sdjl if (h_name) 592*cb5caa98Sdjl free(h_name); 593*cb5caa98Sdjl if (abuf_start) 594*cb5caa98Sdjl free(abuf_start); 595*cb5caa98Sdjl 5967c478bd9Sstevel@tonic-gate return (res); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * A case-insensitive version of strstr(). 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate static char * 603*cb5caa98Sdjl strcasestr(const char *as1, const char *as2) 6047c478bd9Sstevel@tonic-gate { 6057c478bd9Sstevel@tonic-gate int c2; 606*cb5caa98Sdjl register const char *tptr; 607*cb5caa98Sdjl register const char *s1, *s2; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate s1 = as1; 6107c478bd9Sstevel@tonic-gate s2 = as2; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 6137c478bd9Sstevel@tonic-gate return (0); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate while (*s1) { 6167c478bd9Sstevel@tonic-gate if (tolower(*s1++) == tolower(c2 = *s2)) { 6177c478bd9Sstevel@tonic-gate tptr = s1; 6187c478bd9Sstevel@tonic-gate while ((tolower(c2 = *++s2) == 6197c478bd9Sstevel@tonic-gate tolower(*s1++)) && c2 != 0) 6207c478bd9Sstevel@tonic-gate ; 6217c478bd9Sstevel@tonic-gate if (c2 == 0) 6227c478bd9Sstevel@tonic-gate return ((char *)tptr - 1); 6237c478bd9Sstevel@tonic-gate s1 = tptr; 6247c478bd9Sstevel@tonic-gate s2 = as2; 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate return (0); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate static char * 632*cb5caa98Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 6337c478bd9Sstevel@tonic-gate { 634*cb5caa98Sdjl char **cp; 635*cb5caa98Sdjl size_t len; 6367c478bd9Sstevel@tonic-gate 637*cb5caa98Sdjl if ((cp = hp->h_aliases) == NULL) 638*cb5caa98Sdjl return (abuf); 6397c478bd9Sstevel@tonic-gate 640*cb5caa98Sdjl for (; *cp; cp++) { 6417c478bd9Sstevel@tonic-gate len = strlen(*cp); 6427c478bd9Sstevel@tonic-gate if (abuf+len+1 >= end) { 643*cb5caa98Sdjl return (NULL); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate *abuf++ = ' '; 646*cb5caa98Sdjl (void) memcpy(abuf, *cp, len); 647*cb5caa98Sdjl abuf += len; 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate *abuf = '\0'; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate return (abuf); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* 6567c478bd9Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 6577c478bd9Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 6587c478bd9Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate int 6617c478bd9Sstevel@tonic-gate __nss_files_2herrno(nsstat) 6627c478bd9Sstevel@tonic-gate nss_status_t nsstat; 6637c478bd9Sstevel@tonic-gate { 6647c478bd9Sstevel@tonic-gate switch (nsstat) { 6657c478bd9Sstevel@tonic-gate case NSS_SUCCESS: 6667c478bd9Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 6677c478bd9Sstevel@tonic-gate return (0); 6687c478bd9Sstevel@tonic-gate case NSS_NOTFOUND: 6697c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND); 6707c478bd9Sstevel@tonic-gate case NSS_TRYAGAIN: 6717c478bd9Sstevel@tonic-gate return (TRY_AGAIN); 6727c478bd9Sstevel@tonic-gate case NSS_UNAVAIL: 6737c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate /* anything else */ 6767c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 6777c478bd9Sstevel@tonic-gate } 678