10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2830Sdjl * Common Development and Distribution License (the "License"). 6*2830Sdjl * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * files/gethostent.c -- "files" backend for nsswitch "hosts" database 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <netdb.h> 310Sstevel@tonic-gate #include "files_common.h" 320Sstevel@tonic-gate #include <string.h> 330Sstevel@tonic-gate #include <strings.h> 340Sstevel@tonic-gate #include <stddef.h> 350Sstevel@tonic-gate #include <stdlib.h> 360Sstevel@tonic-gate #include <sys/types.h> 370Sstevel@tonic-gate #include <sys/socket.h> 380Sstevel@tonic-gate #include <netinet/in.h> 390Sstevel@tonic-gate #include <arpa/nameser.h> 40*2830Sdjl #include <arpa/inet.h> 410Sstevel@tonic-gate #include <ctype.h> 420Sstevel@tonic-gate 43*2830Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 44*2830Sdjl int, const char **, int *, void *, int *); 450Sstevel@tonic-gate static char *do_aliases(); 46*2830Sdjl static char *strcasestr(const char *as1, const char *as2); 470Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname(); 480Sstevel@tonic-gate int __nss_files_2herrno(); 49*2830Sdjl static int __nss_files_get_addr(int, const char *, int, 50*2830Sdjl void *, int, int *); 510Sstevel@tonic-gate 520Sstevel@tonic-gate static int 53*2830Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 54*2830Sdjl int type, const char **namep, int *namelen, 55*2830Sdjl void *addrp, int *addrsize) 560Sstevel@tonic-gate { 57*2830Sdjl const char *limit, *linep, *keyp, *addrstart; 58*2830Sdjl int v6flag = 0, addrlen; 59*2830Sdjl 60*2830Sdjl linep = line; 61*2830Sdjl limit = line + linelen; 620Sstevel@tonic-gate 63*2830Sdjl /* Address */ 64*2830Sdjl addrstart = linep; 65*2830Sdjl while (linep < limit && !isspace(*linep)) { 66*2830Sdjl if (*linep == ':') 67*2830Sdjl v6flag++; 68*2830Sdjl linep++; 690Sstevel@tonic-gate } 70*2830Sdjl addrlen = linep - addrstart; 71*2830Sdjl 72*2830Sdjl /* skip the delimiting spaces */ 73*2830Sdjl while (linep < limit && isspace(*linep)) 74*2830Sdjl linep++; 75*2830Sdjl 76*2830Sdjl /* Canonical name */ 77*2830Sdjl keyp = argp->key.name; 78*2830Sdjl *namep = linep; 79*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 80*2830Sdjl tolower(*keyp) == tolower(*linep)) { 81*2830Sdjl keyp++; 82*2830Sdjl linep++; 83*2830Sdjl } 84*2830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 85*2830Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 86*2830Sdjl addrp, v6flag, addrsize)) { 87*2830Sdjl *namelen = linep - *namep; 880Sstevel@tonic-gate return (1); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate } 91*2830Sdjl while (linep < limit && !isspace(*linep)) 92*2830Sdjl linep++; 93*2830Sdjl *namelen = linep - *namep; 94*2830Sdjl 95*2830Sdjl /* Aliases */ 96*2830Sdjl while (linep < limit) { 97*2830Sdjl /* skip the delimiting spaces */ 98*2830Sdjl while (linep < limit && isspace(*linep)) 99*2830Sdjl linep++; 100*2830Sdjl 101*2830Sdjl /* compare name (case insensitive) */ 102*2830Sdjl keyp = argp->key.name; 103*2830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 104*2830Sdjl tolower(*keyp) == tolower(*linep)) { 105*2830Sdjl keyp++; 106*2830Sdjl linep++; 107*2830Sdjl } 108*2830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 109*2830Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 110*2830Sdjl addrp, v6flag, addrsize)); 111*2830Sdjl 112*2830Sdjl /* skip remainder of alias, if any */ 113*2830Sdjl while (linep < limit && !isspace(*linep)) 114*2830Sdjl linep++; 115*2830Sdjl } 1160Sstevel@tonic-gate return (0); 117*2830Sdjl 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate static nss_status_t 1210Sstevel@tonic-gate getbyname(be, a) 1220Sstevel@tonic-gate files_backend_ptr_t be; 1230Sstevel@tonic-gate void *a; 1240Sstevel@tonic-gate { 1250Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1260Sstevel@tonic-gate nss_status_t res; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET); 1290Sstevel@tonic-gate if (res != NSS_SUCCESS) 1300Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 1310Sstevel@tonic-gate return (res); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 134*2830Sdjl static int 135*2830Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 136*2830Sdjl void *addrp, int v6flag, int *h_length) 137*2830Sdjl { 138*2830Sdjl struct in_addr addr_ipv4; 139*2830Sdjl struct in6_addr *addrpv6; 140*2830Sdjl in_addr_t *addrpv4; 141*2830Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 142*2830Sdjl 143*2830Sdjl if (addrlen >= sizeof (addrbuf)) 144*2830Sdjl return (0); 145*2830Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 146*2830Sdjl addrbuf[addrlen] = '\0'; 147*2830Sdjl 148*2830Sdjl if (af == AF_INET) { 149*2830Sdjl addrpv4 = (in_addr_t *)addrp; 150*2830Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 151*2830Sdjl return (0); 152*2830Sdjl *h_length = sizeof (in_addr_t); 153*2830Sdjl } else if (af == AF_INET6) { 154*2830Sdjl addrpv6 = (struct in6_addr *)addrp; 155*2830Sdjl if (v6flag) { 156*2830Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 157*2830Sdjl return (0); 158*2830Sdjl } else { 159*2830Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 160*2830Sdjl 0xffffffffU) 161*2830Sdjl return (0); 162*2830Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 163*2830Sdjl } 164*2830Sdjl *h_length = sizeof (struct in6_addr); 165*2830Sdjl } else { 166*2830Sdjl return (0); 167*2830Sdjl } 168*2830Sdjl return (1); 169*2830Sdjl } 170*2830Sdjl 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate int 173*2830Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 174*2830Sdjl int linelen) 1750Sstevel@tonic-gate { 176*2830Sdjl const char *limit, *linep, *addrstart; 177*2830Sdjl int v6flag = 0, addrlen, h_length; 178*2830Sdjl in_addr_t addr_ipv4; 179*2830Sdjl struct in6_addr addr_ipv6; 180*2830Sdjl char *h_addrp; 181*2830Sdjl 182*2830Sdjl /* Compare the address type */ 183*2830Sdjl if (argp->key.hostaddr.type != af) 184*2830Sdjl return (0); 1850Sstevel@tonic-gate 186*2830Sdjl /* Retrieve the address */ 187*2830Sdjl if (af == AF_INET) 188*2830Sdjl h_addrp = (char *)&addr_ipv4; 189*2830Sdjl else 190*2830Sdjl h_addrp = (char *)&addr_ipv6; 191*2830Sdjl linep = line; 192*2830Sdjl limit = line + linelen; 193*2830Sdjl addrstart = linep; 194*2830Sdjl while (linep < limit && !isspace(*linep)) { 195*2830Sdjl if (*linep == ':') 196*2830Sdjl v6flag++; 197*2830Sdjl linep++; 198*2830Sdjl } 199*2830Sdjl addrlen = linep - addrstart; 200*2830Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 201*2830Sdjl v6flag, &h_length) == 0) 202*2830Sdjl return (0); 203*2830Sdjl 204*2830Sdjl /* Compare the address */ 205*2830Sdjl return (h_length == argp->key.hostaddr.len && 206*2830Sdjl memcmp(h_addrp, argp->key.hostaddr.addr, 2070Sstevel@tonic-gate argp->key.hostaddr.len) == 0); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 210*2830Sdjl static int 211*2830Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 212*2830Sdjl { 213*2830Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 214*2830Sdjl } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate static nss_status_t 2170Sstevel@tonic-gate getbyaddr(be, a) 2180Sstevel@tonic-gate files_backend_ptr_t be; 2190Sstevel@tonic-gate void *a; 2200Sstevel@tonic-gate { 2210Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2220Sstevel@tonic-gate nss_status_t res; 2230Sstevel@tonic-gate 224*2830Sdjl res = _nss_files_XY_all(be, argp, 1, 0, check_addr); 2250Sstevel@tonic-gate if (res != NSS_SUCCESS) 2260Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 2270Sstevel@tonic-gate return (res); 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 2320Sstevel@tonic-gate _nss_files_destr, 2330Sstevel@tonic-gate _nss_files_endent, 2340Sstevel@tonic-gate _nss_files_setent, 2350Sstevel@tonic-gate _nss_files_getent_netdb, 2360Sstevel@tonic-gate getbyname, 2370Sstevel@tonic-gate getbyaddr, 2380Sstevel@tonic-gate }; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /*ARGSUSED*/ 2410Sstevel@tonic-gate nss_backend_t * 2420Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 2430Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate return (_nss_files_constr(host_ops, 2460Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 2470Sstevel@tonic-gate _PATH_HOSTS, 2480Sstevel@tonic-gate NSS_LINELEN_HOSTS, 2490Sstevel@tonic-gate NULL)); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate /* 2540Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 2550Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 2560Sstevel@tonic-gate */ 2570Sstevel@tonic-gate nss_status_t 2580Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 2590Sstevel@tonic-gate files_backend_ptr_t be; 2600Sstevel@tonic-gate nss_XbyY_args_t *args; 2610Sstevel@tonic-gate const char *filter; /* hint for name string */ 2620Sstevel@tonic-gate int type; 2630Sstevel@tonic-gate { 264*2830Sdjl nss_status_t res; 265*2830Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 266*2830Sdjl char *first, *last, *buffer; 267*2830Sdjl int parsestat, i, nhosts = 0, buflen; 268*2830Sdjl const char *namep; 269*2830Sdjl char *h_name; 270*2830Sdjl int h_namelen, namelen; 271*2830Sdjl struct hostent *hp; 272*2830Sdjl in_addr_t *taddr = NULL; 273*2830Sdjl struct in6_addr *taddr6 = NULL; 274*2830Sdjl size_t ntaddr; 275*2830Sdjl void *addrp; 276*2830Sdjl char *alias_end = NULL; 2770Sstevel@tonic-gate 278*2830Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 2790Sstevel@tonic-gate return (NSS_UNAVAIL); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (be->f == 0) { 2830Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 2840Sstevel@tonic-gate return (res); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 287*2830Sdjl ntaddr = MAXADDRS; 288*2830Sdjl if (type == AF_INET) { 289*2830Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 290*2830Sdjl if (taddr == NULL) 291*2830Sdjl return (NSS_UNAVAIL); 292*2830Sdjl } else { 293*2830Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 294*2830Sdjl if (taddr6 == NULL) 295*2830Sdjl return (NSS_UNAVAIL); 296*2830Sdjl } 297*2830Sdjl 2980Sstevel@tonic-gate res = NSS_NOTFOUND; 2990Sstevel@tonic-gate args->returnval = (char *)0; 300*2830Sdjl args->returnlen = 0; 301*2830Sdjl hp = (struct hostent *)args->buf.result; 302*2830Sdjl buffer = args->buf.buffer; 303*2830Sdjl buflen = args->buf.buflen; 304*2830Sdjl h_namelen = 0; 305*2830Sdjl h_name = NULL; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate for (;;) { 3080Sstevel@tonic-gate char *instr = be->buf; 3090Sstevel@tonic-gate int linelen; 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3120Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3130Sstevel@tonic-gate break; /* EOF */ 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* 3170Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 3180Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 3190Sstevel@tonic-gate * already matched entry doesn't share a canonical name 3200Sstevel@tonic-gate * with the current one, bail. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 3230Sstevel@tonic-gate continue; 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 3270Sstevel@tonic-gate last = instr + linelen; 3280Sstevel@tonic-gate *last-- = '\0'; 3290Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 3300Sstevel@tonic-gate ; 3310Sstevel@tonic-gate /* Ignore blank and comment lines */ 3320Sstevel@tonic-gate if (*first == '\0') 3330Sstevel@tonic-gate continue; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate while (isspace(*last)) 3360Sstevel@tonic-gate --last; 3370Sstevel@tonic-gate linelen = last - first + 1; 3380Sstevel@tonic-gate if (first != instr) 3390Sstevel@tonic-gate instr = first; 3400Sstevel@tonic-gate 341*2830Sdjl /* Bail out if the canonical name does not match */ 342*2830Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 3430Sstevel@tonic-gate continue; 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /* 3470Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 3480Sstevel@tonic-gate */ 349*2830Sdjl addrp = (type == AF_INET)? 350*2830Sdjl (void *)&taddr[nhosts]: 351*2830Sdjl (void *)&taddr6[nhosts]; 3520Sstevel@tonic-gate 353*2830Sdjl if (check_name(args, instr, linelen, 354*2830Sdjl type, &namep, &namelen, 355*2830Sdjl addrp, &i)) { 356*2830Sdjl 357*2830Sdjl /* 358*2830Sdjl * If we've already matched once and have a possible 359*2830Sdjl * match on this line, copy the aliases where they're 360*2830Sdjl * safe from being overwritten when we look at the 361*2830Sdjl * next entry. They're saved as a string of blank 362*2830Sdjl * separated names for the alias parser. On errors, 363*2830Sdjl * we return failure whether or not we have already 364*2830Sdjl * obtained a valid address. 365*2830Sdjl */ 366*2830Sdjl if (nhosts == 1 && hp) { 367*2830Sdjl if (h_namelen + 1 > args->buf.buflen) { 368*2830Sdjl args->erange = 1; 369*2830Sdjl res = NSS_NOTFOUND; 370*2830Sdjl break; 371*2830Sdjl } 372*2830Sdjl abuf = (char *)malloc(args->buf.buflen); 373*2830Sdjl if (abuf == NULL) { 374*2830Sdjl res = NSS_UNAVAIL; 375*2830Sdjl break; 376*2830Sdjl } 377*2830Sdjl abuf_start = abuf; 378*2830Sdjl abuf_end = abuf_start + args->buf.buflen; 379*2830Sdjl (void) memcpy(abuf, h_name, h_namelen); 380*2830Sdjl abuf += h_namelen; 381*2830Sdjl *abuf = '\0'; 382*2830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 383*2830Sdjl if (abuf == NULL) { 384*2830Sdjl args->erange = 1; 385*2830Sdjl res = NSS_NOTFOUND; 386*2830Sdjl break; 387*2830Sdjl } 388*2830Sdjl } 389*2830Sdjl 390*2830Sdjl if (hp != NULL) { 391*2830Sdjl /* inside the application */ 392*2830Sdjl parsestat = (*args->str2ent)(instr, linelen, 393*2830Sdjl hp, buffer, buflen); 394*2830Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 395*2830Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 396*2830Sdjl args->erange = 1; 397*2830Sdjl (void) memset(buffer, 0, buflen); 398*2830Sdjl continue; 399*2830Sdjl } 400*2830Sdjl } else { 401*2830Sdjl /* inside nscd */ 402*2830Sdjl int alen, cplen, erange = 0; 403*2830Sdjl char *ap; 404*2830Sdjl 405*2830Sdjl /* Add alias to the first line if any */ 406*2830Sdjl if (nhosts > 0) { 407*2830Sdjl 408*2830Sdjl /* get to the start of alias */ 409*2830Sdjl ap = (char *)namep + namelen; 410*2830Sdjl /* see if there's any alias */ 411*2830Sdjl if (ap == instr + linelen) 412*2830Sdjl alen = 0; 413*2830Sdjl else 414*2830Sdjl alen = linelen - (ap - instr); 415*2830Sdjl if (alen + 1 >= buflen) 416*2830Sdjl erange = 1; 417*2830Sdjl if (erange == 0 && alen != 0) { 418*2830Sdjl /* make room for the alias */ 419*2830Sdjl if (alias_end != NULL) 420*2830Sdjl (void) memmove(alias_end + 421*2830Sdjl alen, alias_end, buffer - 422*2830Sdjl alias_end); 423*2830Sdjl /* copy in the alias */ 424*2830Sdjl (void) memmove(alias_end, 425*2830Sdjl ap, alen); 426*2830Sdjl buffer += alen; 427*2830Sdjl buflen -= alen; 428*2830Sdjl alias_end += alen; 429*2830Sdjl } 430*2830Sdjl 431*2830Sdjl /* Add delimiter to the buffer */ 432*2830Sdjl *buffer++ = '\n'; 433*2830Sdjl buflen--; 434*2830Sdjl args->returnlen++; 435*2830Sdjl } 436*2830Sdjl 437*2830Sdjl /* copy just the addr if not first one */ 438*2830Sdjl if (alias_end == NULL) 439*2830Sdjl cplen = linelen; 440*2830Sdjl else 441*2830Sdjl cplen = namep - instr; 442*2830Sdjl 443*2830Sdjl if (cplen >= buflen || erange == 1) { 444*2830Sdjl args->erange = 1; 445*2830Sdjl if (nhosts > 0) { 446*2830Sdjl *(--buffer) = '\0'; 447*2830Sdjl buflen++; 448*2830Sdjl args->returnlen--; 449*2830Sdjl } 450*2830Sdjl continue; 451*2830Sdjl } 452*2830Sdjl 453*2830Sdjl (void) memcpy(buffer, instr, cplen); 454*2830Sdjl /* Adjust buffer */ 455*2830Sdjl buffer += cplen; 456*2830Sdjl *buffer = '\0'; 457*2830Sdjl buflen -= cplen; 458*2830Sdjl if (alias_end == NULL) 459*2830Sdjl alias_end = buffer; 460*2830Sdjl } 461*2830Sdjl 462*2830Sdjl args->returnlen += linelen; 463*2830Sdjl 464*2830Sdjl /* 465*2830Sdjl * If this is the first one, save the canonical 466*2830Sdjl * name for future matches and continue. 467*2830Sdjl */ 468*2830Sdjl if (++nhosts == 1) { 469*2830Sdjl h_name = malloc(namelen + 1); 470*2830Sdjl if (h_name == NULL) { 471*2830Sdjl res = NSS_UNAVAIL; 472*2830Sdjl break; 473*2830Sdjl } 474*2830Sdjl res = NSS_SUCCESS; 475*2830Sdjl (void) memcpy(h_name, namep, namelen); 476*2830Sdjl h_name[namelen] = '\0'; 477*2830Sdjl h_namelen = namelen; 478*2830Sdjl if (hp) 479*2830Sdjl args->returnval = hp; 480*2830Sdjl else 481*2830Sdjl args->returnval = args->buf.buffer; 482*2830Sdjl continue; 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate 486*2830Sdjl /* Extend the array */ 487*2830Sdjl if (nhosts >= ntaddr) { 488*2830Sdjl ntaddr *= 2; 489*2830Sdjl if (type == AF_INET) { 490*2830Sdjl addrp = realloc(taddr, 491*2830Sdjl sizeof (*taddr) * ntaddr); 492*2830Sdjl if (addrp == NULL) { 493*2830Sdjl res = NSS_UNAVAIL; 494*2830Sdjl break; 495*2830Sdjl } 496*2830Sdjl taddr = (in_addr_t *)addrp; 497*2830Sdjl } else { 498*2830Sdjl addrp = realloc(taddr6, 499*2830Sdjl sizeof (*taddr6) * ntaddr); 500*2830Sdjl if (addrp == NULL) { 501*2830Sdjl res = NSS_UNAVAIL; 502*2830Sdjl break; 503*2830Sdjl } 504*2830Sdjl taddr6 = (struct in6_addr *)addrp; 505*2830Sdjl } 5060Sstevel@tonic-gate } 507*2830Sdjl 508*2830Sdjl /* 509*2830Sdjl * For non-nscd, save aliases in a temporary buffer 510*2830Sdjl * Don't have to do this for nscd as 'buffer' already 511*2830Sdjl * contains the required data in the appropriate 512*2830Sdjl * format 513*2830Sdjl */ 514*2830Sdjl if (hp) { 515*2830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 516*2830Sdjl if (abuf == NULL) { 517*2830Sdjl args->erange = 1; 518*2830Sdjl res = NSS_NOTFOUND; 519*2830Sdjl break; 520*2830Sdjl } 5210Sstevel@tonic-gate } 522*2830Sdjl } else if (namep && h_namelen == namelen && 523*2830Sdjl strncasecmp(h_name, namep, namelen) == 0) { 5240Sstevel@tonic-gate /* 5250Sstevel@tonic-gate * This line didn't have the requested name but 5260Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 5270Sstevel@tonic-gate * has the same canonical name as the previous 5280Sstevel@tonic-gate * line), so march on... 5290Sstevel@tonic-gate */ 5300Sstevel@tonic-gate continue; 5310Sstevel@tonic-gate } else if (nhosts) { 5320Sstevel@tonic-gate break; 5330Sstevel@tonic-gate } 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 536*2830Sdjl if (abuf && res == NSS_SUCCESS) { 537*2830Sdjl 538*2830Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 539*2830Sdjl 5400Sstevel@tonic-gate struct in_addr *addrp; 5410Sstevel@tonic-gate struct in6_addr *addrp6; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate if (type == AF_INET) { 5440Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 5450Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 5460Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 5470Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 5480Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 5490Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 5500Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 5510Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate } else { 5540Sstevel@tonic-gate addrp6 = (struct in6_addr *) 5550Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 5560Sstevel@tonic-gate sizeof (*addrp6))); 5570Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 5580Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 5590Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 5600Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 561*2830Sdjl (void) memcpy(addrp6, &taddr6[i], 562*2830Sdjl sizeof (struct in6_addr)); 5630Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 5680Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 5690Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 5700Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 5710Sstevel@tonic-gate if (hp->h_aliases == 0) { 5720Sstevel@tonic-gate args->erange = 1; 573*2830Sdjl res = NSS_NOTFOUND; 5740Sstevel@tonic-gate } else { 5750Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 5760Sstevel@tonic-gate hp->h_aliases++; 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* 5810Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 5820Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 5830Sstevel@tonic-gate */ 5840Sstevel@tonic-gate if (!args->stayopen) 5850Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 5860Sstevel@tonic-gate 587*2830Sdjl if (taddr) 588*2830Sdjl free(taddr); 589*2830Sdjl if (taddr6) 590*2830Sdjl free(taddr6); 591*2830Sdjl if (h_name) 592*2830Sdjl free(h_name); 593*2830Sdjl if (abuf_start) 594*2830Sdjl free(abuf_start); 595*2830Sdjl 5960Sstevel@tonic-gate return (res); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * A case-insensitive version of strstr(). 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate static char * 603*2830Sdjl strcasestr(const char *as1, const char *as2) 6040Sstevel@tonic-gate { 6050Sstevel@tonic-gate int c2; 606*2830Sdjl register const char *tptr; 607*2830Sdjl register const char *s1, *s2; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate s1 = as1; 6100Sstevel@tonic-gate s2 = as2; 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 6130Sstevel@tonic-gate return (0); 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate while (*s1) { 6160Sstevel@tonic-gate if (tolower(*s1++) == tolower(c2 = *s2)) { 6170Sstevel@tonic-gate tptr = s1; 6180Sstevel@tonic-gate while ((tolower(c2 = *++s2) == 6190Sstevel@tonic-gate tolower(*s1++)) && c2 != 0) 6200Sstevel@tonic-gate ; 6210Sstevel@tonic-gate if (c2 == 0) 6220Sstevel@tonic-gate return ((char *)tptr - 1); 6230Sstevel@tonic-gate s1 = tptr; 6240Sstevel@tonic-gate s2 = as2; 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate return (0); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate static char * 632*2830Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 6330Sstevel@tonic-gate { 634*2830Sdjl char **cp; 635*2830Sdjl size_t len; 6360Sstevel@tonic-gate 637*2830Sdjl if ((cp = hp->h_aliases) == NULL) 638*2830Sdjl return (abuf); 6390Sstevel@tonic-gate 640*2830Sdjl for (; *cp; cp++) { 6410Sstevel@tonic-gate len = strlen(*cp); 6420Sstevel@tonic-gate if (abuf+len+1 >= end) { 643*2830Sdjl return (NULL); 6440Sstevel@tonic-gate } 645*2830Sdjl *abuf++ = ' '; 646*2830Sdjl (void) memcpy(abuf, *cp, len); 6470Sstevel@tonic-gate abuf += len; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate *abuf = '\0'; 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate return (abuf); 6520Sstevel@tonic-gate } 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate /* 6560Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 6570Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 6580Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 6590Sstevel@tonic-gate */ 6600Sstevel@tonic-gate int 6610Sstevel@tonic-gate __nss_files_2herrno(nsstat) 6620Sstevel@tonic-gate nss_status_t nsstat; 6630Sstevel@tonic-gate { 6640Sstevel@tonic-gate switch (nsstat) { 6650Sstevel@tonic-gate case NSS_SUCCESS: 6660Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 6670Sstevel@tonic-gate return (0); 6680Sstevel@tonic-gate case NSS_NOTFOUND: 6690Sstevel@tonic-gate return (HOST_NOT_FOUND); 6700Sstevel@tonic-gate case NSS_TRYAGAIN: 6710Sstevel@tonic-gate return (TRY_AGAIN); 6720Sstevel@tonic-gate case NSS_UNAVAIL: 6730Sstevel@tonic-gate return (NO_RECOVERY); 6740Sstevel@tonic-gate } 6750Sstevel@tonic-gate /* anything else */ 6760Sstevel@tonic-gate return (NO_RECOVERY); 6770Sstevel@tonic-gate } 678