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 */ 21*6812Sraf 220Sstevel@tonic-gate /* 23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <netdb.h> 300Sstevel@tonic-gate #include "files_common.h" 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <strings.h> 330Sstevel@tonic-gate #include <stddef.h> 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #include <sys/types.h> 360Sstevel@tonic-gate #include <sys/socket.h> 370Sstevel@tonic-gate #include <netinet/in.h> 380Sstevel@tonic-gate #include <arpa/nameser.h> 392830Sdjl #include <arpa/inet.h> 400Sstevel@tonic-gate #include <ctype.h> 410Sstevel@tonic-gate 422830Sdjl static int check_name(nss_XbyY_args_t *, const char *, int, 432830Sdjl int, const char **, int *, void *, int *); 440Sstevel@tonic-gate static char *do_aliases(); 452830Sdjl static char *strcasestr(const char *as1, const char *as2); 460Sstevel@tonic-gate nss_status_t __nss_files_XY_hostbyname(); 470Sstevel@tonic-gate int __nss_files_2herrno(); 482830Sdjl static int __nss_files_get_addr(int, const char *, int, 492830Sdjl void *, int, int *); 500Sstevel@tonic-gate 510Sstevel@tonic-gate static int 522830Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen, 532830Sdjl int type, const char **namep, int *namelen, 542830Sdjl void *addrp, int *addrsize) 550Sstevel@tonic-gate { 562830Sdjl const char *limit, *linep, *keyp, *addrstart; 572830Sdjl int v6flag = 0, addrlen; 582830Sdjl 592830Sdjl linep = line; 602830Sdjl limit = line + linelen; 610Sstevel@tonic-gate 622830Sdjl /* Address */ 632830Sdjl addrstart = linep; 642830Sdjl while (linep < limit && !isspace(*linep)) { 652830Sdjl if (*linep == ':') 662830Sdjl v6flag++; 672830Sdjl linep++; 680Sstevel@tonic-gate } 692830Sdjl addrlen = linep - addrstart; 702830Sdjl 712830Sdjl /* skip the delimiting spaces */ 722830Sdjl while (linep < limit && isspace(*linep)) 732830Sdjl linep++; 742830Sdjl 752830Sdjl /* Canonical name */ 762830Sdjl keyp = argp->key.name; 772830Sdjl *namep = linep; 782830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 79*6812Sraf tolower(*keyp) == tolower(*linep)) { 802830Sdjl keyp++; 812830Sdjl linep++; 822830Sdjl } 832830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) { 842830Sdjl if (__nss_files_get_addr(type, addrstart, addrlen, 85*6812Sraf addrp, v6flag, addrsize)) { 862830Sdjl *namelen = linep - *namep; 870Sstevel@tonic-gate return (1); 880Sstevel@tonic-gate } 890Sstevel@tonic-gate } 902830Sdjl while (linep < limit && !isspace(*linep)) 912830Sdjl linep++; 922830Sdjl *namelen = linep - *namep; 932830Sdjl 942830Sdjl /* Aliases */ 952830Sdjl while (linep < limit) { 962830Sdjl /* skip the delimiting spaces */ 972830Sdjl while (linep < limit && isspace(*linep)) 982830Sdjl linep++; 992830Sdjl 1002830Sdjl /* compare name (case insensitive) */ 1012830Sdjl keyp = argp->key.name; 1022830Sdjl while (*keyp && linep < limit && !isspace(*linep) && 103*6812Sraf tolower(*keyp) == tolower(*linep)) { 1042830Sdjl keyp++; 1052830Sdjl linep++; 1062830Sdjl } 1072830Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep))) 1082830Sdjl return (__nss_files_get_addr(type, addrstart, addrlen, 109*6812Sraf addrp, v6flag, addrsize)); 1102830Sdjl 1112830Sdjl /* skip remainder of alias, if any */ 1122830Sdjl while (linep < limit && !isspace(*linep)) 1132830Sdjl linep++; 1142830Sdjl } 1150Sstevel@tonic-gate return (0); 1162830Sdjl 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate static nss_status_t 1200Sstevel@tonic-gate getbyname(be, a) 1210Sstevel@tonic-gate files_backend_ptr_t be; 1220Sstevel@tonic-gate void *a; 1230Sstevel@tonic-gate { 1240Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 1250Sstevel@tonic-gate nss_status_t res; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate res = __nss_files_XY_hostbyname(be, argp, argp->key.name, AF_INET); 1280Sstevel@tonic-gate if (res != NSS_SUCCESS) 1290Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 1300Sstevel@tonic-gate return (res); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1332830Sdjl static int 1342830Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen, 1352830Sdjl void *addrp, int v6flag, int *h_length) 1362830Sdjl { 1372830Sdjl struct in_addr addr_ipv4; 1382830Sdjl struct in6_addr *addrpv6; 1392830Sdjl in_addr_t *addrpv4; 1402830Sdjl char addrbuf[INET6_ADDRSTRLEN + 1]; 1412830Sdjl 1422830Sdjl if (addrlen >= sizeof (addrbuf)) 1432830Sdjl return (0); 1442830Sdjl (void) memcpy(addrbuf, addrstart, addrlen); 1452830Sdjl addrbuf[addrlen] = '\0'; 1462830Sdjl 1472830Sdjl if (af == AF_INET) { 1482830Sdjl addrpv4 = (in_addr_t *)addrp; 1492830Sdjl if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU) 1502830Sdjl return (0); 1512830Sdjl *h_length = sizeof (in_addr_t); 1522830Sdjl } else if (af == AF_INET6) { 1532830Sdjl addrpv6 = (struct in6_addr *)addrp; 1542830Sdjl if (v6flag) { 1552830Sdjl if (inet_pton(af, addrbuf, addrpv6) != 1) 1562830Sdjl return (0); 1572830Sdjl } else { 1582830Sdjl if ((addr_ipv4.s_addr = inet_addr(addrbuf)) == 159*6812Sraf 0xffffffffU) 1602830Sdjl return (0); 1612830Sdjl IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6); 1622830Sdjl } 1632830Sdjl *h_length = sizeof (struct in6_addr); 1642830Sdjl } else { 1652830Sdjl return (0); 1662830Sdjl } 1672830Sdjl return (1); 1682830Sdjl } 1692830Sdjl 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate int 1722830Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line, 1732830Sdjl int linelen) 1740Sstevel@tonic-gate { 1752830Sdjl const char *limit, *linep, *addrstart; 1762830Sdjl int v6flag = 0, addrlen, h_length; 1772830Sdjl in_addr_t addr_ipv4; 1782830Sdjl struct in6_addr addr_ipv6; 1792830Sdjl char *h_addrp; 1802830Sdjl 1812830Sdjl /* Compare the address type */ 1822830Sdjl if (argp->key.hostaddr.type != af) 1832830Sdjl return (0); 1840Sstevel@tonic-gate 1852830Sdjl /* Retrieve the address */ 1862830Sdjl if (af == AF_INET) 1872830Sdjl h_addrp = (char *)&addr_ipv4; 1882830Sdjl else 1892830Sdjl h_addrp = (char *)&addr_ipv6; 1902830Sdjl linep = line; 1912830Sdjl limit = line + linelen; 1922830Sdjl addrstart = linep; 1932830Sdjl while (linep < limit && !isspace(*linep)) { 1942830Sdjl if (*linep == ':') 1952830Sdjl v6flag++; 1962830Sdjl linep++; 1972830Sdjl } 1982830Sdjl addrlen = linep - addrstart; 1992830Sdjl if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp, 200*6812Sraf v6flag, &h_length) == 0) 2012830Sdjl return (0); 2022830Sdjl 2032830Sdjl /* Compare the address */ 2042830Sdjl return (h_length == argp->key.hostaddr.len && 205*6812Sraf memcmp(h_addrp, argp->key.hostaddr.addr, 206*6812Sraf argp->key.hostaddr.len) == 0); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2092830Sdjl static int 2102830Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen) 2112830Sdjl { 2122830Sdjl return (__nss_files_check_addr(AF_INET, argp, line, linelen)); 2132830Sdjl } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate static nss_status_t 2160Sstevel@tonic-gate getbyaddr(be, a) 2170Sstevel@tonic-gate files_backend_ptr_t be; 2180Sstevel@tonic-gate void *a; 2190Sstevel@tonic-gate { 2200Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 2210Sstevel@tonic-gate nss_status_t res; 2220Sstevel@tonic-gate 2232830Sdjl res = _nss_files_XY_all(be, argp, 1, 0, check_addr); 2240Sstevel@tonic-gate if (res != NSS_SUCCESS) 2250Sstevel@tonic-gate argp->h_errno = __nss_files_2herrno(res); 2260Sstevel@tonic-gate return (res); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2292883Schinlong /* 2302883Schinlong * filter_ipv6 2312883Schinlong * 2322883Schinlong * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address 2332883Schinlong * NSS_STR_PARSE_PARSE: An IPv6 address or other errors 2342883Schinlong */ 2352883Schinlong static int 2362883Schinlong filter_ipv6(char *instr, int lenstr) { 2372883Schinlong char *p, *addrstart, *limit, c; 2382883Schinlong int rc; 2392883Schinlong struct in_addr addr; 2402883Schinlong 2412883Schinlong p = instr; 2422883Schinlong limit = p + lenstr; 2432883Schinlong 2442883Schinlong addrstart = p; 2452883Schinlong 2462883Schinlong /* parse IP address */ 2472883Schinlong while (p < limit && !isspace(*p)) { 2482883Schinlong if (*p == ':') 2492883Schinlong /* IPv6 */ 2502883Schinlong return (NSS_STR_PARSE_PARSE); 2512883Schinlong else 2522883Schinlong p++; 2532883Schinlong } 2542883Schinlong 2552883Schinlong if (p >= limit) 2562883Schinlong /* invalid IP */ 2572883Schinlong return (NSS_STR_PARSE_PARSE); 2582883Schinlong 2592883Schinlong /* extract IP address */ 2602883Schinlong c = *p; 2612883Schinlong *p = '\0'; 262*6812Sraf rc = inet_aton(addrstart, &addr); 2632883Schinlong *p = c; 2642883Schinlong 2652883Schinlong if (rc == 0) 2662883Schinlong /* invalid IP */ 2672883Schinlong return (NSS_STR_PARSE_PARSE); 2682883Schinlong else 2692883Schinlong /* IPv4 */ 2702883Schinlong return (NSS_STR_PARSE_SUCCESS); 2712883Schinlong 2722883Schinlong 2732883Schinlong } 2742883Schinlong static nss_status_t 2752883Schinlong getent_hosts(files_backend_ptr_t be, void *a) 2762883Schinlong { 2772883Schinlong nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 2782883Schinlong nss_status_t rc = NSS_SUCCESS; 2792883Schinlong 2802883Schinlong if (args->buf.result != NULL) { 2812883Schinlong return (_nss_files_XY_all(be, args, 1, 0, 0)); 2822883Schinlong } else { 2832883Schinlong /* 2842883Schinlong * Called by nscd 2852883Schinlong */ 2862883Schinlong /*CONSTCOND*/ 2872883Schinlong while (1) { 2882883Schinlong rc = _nss_files_XY_all(be, args, 1, 0, 0); 2892883Schinlong /* 2902883Schinlong * NSS_NOTFOUND, end of file or other errors. 2912883Schinlong */ 2922883Schinlong if (rc != NSS_SUCCESS) 2932883Schinlong break; 2942883Schinlong /* 2952883Schinlong * /etc/hosts and /etc/ipnodes are merged and 2962883Schinlong * /etc/hosts can contain IPv6 addresses. 2972883Schinlong * These addresses have to be filtered. 2982883Schinlong */ 2992883Schinlong if (filter_ipv6(args->returnval, args->returnlen) 300*6812Sraf == NSS_STR_PARSE_SUCCESS) 3012883Schinlong break; 3022883Schinlong /* 3032883Schinlong * The entry is an IPv6 address or other errors. 3042883Schinlong * Skip it and continue to find next one. 3052883Schinlong */ 3062883Schinlong args->returnval = NULL; 3072883Schinlong args->returnlen = 0; 3082883Schinlong 3092883Schinlong } 3102883Schinlong return (rc); 3112883Schinlong } 3122883Schinlong 3132883Schinlong } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate static files_backend_op_t host_ops[] = { 3160Sstevel@tonic-gate _nss_files_destr, 3170Sstevel@tonic-gate _nss_files_endent, 3180Sstevel@tonic-gate _nss_files_setent, 3192883Schinlong getent_hosts, 3200Sstevel@tonic-gate getbyname, 3210Sstevel@tonic-gate getbyaddr, 3220Sstevel@tonic-gate }; 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /*ARGSUSED*/ 3250Sstevel@tonic-gate nss_backend_t * 3260Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3) 3270Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 3280Sstevel@tonic-gate { 3290Sstevel@tonic-gate return (_nss_files_constr(host_ops, 3300Sstevel@tonic-gate sizeof (host_ops) / sizeof (host_ops[0]), 3310Sstevel@tonic-gate _PATH_HOSTS, 3320Sstevel@tonic-gate NSS_LINELEN_HOSTS, 3330Sstevel@tonic-gate NULL)); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate /* 3380Sstevel@tonic-gate * XXX - this duplicates code from files_common.c because we need to keep 3390Sstevel@tonic-gate * going after we've found a match to satisfy the multihomed host case. 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate nss_status_t 3420Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type) 3430Sstevel@tonic-gate files_backend_ptr_t be; 3440Sstevel@tonic-gate nss_XbyY_args_t *args; 3450Sstevel@tonic-gate const char *filter; /* hint for name string */ 3460Sstevel@tonic-gate int type; 3470Sstevel@tonic-gate { 3482830Sdjl nss_status_t res; 3492830Sdjl char *abuf = NULL, *abuf_start = NULL, *abuf_end; 3502830Sdjl char *first, *last, *buffer; 3512830Sdjl int parsestat, i, nhosts = 0, buflen; 3522830Sdjl const char *namep; 3532830Sdjl char *h_name; 3542830Sdjl int h_namelen, namelen; 3552830Sdjl struct hostent *hp; 3562830Sdjl in_addr_t *taddr = NULL; 3572830Sdjl struct in6_addr *taddr6 = NULL; 3582830Sdjl size_t ntaddr; 3592830Sdjl void *addrp; 3602830Sdjl char *alias_end = NULL; 3610Sstevel@tonic-gate 3622830Sdjl if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) { 3630Sstevel@tonic-gate return (NSS_UNAVAIL); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate if (be->f == 0) { 3670Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) 3680Sstevel@tonic-gate return (res); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3712830Sdjl ntaddr = MAXADDRS; 3722830Sdjl if (type == AF_INET) { 3732830Sdjl taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr)); 3742830Sdjl if (taddr == NULL) 3752830Sdjl return (NSS_UNAVAIL); 3762830Sdjl } else { 3772830Sdjl taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6)); 3782830Sdjl if (taddr6 == NULL) 3792830Sdjl return (NSS_UNAVAIL); 3802830Sdjl } 3812830Sdjl 3820Sstevel@tonic-gate res = NSS_NOTFOUND; 3830Sstevel@tonic-gate args->returnval = (char *)0; 3842830Sdjl args->returnlen = 0; 3852830Sdjl hp = (struct hostent *)args->buf.result; 3862830Sdjl buffer = args->buf.buffer; 3872830Sdjl buflen = args->buf.buflen; 3882830Sdjl h_namelen = 0; 3892830Sdjl h_name = NULL; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate for (;;) { 3920Sstevel@tonic-gate char *instr = be->buf; 3930Sstevel@tonic-gate int linelen; 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, 3960Sstevel@tonic-gate instr, be->minbuf)) < 0) { 3970Sstevel@tonic-gate break; /* EOF */ 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * This check avoids a malloc()/free() for the common 4020Sstevel@tonic-gate * case. Also, if we're trying to match an alias and an 4030Sstevel@tonic-gate * already matched entry doesn't share a canonical name 4040Sstevel@tonic-gate * with the current one, bail. 4050Sstevel@tonic-gate */ 4060Sstevel@tonic-gate if (nhosts == 0 && strcasestr(instr, filter) == 0) { 4070Sstevel@tonic-gate continue; 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) 4110Sstevel@tonic-gate last = instr + linelen; 4120Sstevel@tonic-gate *last-- = '\0'; 4130Sstevel@tonic-gate for (first = instr; isspace(*first); first++) 4140Sstevel@tonic-gate ; 4150Sstevel@tonic-gate /* Ignore blank and comment lines */ 4160Sstevel@tonic-gate if (*first == '\0') 4170Sstevel@tonic-gate continue; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate while (isspace(*last)) 4200Sstevel@tonic-gate --last; 4210Sstevel@tonic-gate linelen = last - first + 1; 4220Sstevel@tonic-gate if (first != instr) 4230Sstevel@tonic-gate instr = first; 4240Sstevel@tonic-gate 4252830Sdjl /* Bail out if the canonical name does not match */ 4262830Sdjl if (nhosts && strcasestr(instr, h_name) == 0) { 4270Sstevel@tonic-gate continue; 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate /* 4310Sstevel@tonic-gate * Still need to check, strcasestr() above is just a hint. 4320Sstevel@tonic-gate */ 4332830Sdjl addrp = (type == AF_INET)? 4342830Sdjl (void *)&taddr[nhosts]: 4352830Sdjl (void *)&taddr6[nhosts]; 4360Sstevel@tonic-gate 4372830Sdjl if (check_name(args, instr, linelen, 4382830Sdjl type, &namep, &namelen, 4392830Sdjl addrp, &i)) { 4402830Sdjl 4412830Sdjl /* 4422830Sdjl * If we've already matched once and have a possible 4432830Sdjl * match on this line, copy the aliases where they're 4442830Sdjl * safe from being overwritten when we look at the 4452830Sdjl * next entry. They're saved as a string of blank 4462830Sdjl * separated names for the alias parser. On errors, 4472830Sdjl * we return failure whether or not we have already 4482830Sdjl * obtained a valid address. 4492830Sdjl */ 4502830Sdjl if (nhosts == 1 && hp) { 4512830Sdjl if (h_namelen + 1 > args->buf.buflen) { 4522830Sdjl args->erange = 1; 4532830Sdjl res = NSS_NOTFOUND; 4542830Sdjl break; 4552830Sdjl } 4562830Sdjl abuf = (char *)malloc(args->buf.buflen); 4572830Sdjl if (abuf == NULL) { 4582830Sdjl res = NSS_UNAVAIL; 4592830Sdjl break; 4602830Sdjl } 4612830Sdjl abuf_start = abuf; 4622830Sdjl abuf_end = abuf_start + args->buf.buflen; 4632830Sdjl (void) memcpy(abuf, h_name, h_namelen); 4642830Sdjl abuf += h_namelen; 4652830Sdjl *abuf = '\0'; 4662830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 4672830Sdjl if (abuf == NULL) { 4682830Sdjl args->erange = 1; 4692830Sdjl res = NSS_NOTFOUND; 4702830Sdjl break; 4712830Sdjl } 4722830Sdjl } 4732830Sdjl 4742830Sdjl if (hp != NULL) { 4752830Sdjl /* inside the application */ 4762830Sdjl parsestat = (*args->str2ent)(instr, linelen, 4772830Sdjl hp, buffer, buflen); 4782830Sdjl if (parsestat != NSS_STR_PARSE_SUCCESS) { 4792830Sdjl if (parsestat == NSS_STR_PARSE_ERANGE) 4802830Sdjl args->erange = 1; 4812830Sdjl (void) memset(buffer, 0, buflen); 4822830Sdjl continue; 4832830Sdjl } 4842830Sdjl } else { 4852830Sdjl /* inside nscd */ 4862830Sdjl int alen, cplen, erange = 0; 4872830Sdjl char *ap; 4882830Sdjl 4892830Sdjl /* Add alias to the first line if any */ 4902830Sdjl if (nhosts > 0) { 4912830Sdjl 4922830Sdjl /* get to the start of alias */ 4932830Sdjl ap = (char *)namep + namelen; 4942830Sdjl /* see if there's any alias */ 4952830Sdjl if (ap == instr + linelen) 4962830Sdjl alen = 0; 4972830Sdjl else 4982830Sdjl alen = linelen - (ap - instr); 4992830Sdjl if (alen + 1 >= buflen) 5002830Sdjl erange = 1; 5012830Sdjl if (erange == 0 && alen != 0) { 5022830Sdjl /* make room for the alias */ 5032830Sdjl if (alias_end != NULL) 5042830Sdjl (void) memmove(alias_end + 5052830Sdjl alen, alias_end, buffer - 5062830Sdjl alias_end); 5072830Sdjl /* copy in the alias */ 5082830Sdjl (void) memmove(alias_end, 5092830Sdjl ap, alen); 5102830Sdjl buffer += alen; 5112830Sdjl buflen -= alen; 5122924Smichen args->returnlen += alen; 5132830Sdjl alias_end += alen; 5142830Sdjl } 5152830Sdjl 5162830Sdjl /* Add delimiter to the buffer */ 5172830Sdjl *buffer++ = '\n'; 5182830Sdjl buflen--; 5192830Sdjl args->returnlen++; 5202830Sdjl } 5212830Sdjl 5222830Sdjl /* copy just the addr if not first one */ 5232830Sdjl if (alias_end == NULL) 5242830Sdjl cplen = linelen; 5252830Sdjl else 5262830Sdjl cplen = namep - instr; 5272830Sdjl 5282830Sdjl if (cplen >= buflen || erange == 1) { 5292830Sdjl args->erange = 1; 5302830Sdjl if (nhosts > 0) { 5312830Sdjl *(--buffer) = '\0'; 5322830Sdjl buflen++; 5332830Sdjl args->returnlen--; 5342830Sdjl } 5352830Sdjl continue; 5362830Sdjl } 5372830Sdjl 5382830Sdjl (void) memcpy(buffer, instr, cplen); 5392830Sdjl /* Adjust buffer */ 5402830Sdjl buffer += cplen; 5412830Sdjl *buffer = '\0'; 5422830Sdjl buflen -= cplen; 5432924Smichen args->returnlen += cplen; 5442830Sdjl if (alias_end == NULL) 5452830Sdjl alias_end = buffer; 5462830Sdjl } 5472830Sdjl 5482830Sdjl /* 5492830Sdjl * If this is the first one, save the canonical 5502830Sdjl * name for future matches and continue. 5512830Sdjl */ 5522830Sdjl if (++nhosts == 1) { 5532830Sdjl h_name = malloc(namelen + 1); 5542830Sdjl if (h_name == NULL) { 5552830Sdjl res = NSS_UNAVAIL; 5562830Sdjl break; 5572830Sdjl } 5582830Sdjl res = NSS_SUCCESS; 5592830Sdjl (void) memcpy(h_name, namep, namelen); 5602830Sdjl h_name[namelen] = '\0'; 5612830Sdjl h_namelen = namelen; 5622830Sdjl if (hp) 5632830Sdjl args->returnval = hp; 5642830Sdjl else 5652830Sdjl args->returnval = args->buf.buffer; 5662830Sdjl continue; 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate 5702830Sdjl /* Extend the array */ 5712830Sdjl if (nhosts >= ntaddr) { 5722830Sdjl ntaddr *= 2; 5732830Sdjl if (type == AF_INET) { 5742830Sdjl addrp = realloc(taddr, 5752830Sdjl sizeof (*taddr) * ntaddr); 5762830Sdjl if (addrp == NULL) { 5772830Sdjl res = NSS_UNAVAIL; 5782830Sdjl break; 5792830Sdjl } 5802830Sdjl taddr = (in_addr_t *)addrp; 5812830Sdjl } else { 5822830Sdjl addrp = realloc(taddr6, 5832830Sdjl sizeof (*taddr6) * ntaddr); 5842830Sdjl if (addrp == NULL) { 5852830Sdjl res = NSS_UNAVAIL; 5862830Sdjl break; 5872830Sdjl } 5882830Sdjl taddr6 = (struct in6_addr *)addrp; 5892830Sdjl } 5900Sstevel@tonic-gate } 5912830Sdjl 5922830Sdjl /* 5932830Sdjl * For non-nscd, save aliases in a temporary buffer 5942830Sdjl * Don't have to do this for nscd as 'buffer' already 5952830Sdjl * contains the required data in the appropriate 5962830Sdjl * format 5972830Sdjl */ 5982830Sdjl if (hp) { 5992830Sdjl abuf = do_aliases(hp, abuf, abuf_end); 6002830Sdjl if (abuf == NULL) { 6012830Sdjl args->erange = 1; 6022830Sdjl res = NSS_NOTFOUND; 6032830Sdjl break; 6042830Sdjl } 6050Sstevel@tonic-gate } 6062830Sdjl } else if (namep && h_namelen == namelen && 6072830Sdjl strncasecmp(h_name, namep, namelen) == 0) { 6080Sstevel@tonic-gate /* 6090Sstevel@tonic-gate * This line didn't have the requested name but 6100Sstevel@tonic-gate * is part of the same multihomed host (i.e. it 6110Sstevel@tonic-gate * has the same canonical name as the previous 6120Sstevel@tonic-gate * line), so march on... 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate continue; 6150Sstevel@tonic-gate } else if (nhosts) { 6163099Smichen continue; 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate 6202830Sdjl if (abuf && res == NSS_SUCCESS) { 6212830Sdjl 6222830Sdjl /* abuf != NULL implies hp and abuf_start != NULL */ 6232830Sdjl 6240Sstevel@tonic-gate struct in_addr *addrp; 6250Sstevel@tonic-gate struct in6_addr *addrp6; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate if (type == AF_INET) { 6280Sstevel@tonic-gate addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer + 6290Sstevel@tonic-gate args->buf.buflen, sizeof (*addrp))); 6300Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp - 6310Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6320Sstevel@tonic-gate (nhosts * sizeof (*addrp))), sizeof (char *))); 6330Sstevel@tonic-gate for (i = 0, --addrp; i < nhosts; i++, --addrp) { 6340Sstevel@tonic-gate (*(in_addr_t *)addrp) = taddr[i]; 6350Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp; 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate } else { 6380Sstevel@tonic-gate addrp6 = (struct in6_addr *) 6390Sstevel@tonic-gate (ROUND_DOWN(args->buf.buffer + args->buf.buflen, 6400Sstevel@tonic-gate sizeof (*addrp6))); 6410Sstevel@tonic-gate hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 - 6420Sstevel@tonic-gate ((nhosts + 1) * sizeof (char *) + 6430Sstevel@tonic-gate (nhosts * sizeof (*addrp6))), sizeof (char *))); 6440Sstevel@tonic-gate for (i = 0, --addrp6; i < nhosts; i++, --addrp6) { 6452830Sdjl (void) memcpy(addrp6, &taddr6[i], 6462830Sdjl sizeof (struct in6_addr)); 6470Sstevel@tonic-gate hp->h_addr_list[i] = (char *)addrp6; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate hp->h_addr_list[nhosts] = 0; 6520Sstevel@tonic-gate hp->h_aliases = _nss_netdb_aliases(abuf_start, 6530Sstevel@tonic-gate abuf - abuf_start, args->buf.buffer, 6540Sstevel@tonic-gate (char *)hp->h_addr_list - args->buf.buffer); 6550Sstevel@tonic-gate if (hp->h_aliases == 0) { 6560Sstevel@tonic-gate args->erange = 1; 6572830Sdjl res = NSS_NOTFOUND; 6580Sstevel@tonic-gate } else { 6590Sstevel@tonic-gate hp->h_name = hp->h_aliases[0]; 6600Sstevel@tonic-gate hp->h_aliases++; 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate /* 6650Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened 6660Sstevel@tonic-gate * file. Some applications may break if it is set to 1. 6670Sstevel@tonic-gate */ 6680Sstevel@tonic-gate if (!args->stayopen) 6690Sstevel@tonic-gate (void) _nss_files_endent(be, 0); 6700Sstevel@tonic-gate 6712830Sdjl if (taddr) 6722830Sdjl free(taddr); 6732830Sdjl if (taddr6) 6742830Sdjl free(taddr6); 6752830Sdjl if (h_name) 6762830Sdjl free(h_name); 6772830Sdjl if (abuf_start) 6782830Sdjl free(abuf_start); 6792830Sdjl 6800Sstevel@tonic-gate return (res); 6810Sstevel@tonic-gate } 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate /* 6840Sstevel@tonic-gate * A case-insensitive version of strstr(). 6850Sstevel@tonic-gate */ 6860Sstevel@tonic-gate static char * 6872830Sdjl strcasestr(const char *as1, const char *as2) 6880Sstevel@tonic-gate { 6890Sstevel@tonic-gate int c2; 6902830Sdjl register const char *tptr; 6912830Sdjl register const char *s1, *s2; 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate s1 = as1; 6940Sstevel@tonic-gate s2 = as2; 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 6970Sstevel@tonic-gate return (0); 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate while (*s1) { 7000Sstevel@tonic-gate if (tolower(*s1++) == tolower(c2 = *s2)) { 7010Sstevel@tonic-gate tptr = s1; 7020Sstevel@tonic-gate while ((tolower(c2 = *++s2) == 7030Sstevel@tonic-gate tolower(*s1++)) && c2 != 0) 7040Sstevel@tonic-gate ; 7050Sstevel@tonic-gate if (c2 == 0) 7060Sstevel@tonic-gate return ((char *)tptr - 1); 7070Sstevel@tonic-gate s1 = tptr; 7080Sstevel@tonic-gate s2 = as2; 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate return (0); 7120Sstevel@tonic-gate } 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate static char * 7162830Sdjl do_aliases(struct hostent *hp, char *abuf, char *end) 7170Sstevel@tonic-gate { 7182830Sdjl char **cp; 7192830Sdjl size_t len; 7200Sstevel@tonic-gate 7212830Sdjl if ((cp = hp->h_aliases) == NULL) 7222830Sdjl return (abuf); 7230Sstevel@tonic-gate 7242830Sdjl for (; *cp; cp++) { 7250Sstevel@tonic-gate len = strlen(*cp); 7260Sstevel@tonic-gate if (abuf+len+1 >= end) { 7272830Sdjl return (NULL); 7280Sstevel@tonic-gate } 7292830Sdjl *abuf++ = ' '; 7302830Sdjl (void) memcpy(abuf, *cp, len); 7310Sstevel@tonic-gate abuf += len; 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate *abuf = '\0'; 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate return (abuf); 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate /* 7400Sstevel@tonic-gate * This is a copy of a routine in libnsl/nss/netdir_inet.c. It is 7410Sstevel@tonic-gate * here because /etc/lib/nss_files.so.1 cannot call routines 7420Sstevel@tonic-gate * in libnsl. Care should be taken to keep the two copies in sync. 7430Sstevel@tonic-gate */ 7440Sstevel@tonic-gate int 7450Sstevel@tonic-gate __nss_files_2herrno(nsstat) 7460Sstevel@tonic-gate nss_status_t nsstat; 7470Sstevel@tonic-gate { 7480Sstevel@tonic-gate switch (nsstat) { 7490Sstevel@tonic-gate case NSS_SUCCESS: 7500Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 7510Sstevel@tonic-gate return (0); 7520Sstevel@tonic-gate case NSS_NOTFOUND: 7530Sstevel@tonic-gate return (HOST_NOT_FOUND); 7540Sstevel@tonic-gate case NSS_TRYAGAIN: 7550Sstevel@tonic-gate return (TRY_AGAIN); 7560Sstevel@tonic-gate case NSS_UNAVAIL: 7570Sstevel@tonic-gate return (NO_RECOVERY); 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate /* anything else */ 7600Sstevel@tonic-gate return (NO_RECOVERY); 7610Sstevel@tonic-gate } 762