17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22cb5caa98Sdjl  * 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>
40cb5caa98Sdjl #include <arpa/inet.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate 
43cb5caa98Sdjl static int	check_name(nss_XbyY_args_t *, const char *, int,
44cb5caa98Sdjl 			int, const char **, int *, void *, int *);
457c478bd9Sstevel@tonic-gate static char *do_aliases();
46cb5caa98Sdjl 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();
49cb5caa98Sdjl static int	__nss_files_get_addr(int, const char *, int,
50cb5caa98Sdjl 			void *, int, int *);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate static int
53cb5caa98Sdjl check_name(nss_XbyY_args_t *argp, const char *line, int linelen,
54cb5caa98Sdjl 	int type, const char **namep, int *namelen,
55cb5caa98Sdjl 	void *addrp, int *addrsize)
567c478bd9Sstevel@tonic-gate {
57cb5caa98Sdjl 	const char	*limit, *linep, *keyp, *addrstart;
58cb5caa98Sdjl 	int		v6flag = 0, addrlen;
59cb5caa98Sdjl 
60cb5caa98Sdjl 	linep = line;
61cb5caa98Sdjl 	limit = line + linelen;
62cb5caa98Sdjl 
63cb5caa98Sdjl 	/* Address */
64cb5caa98Sdjl 	addrstart = linep;
65cb5caa98Sdjl 	while (linep < limit && !isspace(*linep)) {
66cb5caa98Sdjl 		if (*linep == ':')
67cb5caa98Sdjl 			v6flag++;
68cb5caa98Sdjl 		linep++;
697c478bd9Sstevel@tonic-gate 	}
70cb5caa98Sdjl 	addrlen = linep - addrstart;
71cb5caa98Sdjl 
72cb5caa98Sdjl 	/* skip the delimiting spaces */
73cb5caa98Sdjl 	while (linep < limit && isspace(*linep))
74cb5caa98Sdjl 		linep++;
75cb5caa98Sdjl 
76cb5caa98Sdjl 	/* Canonical name */
77cb5caa98Sdjl 	keyp = argp->key.name;
78cb5caa98Sdjl 	*namep = linep;
79cb5caa98Sdjl 	while (*keyp && linep < limit && !isspace(*linep) &&
80cb5caa98Sdjl 			tolower(*keyp) == tolower(*linep)) {
81cb5caa98Sdjl 		keyp++;
82cb5caa98Sdjl 		linep++;
83cb5caa98Sdjl 	}
84cb5caa98Sdjl 	if (*keyp == '\0' && (linep == limit || isspace(*linep))) {
85cb5caa98Sdjl 		if (__nss_files_get_addr(type, addrstart, addrlen,
86cb5caa98Sdjl 					addrp, v6flag, addrsize)) {
87cb5caa98Sdjl 			*namelen = linep - *namep;
887c478bd9Sstevel@tonic-gate 			return (1);
897c478bd9Sstevel@tonic-gate 		}
907c478bd9Sstevel@tonic-gate 	}
91cb5caa98Sdjl 	while (linep < limit && !isspace(*linep))
92cb5caa98Sdjl 		linep++;
93cb5caa98Sdjl 	*namelen = linep - *namep;
94cb5caa98Sdjl 
95cb5caa98Sdjl 	/* Aliases */
96cb5caa98Sdjl 	while (linep < limit) {
97cb5caa98Sdjl 		/* skip the delimiting spaces */
98cb5caa98Sdjl 		while (linep < limit && isspace(*linep))
99cb5caa98Sdjl 			linep++;
100cb5caa98Sdjl 
101cb5caa98Sdjl 		/* compare name (case insensitive) */
102cb5caa98Sdjl 		keyp = argp->key.name;
103cb5caa98Sdjl 		while (*keyp && linep < limit && !isspace(*linep) &&
104cb5caa98Sdjl 				tolower(*keyp) == tolower(*linep)) {
105cb5caa98Sdjl 			keyp++;
106cb5caa98Sdjl 			linep++;
107cb5caa98Sdjl 		}
108cb5caa98Sdjl 		if (*keyp == '\0' && (linep == limit || isspace(*linep)))
109cb5caa98Sdjl 			return (__nss_files_get_addr(type, addrstart, addrlen,
110cb5caa98Sdjl 					addrp, v6flag, addrsize));
111cb5caa98Sdjl 
112cb5caa98Sdjl 		/* skip remainder of alias, if any */
113cb5caa98Sdjl 		while (linep < limit && !isspace(*linep))
114cb5caa98Sdjl 			linep++;
115cb5caa98Sdjl 	}
1167c478bd9Sstevel@tonic-gate 	return (0);
117cb5caa98Sdjl 
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 
134cb5caa98Sdjl static int
135cb5caa98Sdjl __nss_files_get_addr(int af, const char *addrstart, int addrlen,
136cb5caa98Sdjl 	void *addrp, int v6flag, int *h_length)
137cb5caa98Sdjl {
138cb5caa98Sdjl 	struct in_addr	addr_ipv4;
139cb5caa98Sdjl 	struct in6_addr	*addrpv6;
140cb5caa98Sdjl 	in_addr_t	*addrpv4;
141cb5caa98Sdjl 	char		addrbuf[INET6_ADDRSTRLEN + 1];
142cb5caa98Sdjl 
143cb5caa98Sdjl 	if (addrlen >= sizeof (addrbuf))
144cb5caa98Sdjl 		return (0);
145cb5caa98Sdjl 	(void) memcpy(addrbuf, addrstart, addrlen);
146cb5caa98Sdjl 	addrbuf[addrlen] = '\0';
147cb5caa98Sdjl 
148cb5caa98Sdjl 	if (af == AF_INET) {
149cb5caa98Sdjl 		addrpv4 = (in_addr_t *)addrp;
150cb5caa98Sdjl 		if ((*addrpv4 = inet_addr(addrbuf)) == 0xffffffffU)
151cb5caa98Sdjl 			return (0);
152cb5caa98Sdjl 		*h_length = sizeof (in_addr_t);
153cb5caa98Sdjl 	} else if (af == AF_INET6) {
154cb5caa98Sdjl 		addrpv6 = (struct in6_addr *)addrp;
155cb5caa98Sdjl 		if (v6flag) {
156cb5caa98Sdjl 			if (inet_pton(af, addrbuf, addrpv6) != 1)
157cb5caa98Sdjl 				return (0);
158cb5caa98Sdjl 		} else {
159cb5caa98Sdjl 			if ((addr_ipv4.s_addr = inet_addr(addrbuf)) ==
160cb5caa98Sdjl 							0xffffffffU)
161cb5caa98Sdjl 				return (0);
162cb5caa98Sdjl 			IN6_INADDR_TO_V4MAPPED(&addr_ipv4, addrpv6);
163cb5caa98Sdjl 		}
164cb5caa98Sdjl 		*h_length = sizeof (struct in6_addr);
165cb5caa98Sdjl 	} else {
166cb5caa98Sdjl 		return (0);
167cb5caa98Sdjl 	}
168cb5caa98Sdjl 	return (1);
169cb5caa98Sdjl }
170cb5caa98Sdjl 
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
173cb5caa98Sdjl __nss_files_check_addr(int af, nss_XbyY_args_t *argp, const char *line,
174cb5caa98Sdjl 		int linelen)
1757c478bd9Sstevel@tonic-gate {
176cb5caa98Sdjl 	const char	*limit, *linep, *addrstart;
177cb5caa98Sdjl 	int		v6flag = 0, addrlen, h_length;
178cb5caa98Sdjl 	in_addr_t	addr_ipv4;
179cb5caa98Sdjl 	struct in6_addr	addr_ipv6;
180cb5caa98Sdjl 	char		*h_addrp;
181cb5caa98Sdjl 
182cb5caa98Sdjl 	/* Compare the address type */
183cb5caa98Sdjl 	if (argp->key.hostaddr.type != af)
184cb5caa98Sdjl 		return (0);
1857c478bd9Sstevel@tonic-gate 
186cb5caa98Sdjl 	/* Retrieve the address */
187cb5caa98Sdjl 	if (af == AF_INET)
188cb5caa98Sdjl 		h_addrp = (char *)&addr_ipv4;
189cb5caa98Sdjl 	else
190cb5caa98Sdjl 		h_addrp = (char *)&addr_ipv6;
191cb5caa98Sdjl 	linep = line;
192cb5caa98Sdjl 	limit = line + linelen;
193cb5caa98Sdjl 	addrstart = linep;
194cb5caa98Sdjl 	while (linep < limit && !isspace(*linep)) {
195cb5caa98Sdjl 		if (*linep == ':')
196cb5caa98Sdjl 			v6flag++;
197cb5caa98Sdjl 		linep++;
198cb5caa98Sdjl 	}
199cb5caa98Sdjl 	addrlen = linep - addrstart;
200cb5caa98Sdjl 	if (__nss_files_get_addr(af, addrstart, addrlen, h_addrp,
201cb5caa98Sdjl 			v6flag, &h_length) == 0)
202cb5caa98Sdjl 		return (0);
203cb5caa98Sdjl 
204cb5caa98Sdjl 	/* Compare the address */
205cb5caa98Sdjl 	return (h_length == argp->key.hostaddr.len &&
206cb5caa98Sdjl 		memcmp(h_addrp, argp->key.hostaddr.addr,
2077c478bd9Sstevel@tonic-gate 			argp->key.hostaddr.len) == 0);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
210cb5caa98Sdjl static int
211cb5caa98Sdjl check_addr(nss_XbyY_args_t *argp, const char *line, int linelen)
212cb5caa98Sdjl {
213cb5caa98Sdjl 	return (__nss_files_check_addr(AF_INET, argp, line, linelen));
214cb5caa98Sdjl }
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 
224cb5caa98Sdjl 	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 
230*c77e7dfdSchinlong int _inet_aton(const char *cp, struct in_addr *addr);
231*c77e7dfdSchinlong /*
232*c77e7dfdSchinlong  * filter_ipv6
233*c77e7dfdSchinlong  *
234*c77e7dfdSchinlong  * Return - NSS_STR_PARSE_SUCCESS: An IPv4 address
235*c77e7dfdSchinlong  *          NSS_STR_PARSE_PARSE: An IPv6 address or other errors
236*c77e7dfdSchinlong  */
237*c77e7dfdSchinlong static int
238*c77e7dfdSchinlong filter_ipv6(char *instr, int lenstr) {
239*c77e7dfdSchinlong 	char	*p, *addrstart, *limit, c;
240*c77e7dfdSchinlong 	int	rc;
241*c77e7dfdSchinlong 	struct in_addr	addr;
242*c77e7dfdSchinlong 
243*c77e7dfdSchinlong 	p = instr;
244*c77e7dfdSchinlong 	limit = p + lenstr;
245*c77e7dfdSchinlong 
246*c77e7dfdSchinlong 	addrstart = p;
247*c77e7dfdSchinlong 
248*c77e7dfdSchinlong 	/* parse IP address */
249*c77e7dfdSchinlong 	while (p < limit && !isspace(*p)) {
250*c77e7dfdSchinlong 		if (*p == ':')
251*c77e7dfdSchinlong 			/* IPv6 */
252*c77e7dfdSchinlong 			return (NSS_STR_PARSE_PARSE);
253*c77e7dfdSchinlong 		else
254*c77e7dfdSchinlong 			p++;
255*c77e7dfdSchinlong 	}
256*c77e7dfdSchinlong 
257*c77e7dfdSchinlong 	if (p >= limit)
258*c77e7dfdSchinlong 		/* invalid IP */
259*c77e7dfdSchinlong 		return (NSS_STR_PARSE_PARSE);
260*c77e7dfdSchinlong 
261*c77e7dfdSchinlong 	/* extract IP address */
262*c77e7dfdSchinlong 	c = *p;
263*c77e7dfdSchinlong 	*p = '\0';
264*c77e7dfdSchinlong 	rc = _inet_aton(addrstart, &addr);
265*c77e7dfdSchinlong 	*p = c;
266*c77e7dfdSchinlong 
267*c77e7dfdSchinlong 	if (rc == 0)
268*c77e7dfdSchinlong 		/* invalid IP */
269*c77e7dfdSchinlong 		return (NSS_STR_PARSE_PARSE);
270*c77e7dfdSchinlong 	else
271*c77e7dfdSchinlong 		/* IPv4 */
272*c77e7dfdSchinlong 		return (NSS_STR_PARSE_SUCCESS);
273*c77e7dfdSchinlong 
274*c77e7dfdSchinlong 
275*c77e7dfdSchinlong }
276*c77e7dfdSchinlong static nss_status_t
277*c77e7dfdSchinlong getent_hosts(files_backend_ptr_t be, void *a)
278*c77e7dfdSchinlong {
279*c77e7dfdSchinlong 	nss_XbyY_args_t	*args = (nss_XbyY_args_t *)a;
280*c77e7dfdSchinlong 	nss_status_t	rc = NSS_SUCCESS;
281*c77e7dfdSchinlong 
282*c77e7dfdSchinlong 	if (args->buf.result != NULL) {
283*c77e7dfdSchinlong 		return (_nss_files_XY_all(be, args, 1, 0, 0));
284*c77e7dfdSchinlong 	} else {
285*c77e7dfdSchinlong 		/*
286*c77e7dfdSchinlong 		 * Called by nscd
287*c77e7dfdSchinlong 		 */
288*c77e7dfdSchinlong 		/*CONSTCOND*/
289*c77e7dfdSchinlong 		while (1) {
290*c77e7dfdSchinlong 			rc = _nss_files_XY_all(be, args, 1, 0, 0);
291*c77e7dfdSchinlong 			/*
292*c77e7dfdSchinlong 			 * NSS_NOTFOUND, end of file or other errors.
293*c77e7dfdSchinlong 			 */
294*c77e7dfdSchinlong 			if (rc != NSS_SUCCESS)
295*c77e7dfdSchinlong 				break;
296*c77e7dfdSchinlong 			/*
297*c77e7dfdSchinlong 			 * /etc/hosts and /etc/ipnodes are merged and
298*c77e7dfdSchinlong 			 * /etc/hosts can contain IPv6 addresses.
299*c77e7dfdSchinlong 			 * These addresses have to be filtered.
300*c77e7dfdSchinlong 			 */
301*c77e7dfdSchinlong 			if (filter_ipv6(args->returnval, args->returnlen)
302*c77e7dfdSchinlong 					== NSS_STR_PARSE_SUCCESS)
303*c77e7dfdSchinlong 				break;
304*c77e7dfdSchinlong 			/*
305*c77e7dfdSchinlong 			 * The entry is an IPv6 address or other errors.
306*c77e7dfdSchinlong 			 * Skip it and continue to find next one.
307*c77e7dfdSchinlong 			 */
308*c77e7dfdSchinlong 			args->returnval = NULL;
309*c77e7dfdSchinlong 			args->returnlen = 0;
310*c77e7dfdSchinlong 
311*c77e7dfdSchinlong 		}
312*c77e7dfdSchinlong 		return (rc);
313*c77e7dfdSchinlong 	}
314*c77e7dfdSchinlong 
315*c77e7dfdSchinlong }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static files_backend_op_t host_ops[] = {
3187c478bd9Sstevel@tonic-gate 	_nss_files_destr,
3197c478bd9Sstevel@tonic-gate 	_nss_files_endent,
3207c478bd9Sstevel@tonic-gate 	_nss_files_setent,
321*c77e7dfdSchinlong 	getent_hosts,
3227c478bd9Sstevel@tonic-gate 	getbyname,
3237c478bd9Sstevel@tonic-gate 	getbyaddr,
3247c478bd9Sstevel@tonic-gate };
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3277c478bd9Sstevel@tonic-gate nss_backend_t *
3287c478bd9Sstevel@tonic-gate _nss_files_hosts_constr(dummy1, dummy2, dummy3)
3297c478bd9Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate 	return (_nss_files_constr(host_ops,
3327c478bd9Sstevel@tonic-gate 				sizeof (host_ops) / sizeof (host_ops[0]),
3337c478bd9Sstevel@tonic-gate 				_PATH_HOSTS,
3347c478bd9Sstevel@tonic-gate 				NSS_LINELEN_HOSTS,
3357c478bd9Sstevel@tonic-gate 				NULL));
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate  * XXX - this duplicates code from files_common.c because we need to keep
3417c478bd9Sstevel@tonic-gate  * going after we've found a match to satisfy the multihomed host case.
3427c478bd9Sstevel@tonic-gate  */
3437c478bd9Sstevel@tonic-gate nss_status_t
3447c478bd9Sstevel@tonic-gate __nss_files_XY_hostbyname(be, args, filter, type)
3457c478bd9Sstevel@tonic-gate 	files_backend_ptr_t be;
3467c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t *args;
3477c478bd9Sstevel@tonic-gate 	const char *filter;		/* hint for name string */
3487c478bd9Sstevel@tonic-gate 	int type;
3497c478bd9Sstevel@tonic-gate {
350cb5caa98Sdjl 	nss_status_t	res;
351cb5caa98Sdjl 	char		*abuf = NULL, *abuf_start = NULL, *abuf_end;
352cb5caa98Sdjl 	char		*first, *last, *buffer;
353cb5caa98Sdjl 	int		parsestat, i, nhosts = 0, buflen;
354cb5caa98Sdjl 	const char	*namep;
355cb5caa98Sdjl 	char		*h_name;
356cb5caa98Sdjl 	int		h_namelen, namelen;
357cb5caa98Sdjl 	struct hostent	*hp;
358cb5caa98Sdjl 	in_addr_t	*taddr = NULL;
359cb5caa98Sdjl 	struct in6_addr	*taddr6 = NULL;
360cb5caa98Sdjl 	size_t		ntaddr;
361cb5caa98Sdjl 	void		*addrp;
362cb5caa98Sdjl 	char		*alias_end = NULL;
363cb5caa98Sdjl 
364cb5caa98Sdjl 	if (be->buf == 0 && (be->buf = malloc(be->minbuf)) == 0) {
3657c478bd9Sstevel@tonic-gate 		return (NSS_UNAVAIL);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (be->f == 0) {
3697c478bd9Sstevel@tonic-gate 		if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS)
3707c478bd9Sstevel@tonic-gate 			return (res);
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
373cb5caa98Sdjl 	ntaddr = MAXADDRS;
374cb5caa98Sdjl 	if (type == AF_INET) {
375cb5caa98Sdjl 		taddr = (in_addr_t *)calloc(ntaddr, sizeof (*taddr));
376cb5caa98Sdjl 		if (taddr == NULL)
377cb5caa98Sdjl 			return (NSS_UNAVAIL);
378cb5caa98Sdjl 	} else {
379cb5caa98Sdjl 		taddr6 = (struct in6_addr *)calloc(ntaddr, sizeof (*taddr6));
380cb5caa98Sdjl 		if (taddr6 == NULL)
381cb5caa98Sdjl 			return (NSS_UNAVAIL);
382cb5caa98Sdjl 	}
383cb5caa98Sdjl 
3847c478bd9Sstevel@tonic-gate 	res = NSS_NOTFOUND;
3857c478bd9Sstevel@tonic-gate 	args->returnval = (char *)0;
386cb5caa98Sdjl 	args->returnlen = 0;
387cb5caa98Sdjl 	hp = (struct hostent *)args->buf.result;
388cb5caa98Sdjl 	buffer = args->buf.buffer;
389cb5caa98Sdjl 	buflen = args->buf.buflen;
390cb5caa98Sdjl 	h_namelen = 0;
391cb5caa98Sdjl 	h_name = NULL;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	for (;;) {
3947c478bd9Sstevel@tonic-gate 		char *instr = be->buf;
3957c478bd9Sstevel@tonic-gate 		int linelen;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		if ((linelen = _nss_files_read_line(be->f,
3987c478bd9Sstevel@tonic-gate 		    instr, be->minbuf)) < 0) {
3997c478bd9Sstevel@tonic-gate 			break;		/* EOF */
4007c478bd9Sstevel@tonic-gate 		}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 		/*
4037c478bd9Sstevel@tonic-gate 		 * This check avoids a malloc()/free() for the common
4047c478bd9Sstevel@tonic-gate 		 * case. Also, if we're trying to match an alias and an
4057c478bd9Sstevel@tonic-gate 		 * already matched entry doesn't share a canonical name
4067c478bd9Sstevel@tonic-gate 		 * with the current one, bail.
4077c478bd9Sstevel@tonic-gate 		 */
4087c478bd9Sstevel@tonic-gate 		if (nhosts == 0 && strcasestr(instr, filter) == 0) {
4097c478bd9Sstevel@tonic-gate 			continue;
4107c478bd9Sstevel@tonic-gate 		}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 		if ((last = strchr(instr, '#')) == 0)
4137c478bd9Sstevel@tonic-gate 			last = instr + linelen;
4147c478bd9Sstevel@tonic-gate 		*last-- = '\0';
4157c478bd9Sstevel@tonic-gate 		for (first = instr;  isspace(*first);  first++)
4167c478bd9Sstevel@tonic-gate 			;
4177c478bd9Sstevel@tonic-gate 		/* Ignore blank and comment lines */
4187c478bd9Sstevel@tonic-gate 		if (*first == '\0')
4197c478bd9Sstevel@tonic-gate 			continue;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 		while (isspace(*last))
4227c478bd9Sstevel@tonic-gate 			--last;
4237c478bd9Sstevel@tonic-gate 		linelen = last - first + 1;
4247c478bd9Sstevel@tonic-gate 		if (first != instr)
4257c478bd9Sstevel@tonic-gate 			instr = first;
4267c478bd9Sstevel@tonic-gate 
427cb5caa98Sdjl 		/* Bail out if the canonical name does not match */
428cb5caa98Sdjl 		if (nhosts && strcasestr(instr, h_name) == 0) {
4297c478bd9Sstevel@tonic-gate 			continue;
4307c478bd9Sstevel@tonic-gate 		}
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 		/*
4337c478bd9Sstevel@tonic-gate 		 * Still need to check, strcasestr() above is just a hint.
4347c478bd9Sstevel@tonic-gate 		 */
435cb5caa98Sdjl 		addrp = (type == AF_INET)?
436cb5caa98Sdjl 				(void *)&taddr[nhosts]:
437cb5caa98Sdjl 				(void *)&taddr6[nhosts];
438cb5caa98Sdjl 
439cb5caa98Sdjl 		if (check_name(args, instr, linelen,
440cb5caa98Sdjl 				type, &namep, &namelen,
441cb5caa98Sdjl 				addrp, &i)) {
4427c478bd9Sstevel@tonic-gate 
443cb5caa98Sdjl 			/*
444cb5caa98Sdjl 			 * If we've already matched once and have a possible
445cb5caa98Sdjl 			 * match on this line, copy the aliases where they're
446cb5caa98Sdjl 			 * safe from being overwritten when we look at the
447cb5caa98Sdjl 			 * next entry. They're saved as a string of blank
448cb5caa98Sdjl 			 * separated names for the alias parser. On errors,
449cb5caa98Sdjl 			 * we return failure whether or not we have already
450cb5caa98Sdjl 			 * obtained a valid address.
451cb5caa98Sdjl 			 */
452cb5caa98Sdjl 			if (nhosts == 1 && hp) {
453cb5caa98Sdjl 				if (h_namelen + 1 > args->buf.buflen) {
454cb5caa98Sdjl 					args->erange = 1;
455cb5caa98Sdjl 					res = NSS_NOTFOUND;
456cb5caa98Sdjl 					break;
457cb5caa98Sdjl 				}
458cb5caa98Sdjl 				abuf = (char *)malloc(args->buf.buflen);
459cb5caa98Sdjl 				if (abuf == NULL) {
460cb5caa98Sdjl 					res = NSS_UNAVAIL;
461cb5caa98Sdjl 					break;
462cb5caa98Sdjl 				}
463cb5caa98Sdjl 				abuf_start = abuf;
464cb5caa98Sdjl 				abuf_end = abuf_start + args->buf.buflen;
465cb5caa98Sdjl 				(void) memcpy(abuf, h_name, h_namelen);
466cb5caa98Sdjl 				abuf += h_namelen;
467cb5caa98Sdjl 				*abuf = '\0';
468cb5caa98Sdjl 				abuf = do_aliases(hp, abuf, abuf_end);
469cb5caa98Sdjl 				if (abuf == NULL) {
470cb5caa98Sdjl 					args->erange = 1;
471cb5caa98Sdjl 					res = NSS_NOTFOUND;
472cb5caa98Sdjl 					break;
473cb5caa98Sdjl 				}
4747c478bd9Sstevel@tonic-gate 			}
4757c478bd9Sstevel@tonic-gate 
476cb5caa98Sdjl 			if (hp != NULL) {
477cb5caa98Sdjl 				/* inside the application */
478cb5caa98Sdjl 				parsestat = (*args->str2ent)(instr, linelen,
479cb5caa98Sdjl 						hp, buffer, buflen);
480cb5caa98Sdjl 				if (parsestat != NSS_STR_PARSE_SUCCESS) {
481cb5caa98Sdjl 					if (parsestat == NSS_STR_PARSE_ERANGE)
482cb5caa98Sdjl 						args->erange = 1;
483cb5caa98Sdjl 					(void) memset(buffer, 0, buflen);
484cb5caa98Sdjl 					continue;
485cb5caa98Sdjl 				}
486cb5caa98Sdjl 			} else {
487cb5caa98Sdjl 				/* inside nscd */
488cb5caa98Sdjl 				int	alen, cplen, erange = 0;
489cb5caa98Sdjl 				char	*ap;
490cb5caa98Sdjl 
491cb5caa98Sdjl 				/* Add alias to the first line if any */
492cb5caa98Sdjl 				if (nhosts > 0) {
493cb5caa98Sdjl 
494cb5caa98Sdjl 					/* get to the start of alias */
495cb5caa98Sdjl 					ap = (char *)namep + namelen;
496cb5caa98Sdjl 					/* see if there's any alias */
497cb5caa98Sdjl 					if (ap == instr + linelen)
498cb5caa98Sdjl 						alen = 0;
499cb5caa98Sdjl 					else
500cb5caa98Sdjl 						alen = linelen - (ap - instr);
501cb5caa98Sdjl 					if (alen + 1 >= buflen)
502cb5caa98Sdjl 						erange  = 1;
503cb5caa98Sdjl 					if (erange == 0 && alen != 0) {
504cb5caa98Sdjl 						/* make room for the alias */
505cb5caa98Sdjl 						if (alias_end != NULL)
506cb5caa98Sdjl 						(void) memmove(alias_end +
507cb5caa98Sdjl 						alen, alias_end, buffer -
508cb5caa98Sdjl 						alias_end);
509cb5caa98Sdjl 						/* copy in the alias */
510cb5caa98Sdjl 						(void) memmove(alias_end,
511cb5caa98Sdjl 							ap, alen);
512cb5caa98Sdjl 						buffer += alen;
513cb5caa98Sdjl 						buflen -= alen;
514cb5caa98Sdjl 						alias_end += alen;
515cb5caa98Sdjl 					}
516cb5caa98Sdjl 
517cb5caa98Sdjl 					/* Add delimiter to the buffer */
518cb5caa98Sdjl 					*buffer++ = '\n';
519cb5caa98Sdjl 					buflen--;
520cb5caa98Sdjl 					args->returnlen++;
521cb5caa98Sdjl 				}
522cb5caa98Sdjl 
523cb5caa98Sdjl 				/* copy just the addr if not first one */
524cb5caa98Sdjl 				if (alias_end == NULL)
525cb5caa98Sdjl 					cplen = linelen;
526cb5caa98Sdjl 				else
527cb5caa98Sdjl 					cplen = namep - instr;
528cb5caa98Sdjl 
529cb5caa98Sdjl 				if (cplen >= buflen || erange == 1) {
530cb5caa98Sdjl 					args->erange = 1;
531cb5caa98Sdjl 					if (nhosts > 0) {
532cb5caa98Sdjl 						*(--buffer) = '\0';
533cb5caa98Sdjl 						buflen++;
534cb5caa98Sdjl 						args->returnlen--;
535cb5caa98Sdjl 					}
536cb5caa98Sdjl 					continue;
537cb5caa98Sdjl 				}
538cb5caa98Sdjl 
539cb5caa98Sdjl 				(void) memcpy(buffer, instr, cplen);
540cb5caa98Sdjl 				/* Adjust buffer */
541cb5caa98Sdjl 				buffer += cplen;
542cb5caa98Sdjl 				*buffer = '\0';
543cb5caa98Sdjl 				buflen -= cplen;
544cb5caa98Sdjl 				if (alias_end == NULL)
545cb5caa98Sdjl 					alias_end = buffer;
546cb5caa98Sdjl 			}
547cb5caa98Sdjl 
548cb5caa98Sdjl 			args->returnlen += linelen;
5497c478bd9Sstevel@tonic-gate 
550cb5caa98Sdjl 			/*
551cb5caa98Sdjl 			 * If this is the first one, save the canonical
552cb5caa98Sdjl 			 * name for future matches and continue.
553cb5caa98Sdjl 			 */
554cb5caa98Sdjl 			if (++nhosts == 1) {
555cb5caa98Sdjl 				h_name = malloc(namelen + 1);
556cb5caa98Sdjl 				if (h_name == NULL) {
557cb5caa98Sdjl 					res = NSS_UNAVAIL;
558cb5caa98Sdjl 					break;
559cb5caa98Sdjl 				}
5607c478bd9Sstevel@tonic-gate 				res = NSS_SUCCESS;
561cb5caa98Sdjl 				(void) memcpy(h_name, namep, namelen);
562cb5caa98Sdjl 				h_name[namelen] = '\0';
563cb5caa98Sdjl 				h_namelen = namelen;
564cb5caa98Sdjl 				if (hp)
565cb5caa98Sdjl 					args->returnval = hp;
566cb5caa98Sdjl 				else
567cb5caa98Sdjl 					args->returnval = args->buf.buffer;
5687c478bd9Sstevel@tonic-gate 				continue;
5697c478bd9Sstevel@tonic-gate 			}
570cb5caa98Sdjl 
571cb5caa98Sdjl 
572cb5caa98Sdjl 			/* Extend the array */
573cb5caa98Sdjl 			if (nhosts >= ntaddr) {
574cb5caa98Sdjl 				ntaddr *= 2;
575cb5caa98Sdjl 				if (type == AF_INET) {
576cb5caa98Sdjl 					addrp = realloc(taddr,
577cb5caa98Sdjl 						sizeof (*taddr) * ntaddr);
578cb5caa98Sdjl 					if (addrp == NULL) {
579cb5caa98Sdjl 						res = NSS_UNAVAIL;
580cb5caa98Sdjl 						break;
581cb5caa98Sdjl 					}
582cb5caa98Sdjl 					taddr = (in_addr_t *)addrp;
583cb5caa98Sdjl 				} else {
584cb5caa98Sdjl 					addrp = realloc(taddr6,
585cb5caa98Sdjl 						sizeof (*taddr6) * ntaddr);
586cb5caa98Sdjl 					if (addrp == NULL) {
587cb5caa98Sdjl 						res = NSS_UNAVAIL;
588cb5caa98Sdjl 						break;
589cb5caa98Sdjl 					}
590cb5caa98Sdjl 					taddr6 = (struct in6_addr *)addrp;
591cb5caa98Sdjl 				}
592cb5caa98Sdjl 			}
593cb5caa98Sdjl 
594cb5caa98Sdjl 			/*
595cb5caa98Sdjl 			 * For non-nscd, save aliases in a temporary buffer
596cb5caa98Sdjl 			 * Don't have to do this for nscd as 'buffer' already
597cb5caa98Sdjl 			 * contains the required data in the appropriate
598cb5caa98Sdjl 			 * format
599cb5caa98Sdjl 			 */
600cb5caa98Sdjl 			if (hp) {
601cb5caa98Sdjl 				abuf = do_aliases(hp, abuf, abuf_end);
602cb5caa98Sdjl 				if (abuf == NULL) {
603cb5caa98Sdjl 					args->erange = 1;
604cb5caa98Sdjl 					res = NSS_NOTFOUND;
605cb5caa98Sdjl 					break;
606cb5caa98Sdjl 				}
6077c478bd9Sstevel@tonic-gate 			}
608cb5caa98Sdjl 		} else if (namep && h_namelen == namelen &&
609cb5caa98Sdjl 		    strncasecmp(h_name, namep, namelen) == 0) {
6107c478bd9Sstevel@tonic-gate 			/*
6117c478bd9Sstevel@tonic-gate 			 * This line didn't have the requested name but
6127c478bd9Sstevel@tonic-gate 			 * is part of the same multihomed host (i.e. it
6137c478bd9Sstevel@tonic-gate 			 * has the same canonical name as the previous
6147c478bd9Sstevel@tonic-gate 			 * line), so march on...
6157c478bd9Sstevel@tonic-gate 			 */
6167c478bd9Sstevel@tonic-gate 			continue;
6177c478bd9Sstevel@tonic-gate 		} else if (nhosts) {
6187c478bd9Sstevel@tonic-gate 			break;
6197c478bd9Sstevel@tonic-gate 		}
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
622cb5caa98Sdjl 	if (abuf && res == NSS_SUCCESS) {
623cb5caa98Sdjl 
624cb5caa98Sdjl 		/* abuf != NULL implies hp and abuf_start != NULL */
625cb5caa98Sdjl 
6267c478bd9Sstevel@tonic-gate 		struct in_addr *addrp;
6277c478bd9Sstevel@tonic-gate 		struct in6_addr *addrp6;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 		if (type == AF_INET) {
6307c478bd9Sstevel@tonic-gate 			addrp = (struct in_addr *)(ROUND_DOWN(args->buf.buffer +
6317c478bd9Sstevel@tonic-gate 			    args->buf.buflen, sizeof (*addrp)));
6327c478bd9Sstevel@tonic-gate 			hp->h_addr_list = (char **)(ROUND_DOWN(addrp -
6337c478bd9Sstevel@tonic-gate 			    ((nhosts + 1) * sizeof (char *) +
6347c478bd9Sstevel@tonic-gate 			    (nhosts * sizeof (*addrp))), sizeof (char *)));
6357c478bd9Sstevel@tonic-gate 			for (i = 0, --addrp; i < nhosts; i++, --addrp) {
6367c478bd9Sstevel@tonic-gate 				(*(in_addr_t *)addrp) = taddr[i];
6377c478bd9Sstevel@tonic-gate 				hp->h_addr_list[i] = (char *)addrp;
6387c478bd9Sstevel@tonic-gate 			}
6397c478bd9Sstevel@tonic-gate 		} else {
6407c478bd9Sstevel@tonic-gate 			addrp6 = (struct in6_addr *)
6417c478bd9Sstevel@tonic-gate 			(ROUND_DOWN(args->buf.buffer + args->buf.buflen,
6427c478bd9Sstevel@tonic-gate 			sizeof (*addrp6)));
6437c478bd9Sstevel@tonic-gate 			hp->h_addr_list = (char **)(ROUND_DOWN(addrp6 -
6447c478bd9Sstevel@tonic-gate 			    ((nhosts + 1) * sizeof (char *) +
6457c478bd9Sstevel@tonic-gate 			    (nhosts * sizeof (*addrp6))), sizeof (char *)));
6467c478bd9Sstevel@tonic-gate 			for (i = 0, --addrp6; i < nhosts; i++, --addrp6) {
647cb5caa98Sdjl 				(void) memcpy(addrp6, &taddr6[i],
648cb5caa98Sdjl 						sizeof (struct in6_addr));
6497c478bd9Sstevel@tonic-gate 				hp->h_addr_list[i] = (char *)addrp6;
6507c478bd9Sstevel@tonic-gate 			}
6517c478bd9Sstevel@tonic-gate 		}
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 		hp->h_addr_list[nhosts] = 0;
6547c478bd9Sstevel@tonic-gate 		hp->h_aliases = _nss_netdb_aliases(abuf_start,
6557c478bd9Sstevel@tonic-gate 		    abuf - abuf_start, args->buf.buffer,
6567c478bd9Sstevel@tonic-gate 		    (char *)hp->h_addr_list - args->buf.buffer);
6577c478bd9Sstevel@tonic-gate 		if (hp->h_aliases == 0) {
6587c478bd9Sstevel@tonic-gate 			args->erange = 1;
659cb5caa98Sdjl 			res = NSS_NOTFOUND;
6607c478bd9Sstevel@tonic-gate 		} else {
6617c478bd9Sstevel@tonic-gate 			hp->h_name = hp->h_aliases[0];
6627c478bd9Sstevel@tonic-gate 			hp->h_aliases++;
6637c478bd9Sstevel@tonic-gate 		}
6647c478bd9Sstevel@tonic-gate 	}
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	/*
6677c478bd9Sstevel@tonic-gate 	 * stayopen is set to 0 by default in order to close the opened
6687c478bd9Sstevel@tonic-gate 	 * file.  Some applications may break if it is set to 1.
6697c478bd9Sstevel@tonic-gate 	 */
6707c478bd9Sstevel@tonic-gate 	if (!args->stayopen)
6717c478bd9Sstevel@tonic-gate 		(void) _nss_files_endent(be, 0);
6727c478bd9Sstevel@tonic-gate 
673cb5caa98Sdjl 	if (taddr)
674cb5caa98Sdjl 		free(taddr);
675cb5caa98Sdjl 	if (taddr6)
676cb5caa98Sdjl 		free(taddr6);
677cb5caa98Sdjl 	if (h_name)
678cb5caa98Sdjl 		free(h_name);
679cb5caa98Sdjl 	if (abuf_start)
680cb5caa98Sdjl 		free(abuf_start);
681cb5caa98Sdjl 
6827c478bd9Sstevel@tonic-gate 	return (res);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate  * A case-insensitive version of strstr().
6877c478bd9Sstevel@tonic-gate  */
6887c478bd9Sstevel@tonic-gate static char *
689cb5caa98Sdjl strcasestr(const char *as1, const char *as2)
6907c478bd9Sstevel@tonic-gate {
6917c478bd9Sstevel@tonic-gate 	int c2;
692cb5caa98Sdjl 	register const char *tptr;
693cb5caa98Sdjl 	register const char *s1, *s2;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	s1 = as1;
6967c478bd9Sstevel@tonic-gate 	s2 = as2;
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	if (s2 == NULL || *s2 == '\0')
6997c478bd9Sstevel@tonic-gate 		return (0);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	while (*s1) {
7027c478bd9Sstevel@tonic-gate 		if (tolower(*s1++) == tolower(c2 = *s2)) {
7037c478bd9Sstevel@tonic-gate 			tptr = s1;
7047c478bd9Sstevel@tonic-gate 			while ((tolower(c2 = *++s2) ==
7057c478bd9Sstevel@tonic-gate 			    tolower(*s1++)) && c2 != 0)
7067c478bd9Sstevel@tonic-gate 				;
7077c478bd9Sstevel@tonic-gate 			if (c2 == 0)
7087c478bd9Sstevel@tonic-gate 				return ((char *)tptr - 1);
7097c478bd9Sstevel@tonic-gate 			s1 = tptr;
7107c478bd9Sstevel@tonic-gate 			s2 = as2;
7117c478bd9Sstevel@tonic-gate 		}
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 	return (0);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate static char *
718cb5caa98Sdjl do_aliases(struct hostent *hp, char *abuf, char *end)
7197c478bd9Sstevel@tonic-gate {
720cb5caa98Sdjl 	char	**cp;
721cb5caa98Sdjl 	size_t	len;
7227c478bd9Sstevel@tonic-gate 
723cb5caa98Sdjl 	if ((cp = hp->h_aliases) == NULL)
724cb5caa98Sdjl 		return (abuf);
7257c478bd9Sstevel@tonic-gate 
726cb5caa98Sdjl 	for (; *cp; cp++) {
7277c478bd9Sstevel@tonic-gate 		len = strlen(*cp);
7287c478bd9Sstevel@tonic-gate 		if (abuf+len+1 >= end) {
729cb5caa98Sdjl 			return (NULL);
7307c478bd9Sstevel@tonic-gate 		}
7317c478bd9Sstevel@tonic-gate 		*abuf++ = ' ';
732cb5caa98Sdjl 		(void) memcpy(abuf, *cp, len);
733cb5caa98Sdjl 		abuf += len;
7347c478bd9Sstevel@tonic-gate 	}
7357c478bd9Sstevel@tonic-gate 	*abuf = '\0';
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	return (abuf);
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate  * This is a copy of a routine in libnsl/nss/netdir_inet.c.  It is
7437c478bd9Sstevel@tonic-gate  * here because /etc/lib/nss_files.so.1 cannot call routines
7447c478bd9Sstevel@tonic-gate  * in libnsl.  Care should be taken to keep the two copies in sync.
7457c478bd9Sstevel@tonic-gate  */
7467c478bd9Sstevel@tonic-gate int
7477c478bd9Sstevel@tonic-gate __nss_files_2herrno(nsstat)
7487c478bd9Sstevel@tonic-gate 	nss_status_t nsstat;
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate 	switch (nsstat) {
7517c478bd9Sstevel@tonic-gate 	case NSS_SUCCESS:
7527c478bd9Sstevel@tonic-gate 		/* no macro-defined success code for h_errno */
7537c478bd9Sstevel@tonic-gate 		return (0);
7547c478bd9Sstevel@tonic-gate 	case NSS_NOTFOUND:
7557c478bd9Sstevel@tonic-gate 		return (HOST_NOT_FOUND);
7567c478bd9Sstevel@tonic-gate 	case NSS_TRYAGAIN:
7577c478bd9Sstevel@tonic-gate 		return (TRY_AGAIN);
7587c478bd9Sstevel@tonic-gate 	case NSS_UNAVAIL:
7597c478bd9Sstevel@tonic-gate 		return (NO_RECOVERY);
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 	/* anything else */
7627c478bd9Sstevel@tonic-gate 	return (NO_RECOVERY);
7637c478bd9Sstevel@tonic-gate }
764