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 52830Sdjl * Common Development and Distribution License (the "License"). 62830Sdjl * 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 /* 222830Sdjl * 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> 402830Sdjl #include <arpa/inet.h> 410Sstevel@tonic-gate #include <ctype.h> 420Sstevel@tonic-gate 432830Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 442830Sdjl int, const char **, int *, void *, int *); 450Sstevel@tonic-gate static char *do_aliases(); 462830Sdjl 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(); 492830Sdjl static int __nss_files_get_addr(int, const char *, int, 502830Sdjl void *, int, int *); 510Sstevel@tonic-gate 520Sstevel@tonic-gate static int 532830Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 542830Sdjl int type, const char **namep, int *namelen, 552830Sdjl void *addrp, int *addrsize) 560Sstevel@tonic-gate { 572830Sdjl const char *limit, *linep, *keyp, *addrstart; 582830Sdjl int v6flag = 0, addrlen; 592830Sdjl 602830Sdjl linep = line; 612830Sdjl limit = line + linelen; 620Sstevel@tonic-gate 632830Sdjl /* Address */ 642830Sdjl addrstart = linep; 652830Sdjl while (linep < limit && !isspace(*linep)) { 662830Sdjl if (*linep == ':') 672830Sdjl v6flag++; 682830Sdjl linep++; 690Sstevel@tonic-gate } 702830Sdjl addrlen = linep - addrstart; 712830Sdjl 722830Sdjl /* skip the delimiting spaces */ 732830Sdjl while (linep < limit && isspace(*linep)) 742830Sdjl linep++; 752830Sdjl 762830Sdjl /* Canonical name */ 772830Sdjl keyp = argp->key.name; 782830Sdjl *namep = linep; 792830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 802830Sdjl tolower(*keyp) == tolower(*linep)) { 812830Sdjl keyp++; 822830Sdjl linep++; 832830Sdjl } 842830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 852830Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 862830Sdjl addrp, v6flag, addrsize)) { 872830Sdjl *namelen = linep - *namep; 880Sstevel@tonic-gate return (1); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate } 912830Sdjl while (linep < limit && !isspace(*linep)) 922830Sdjl linep++; 932830Sdjl *namelen = linep - *namep; 942830Sdjl 952830Sdjl /* Aliases */ 962830Sdjl while (linep < limit) { 972830Sdjl /* skip the delimiting spaces */ 982830Sdjl while (linep < limit && isspace(*linep)) 992830Sdjl linep++; 1002830Sdjl 1012830Sdjl /* compare name (case insensitive) */ 1022830Sdjl keyp = argp->key.name; 1032830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 1042830Sdjl tolower(*keyp) == tolower(*linep)) { 1052830Sdjl keyp++; 1062830Sdjl linep++; 1072830Sdjl } 1082830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 1092830Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 1102830Sdjl addrp, v6flag, addrsize)); 1112830Sdjl 1122830Sdjl /* skip remainder of alias, if any */ 1132830Sdjl while (linep < limit && !isspace(*linep)) 1142830Sdjl linep++; 1152830Sdjl } 1160Sstevel@tonic-gate return (0); 1172830Sdjl 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 1342830Sdjl static int 1352830Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 1362830Sdjl void *addrp, int v6flag, int *h_length) 1372830Sdjl { 1382830Sdjl struct in_addr addr_ipv4; 1392830Sdjl struct in6_addr *addrpv6; 1402830Sdjl in_addr_t *addrpv4; 1412830Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 1422830Sdjl 1432830Sdjl if (addrlen >= sizeof (addrbuf)) 1442830Sdjl return (0); 1452830Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 1462830Sdjl addrbuf[addrlen] = '\0'; 1472830Sdjl 1482830Sdjl if (af == AF_INET) { 1492830Sdjl addrpv4 = (in_addr_t *)addrp; 1502830Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 1512830Sdjl return (0); 1522830Sdjl *h_length = sizeof (in_addr_t); 1532830Sdjl } else if (af == AF_INET6) { 1542830Sdjl addrpv6 = (struct in6_addr *)addrp; 1552830Sdjl if (v6flag) { 1562830Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 1572830Sdjl return (0); 1582830Sdjl } else { 1592830Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 1602830Sdjl 0xffffffffU) 1612830Sdjl return (0); 1622830Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 1632830Sdjl } 1642830Sdjl *h_length = sizeof (struct in6_addr); 1652830Sdjl } else { 1662830Sdjl return (0); 1672830Sdjl } 1682830Sdjl return (1); 1692830Sdjl } 1702830Sdjl 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate int 1732830Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 1742830Sdjl int linelen) 1750Sstevel@tonic-gate { 1762830Sdjl const char *limit, *linep, *addrstart; 1772830Sdjl int v6flag = 0, addrlen, h_length; 1782830Sdjl in_addr_t addr_ipv4; 1792830Sdjl struct in6_addr addr_ipv6; 1802830Sdjl char *h_addrp; 1812830Sdjl 1822830Sdjl /* Compare the address type */ 1832830Sdjl if (argp->key.hostaddr.type != af) 1842830Sdjl return (0); 1850Sstevel@tonic-gate 1862830Sdjl /* Retrieve the address */ 1872830Sdjl if (af == AF_INET) 1882830Sdjl h_addrp = (char *)&addr_ipv4; 1892830Sdjl else 1902830Sdjl h_addrp = (char *)&addr_ipv6; 1912830Sdjl linep = line; 1922830Sdjl limit = line + linelen; 1932830Sdjl addrstart = linep; 1942830Sdjl while (linep < limit && !isspace(*linep)) { 1952830Sdjl if (*linep == ':') 1962830Sdjl v6flag++; 1972830Sdjl linep++; 1982830Sdjl } 1992830Sdjl addrlen = linep - addrstart; 2002830Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 2012830Sdjl v6flag, &h_length) == 0) 2022830Sdjl return (0); 2032830Sdjl 2042830Sdjl /* Compare the address */ 2052830Sdjl return (h_length == argp->key.hostaddr.len && 2062830Sdjl memcmp(h_addrp, argp->key.hostaddr.addr, 2070Sstevel@tonic-gate argp->key.hostaddr.len) == 0); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2102830Sdjl static int 2112830Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 2122830Sdjl { 2132830Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 2142830Sdjl } 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 2242830Sdjl 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 2302883Schinlong int _inet_aton(const char *cp, struct in_addr *addr); 2312883Schinlong /* 2322883Schinlong * filter_ipv6 2332883Schinlong * 2342883Schinlong * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address 2352883Schinlong * NSS_STR_PARSE_PARSE: An IPv6 address or other errors 2362883Schinlong */ 2372883Schinlong static int 2382883Schinlong filter_ipv6(char *instr, int lenstr) { 2392883Schinlong char *p, *addrstart, *limit, c; 2402883Schinlong int rc; 2412883Schinlong struct in_addr addr; 2422883Schinlong 2432883Schinlong p = instr; 2442883Schinlong limit = p + lenstr; 2452883Schinlong 2462883Schinlong addrstart = p; 2472883Schinlong 2482883Schinlong /* parse IP address */ 2492883Schinlong while (p < limit && !isspace(*p)) { 2502883Schinlong if (*p == ':') 2512883Schinlong /* IPv6 */ 2522883Schinlong return (NSS_STR_PARSE_PARSE); 2532883Schinlong else 2542883Schinlong p++; 2552883Schinlong } 2562883Schinlong 2572883Schinlong if (p >= limit) 2582883Schinlong /* invalid IP */ 2592883Schinlong return (NSS_STR_PARSE_PARSE); 2602883Schinlong 2612883Schinlong /* extract IP address */ 2622883Schinlong c = *p; 2632883Schinlong *p = '\0'; 2642883Schinlong rc = _inet_aton(addrstart, &addr); 2652883Schinlong *p = c; 2662883Schinlong 2672883Schinlong if (rc == 0) 2682883Schinlong /* invalid IP */ 2692883Schinlong return (NSS_STR_PARSE_PARSE); 2702883Schinlong else 2712883Schinlong /* IPv4 */ 2722883Schinlong return (NSS_STR_PARSE_SUCCESS); 2732883Schinlong 2742883Schinlong 2752883Schinlong } 2762883Schinlong static nss_status_t 2772883Schinlong getent_hosts(files_backend_ptr_t be, void *a) 2782883Schinlong { 2792883Schinlong nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 2802883Schinlong nss_status_t rc = NSS_SUCCESS; 2812883Schinlong 2822883Schinlong if (args->buf.result != NULL) { 2832883Schinlong return (_nss_files_XY_all(be, args, 1, 0, 0)); 2842883Schinlong } else { 2852883Schinlong /* 2862883Schinlong * Called by nscd 2872883Schinlong */ 2882883Schinlong /*CONSTCOND*/ 2892883Schinlong while (1) { 2902883Schinlong rc = _nss_files_XY_all(be, args, 1, 0, 0); 2912883Schinlong /* 2922883Schinlong * NSS_NOTFOUND, end of file or other errors. 2932883Schinlong */ 2942883Schinlong if (rc != NSS_SUCCESS) 2952883Schinlong break; 2962883Schinlong /* 2972883Schinlong * /etc/hosts and /etc/ipnodes are merged and 2982883Schinlong * /etc/hosts can contain IPv6 addresses. 2992883Schinlong * These addresses have to be filtered. 3002883Schinlong */ 3012883Schinlong if (filter_ipv6(args->returnval, args->returnlen) 3022883Schinlong == NSS_STR_PARSE_SUCCESS) 3032883Schinlong break; 3042883Schinlong /* 3052883Schinlong * The entry is an IPv6 address or other errors. 3062883Schinlong * Skip it and continue to find next one. 3072883Schinlong */ 3082883Schinlong args->returnval = NULL; 3092883Schinlong args->returnlen = 0; 3102883Schinlong 3112883Schinlong } 3122883Schinlong return (rc); 3132883Schinlong } 3142883Schinlong 3152883Schinlong } 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 3180Sstevel@tonic-gate _nss_files_destr, 3190Sstevel@tonic-gate _nss_files_endent, 3200Sstevel@tonic-gate _nss_files_setent, 3212883Schinlong getent_hosts, 3220Sstevel@tonic-gate getbyname, 3230Sstevel@tonic-gate getbyaddr, 3240Sstevel@tonic-gate }; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /*ARGSUSED*/ 3270Sstevel@tonic-gate nss_backend_t * 3280Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 3290Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3300Sstevel@tonic-gate { 3310Sstevel@tonic-gate return (_nss_files_constr(host_ops, 3320Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 3330Sstevel@tonic-gate _PATH_HOSTS, 3340Sstevel@tonic-gate NSS_LINELEN_HOSTS, 3350Sstevel@tonic-gate NULL)); 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate /* 3400Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 3410Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate nss_status_t 3440Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 3450Sstevel@tonic-gate files_backend_ptr_t be; 3460Sstevel@tonic-gate nss_XbyY_args_t *args; 3470Sstevel@tonic-gate const char *filter; /* hint for name string */ 3480Sstevel@tonic-gate int type; 3490Sstevel@tonic-gate { 3502830Sdjl nss_status_t res; 3512830Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 3522830Sdjl char *first, *last, *buffer; 3532830Sdjl int parsestat, i, nhosts = 0, buflen; 3542830Sdjl const char *namep; 3552830Sdjl char *h_name; 3562830Sdjl int h_namelen, namelen; 3572830Sdjl struct hostent *hp; 3582830Sdjl in_addr_t *taddr = NULL; 3592830Sdjl struct in6_addr *taddr6 = NULL; 3602830Sdjl size_t ntaddr; 3612830Sdjl void *addrp; 3622830Sdjl char *alias_end = NULL; 3630Sstevel@tonic-gate 3642830Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 3650Sstevel@tonic-gate return (NSS_UNAVAIL); 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate if (be->f == 0) { 3690Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 3700Sstevel@tonic-gate return (res); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3732830Sdjl ntaddr = MAXADDRS; 3742830Sdjl if (type == AF_INET) { 3752830Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 3762830Sdjl if (taddr == NULL) 3772830Sdjl return (NSS_UNAVAIL); 3782830Sdjl } else { 3792830Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 3802830Sdjl if (taddr6 == NULL) 3812830Sdjl return (NSS_UNAVAIL); 3822830Sdjl } 3832830Sdjl 3840Sstevel@tonic-gate res = NSS_NOTFOUND; 3850Sstevel@tonic-gate args->returnval = (char *)0; 3862830Sdjl args->returnlen = 0; 3872830Sdjl hp = (struct hostent *)args->buf.result; 3882830Sdjl buffer = args->buf.buffer; 3892830Sdjl buflen = args->buf.buflen; 3902830Sdjl h_namelen = 0; 3912830Sdjl h_name = NULL; 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate for (;;) { 3940Sstevel@tonic-gate char *instr = be->buf; 3950Sstevel@tonic-gate int linelen; 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3980Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3990Sstevel@tonic-gate break; /* EOF */ 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate /* 4030Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 4040Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 4050Sstevel@tonic-gate * already matched entry doesn't share a canonical name 4060Sstevel@tonic-gate * with the current one, bail. 4070Sstevel@tonic-gate */ 4080Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 4090Sstevel@tonic-gate continue; 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 4130Sstevel@tonic-gate last = instr + linelen; 4140Sstevel@tonic-gate *last-- = '\0'; 4150Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 4160Sstevel@tonic-gate ; 4170Sstevel@tonic-gate /* Ignore blank and comment lines */ 4180Sstevel@tonic-gate if (*first == '\0') 4190Sstevel@tonic-gate continue; 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate while (isspace(*last)) 4220Sstevel@tonic-gate --last; 4230Sstevel@tonic-gate linelen = last - first + 1; 4240Sstevel@tonic-gate if (first != instr) 4250Sstevel@tonic-gate instr = first; 4260Sstevel@tonic-gate 4272830Sdjl /* Bail out if the canonical name does not match */ 4282830Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 4290Sstevel@tonic-gate continue; 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate /* 4330Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 4340Sstevel@tonic-gate */ 4352830Sdjl addrp = (type == AF_INET)? 4362830Sdjl (void *)&taddr[nhosts]: 4372830Sdjl (void *)&taddr6[nhosts]; 4380Sstevel@tonic-gate 4392830Sdjl if (check_name(args, instr, linelen, 4402830Sdjl type, &namep, &namelen, 4412830Sdjl addrp, &i)) { 4422830Sdjl 4432830Sdjl /* 4442830Sdjl * If we've already matched once and have a possible 4452830Sdjl * match on this line, copy the aliases where they're 4462830Sdjl * safe from being overwritten when we look at the 4472830Sdjl * next entry. They're saved as a string of blank 4482830Sdjl * separated names for the alias parser. On errors, 4492830Sdjl * we return failure whether or not we have already 4502830Sdjl * obtained a valid address. 4512830Sdjl */ 4522830Sdjl if (nhosts == 1 && hp) { 4532830Sdjl if (h_namelen + 1 > args->buf.buflen) { 4542830Sdjl args->erange = 1; 4552830Sdjl res = NSS_NOTFOUND; 4562830Sdjl break; 4572830Sdjl } 4582830Sdjl abuf = (char *)malloc(args->buf.buflen); 4592830Sdjl if (abuf == NULL) { 4602830Sdjl res = NSS_UNAVAIL; 4612830Sdjl break; 4622830Sdjl } 4632830Sdjl abuf_start = abuf; 4642830Sdjl abuf_end = abuf_start + args->buf.buflen; 4652830Sdjl (void) memcpy(abuf, h_name, h_namelen); 4662830Sdjl abuf += h_namelen; 4672830Sdjl *abuf = '\0'; 4682830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 4692830Sdjl if (abuf == NULL) { 4702830Sdjl args->erange = 1; 4712830Sdjl res = NSS_NOTFOUND; 4722830Sdjl break; 4732830Sdjl } 4742830Sdjl } 4752830Sdjl 4762830Sdjl if (hp != NULL) { 4772830Sdjl /* inside the application */ 4782830Sdjl parsestat = (*args->str2ent)(instr, linelen, 4792830Sdjl hp, buffer, buflen); 4802830Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 4812830Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 4822830Sdjl args->erange = 1; 4832830Sdjl (void) memset(buffer, 0, buflen); 4842830Sdjl continue; 4852830Sdjl } 4862830Sdjl } else { 4872830Sdjl /* inside nscd */ 4882830Sdjl int alen, cplen, erange = 0; 4892830Sdjl char *ap; 4902830Sdjl 4912830Sdjl /* Add alias to the first line if any */ 4922830Sdjl if (nhosts > 0) { 4932830Sdjl 4942830Sdjl /* get to the start of alias */ 4952830Sdjl ap = (char *)namep + namelen; 4962830Sdjl /* see if there's any alias */ 4972830Sdjl if (ap == instr + linelen) 4982830Sdjl alen = 0; 4992830Sdjl else 5002830Sdjl alen = linelen - (ap - instr); 5012830Sdjl if (alen + 1 >= buflen) 5022830Sdjl erange = 1; 5032830Sdjl if (erange == 0 && alen != 0) { 5042830Sdjl /* make room for the alias */ 5052830Sdjl if (alias_end != NULL) 5062830Sdjl (void) memmove(alias_end + 5072830Sdjl alen, alias_end, buffer - 5082830Sdjl alias_end); 5092830Sdjl /* copy in the alias */ 5102830Sdjl (void) memmove(alias_end, 5112830Sdjl ap, alen); 5122830Sdjl buffer += alen; 5132830Sdjl buflen -= alen; 514*2924Smichen args->returnlen += alen; 5152830Sdjl alias_end += alen; 5162830Sdjl } 5172830Sdjl 5182830Sdjl /* Add delimiter to the buffer */ 5192830Sdjl *buffer++ = '\n'; 5202830Sdjl buflen--; 5212830Sdjl args->returnlen++; 5222830Sdjl } 5232830Sdjl 5242830Sdjl /* copy just the addr if not first one */ 5252830Sdjl if (alias_end == NULL) 5262830Sdjl cplen = linelen; 5272830Sdjl else 5282830Sdjl cplen = namep - instr; 5292830Sdjl 5302830Sdjl if (cplen >= buflen || erange == 1) { 5312830Sdjl args->erange = 1; 5322830Sdjl if (nhosts > 0) { 5332830Sdjl *(--buffer) = '\0'; 5342830Sdjl buflen++; 5352830Sdjl args->returnlen--; 5362830Sdjl } 5372830Sdjl continue; 5382830Sdjl } 5392830Sdjl 5402830Sdjl (void) memcpy(buffer, instr, cplen); 5412830Sdjl /* Adjust buffer */ 5422830Sdjl buffer += cplen; 5432830Sdjl *buffer = '\0'; 5442830Sdjl buflen -= cplen; 545*2924Smichen args->returnlen += cplen; 5462830Sdjl if (alias_end == NULL) 5472830Sdjl alias_end = buffer; 5482830Sdjl } 5492830Sdjl 5502830Sdjl /* 5512830Sdjl * If this is the first one, save the canonical 5522830Sdjl * name for future matches and continue. 5532830Sdjl */ 5542830Sdjl if (++nhosts == 1) { 5552830Sdjl h_name = malloc(namelen + 1); 5562830Sdjl if (h_name == NULL) { 5572830Sdjl res = NSS_UNAVAIL; 5582830Sdjl break; 5592830Sdjl } 5602830Sdjl res = NSS_SUCCESS; 5612830Sdjl (void) memcpy(h_name, namep, namelen); 5622830Sdjl h_name[namelen] = '\0'; 5632830Sdjl h_namelen = namelen; 5642830Sdjl if (hp) 5652830Sdjl args->returnval = hp; 5662830Sdjl else 5672830Sdjl args->returnval = args->buf.buffer; 5682830Sdjl continue; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate 5722830Sdjl /* Extend the array */ 5732830Sdjl if (nhosts >= ntaddr) { 5742830Sdjl ntaddr *= 2; 5752830Sdjl if (type == AF_INET) { 5762830Sdjl addrp = realloc(taddr, 5772830Sdjl sizeof (*taddr) * ntaddr); 5782830Sdjl if (addrp == NULL) { 5792830Sdjl res = NSS_UNAVAIL; 5802830Sdjl break; 5812830Sdjl } 5822830Sdjl taddr = (in_addr_t *)addrp; 5832830Sdjl } else { 5842830Sdjl addrp = realloc(taddr6, 5852830Sdjl sizeof (*taddr6) * ntaddr); 5862830Sdjl if (addrp == NULL) { 5872830Sdjl res = NSS_UNAVAIL; 5882830Sdjl break; 5892830Sdjl } 5902830Sdjl taddr6 = (struct in6_addr *)addrp; 5912830Sdjl } 5920Sstevel@tonic-gate } 5932830Sdjl 5942830Sdjl /* 5952830Sdjl * For non-nscd, save aliases in a temporary buffer 5962830Sdjl * Don't have to do this for nscd as 'buffer' already 5972830Sdjl * contains the required data in the appropriate 5982830Sdjl * format 5992830Sdjl */ 6002830Sdjl if (hp) { 6012830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 6022830Sdjl if (abuf == NULL) { 6032830Sdjl args->erange = 1; 6042830Sdjl res = NSS_NOTFOUND; 6052830Sdjl break; 6062830Sdjl } 6070Sstevel@tonic-gate } 6082830Sdjl } else if (namep && h_namelen == namelen && 6092830Sdjl strncasecmp(h_name, namep, namelen) == 0) { 6100Sstevel@tonic-gate /* 6110Sstevel@tonic-gate * This line didn't have the requested name but 6120Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 6130Sstevel@tonic-gate * has the same canonical name as the previous 6140Sstevel@tonic-gate * line), so march on... 6150Sstevel@tonic-gate */ 6160Sstevel@tonic-gate continue; 6170Sstevel@tonic-gate } else if (nhosts) { 6180Sstevel@tonic-gate break; 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate } 6210Sstevel@tonic-gate 6222830Sdjl if (abuf && res == NSS_SUCCESS) { 6232830Sdjl 6242830Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 6252830Sdjl 6260Sstevel@tonic-gate struct in_addr *addrp; 6270Sstevel@tonic-gate struct in6_addr *addrp6; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate if (type == AF_INET) { 6300Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 6310Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 6320Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 6330Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6340Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 6350Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 6360Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 6370Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate } else { 6400Sstevel@tonic-gate addrp6 = (struct in6_addr *) 6410Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 6420Sstevel@tonic-gate sizeof (*addrp6))); 6430Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 6440Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6450Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 6460Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 6472830Sdjl (void) memcpy(addrp6, &taddr6[i], 6482830Sdjl sizeof (struct in6_addr)); 6490Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 6540Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 6550Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 6560Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 6570Sstevel@tonic-gate if (hp->h_aliases == 0) { 6580Sstevel@tonic-gate args->erange = 1; 6592830Sdjl res = NSS_NOTFOUND; 6600Sstevel@tonic-gate } else { 6610Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 6620Sstevel@tonic-gate hp->h_aliases++; 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* 6670Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 6680Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 6690Sstevel@tonic-gate */ 6700Sstevel@tonic-gate if (!args->stayopen) 6710Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 6720Sstevel@tonic-gate 6732830Sdjl if (taddr) 6742830Sdjl free(taddr); 6752830Sdjl if (taddr6) 6762830Sdjl free(taddr6); 6772830Sdjl if (h_name) 6782830Sdjl free(h_name); 6792830Sdjl if (abuf_start) 6802830Sdjl free(abuf_start); 6812830Sdjl 6820Sstevel@tonic-gate return (res); 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate /* 6860Sstevel@tonic-gate * A case-insensitive version of strstr(). 6870Sstevel@tonic-gate */ 6880Sstevel@tonic-gate static char * 6892830Sdjl strcasestr(const char *as1, const char *as2) 6900Sstevel@tonic-gate { 6910Sstevel@tonic-gate int c2; 6922830Sdjl register const char *tptr; 6932830Sdjl register const char *s1, *s2; 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate s1 = as1; 6960Sstevel@tonic-gate s2 = as2; 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 6990Sstevel@tonic-gate return (0); 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate while (*s1) { 7020Sstevel@tonic-gate if (tolower(*s1++) == tolower(c2 = *s2)) { 7030Sstevel@tonic-gate tptr = s1; 7040Sstevel@tonic-gate while ((tolower(c2 = *++s2) == 7050Sstevel@tonic-gate tolower(*s1++)) && c2 != 0) 7060Sstevel@tonic-gate ; 7070Sstevel@tonic-gate if (c2 == 0) 7080Sstevel@tonic-gate return ((char *)tptr - 1); 7090Sstevel@tonic-gate s1 = tptr; 7100Sstevel@tonic-gate s2 = as2; 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate } 7130Sstevel@tonic-gate return (0); 7140Sstevel@tonic-gate } 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate static char * 7182830Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 7190Sstevel@tonic-gate { 7202830Sdjl char **cp; 7212830Sdjl size_t len; 7220Sstevel@tonic-gate 7232830Sdjl if ((cp = hp->h_aliases) == NULL) 7242830Sdjl return (abuf); 7250Sstevel@tonic-gate 7262830Sdjl for (; *cp; cp++) { 7270Sstevel@tonic-gate len = strlen(*cp); 7280Sstevel@tonic-gate if (abuf+len+1 >= end) { 7292830Sdjl return (NULL); 7300Sstevel@tonic-gate } 7312830Sdjl *abuf++ = ' '; 7322830Sdjl (void) memcpy(abuf, *cp, len); 7330Sstevel@tonic-gate abuf += len; 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate *abuf = '\0'; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate return (abuf); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate /* 7420Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 7430Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 7440Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 7450Sstevel@tonic-gate */ 7460Sstevel@tonic-gate int 7470Sstevel@tonic-gate __nss_files_2herrno(nsstat) 7480Sstevel@tonic-gate nss_status_t nsstat; 7490Sstevel@tonic-gate { 7500Sstevel@tonic-gate switch (nsstat) { 7510Sstevel@tonic-gate case NSS_SUCCESS: 7520Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 7530Sstevel@tonic-gate return (0); 7540Sstevel@tonic-gate case NSS_NOTFOUND: 7550Sstevel@tonic-gate return (HOST_NOT_FOUND); 7560Sstevel@tonic-gate case NSS_TRYAGAIN: 7570Sstevel@tonic-gate return (TRY_AGAIN); 7580Sstevel@tonic-gate case NSS_UNAVAIL: 7590Sstevel@tonic-gate return (NO_RECOVERY); 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate /* anything else */ 7620Sstevel@tonic-gate return (NO_RECOVERY); 7630Sstevel@tonic-gate } 764