xref: /titanic_53/usr/src/lib/nsswitch/dns/common/gethostent6.c (revision 7257d1b4d25bfac0c802847390e98a464fd787ac)
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  */
21*7257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25cb5caa98Sdjl  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * This is the DNS backend for IPv6 addresses.
317c478bd9Sstevel@tonic-gate  * getbyname() is a local routine, but getbyaddr() actually shares the
327c478bd9Sstevel@tonic-gate  * same codes as the one in gethostent.c.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	endhostent	res_endhostent
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <malloc.h>
387c478bd9Sstevel@tonic-gate #include <stddef.h>
397c478bd9Sstevel@tonic-gate #include <string.h>
407c478bd9Sstevel@tonic-gate #include "dns_common.h"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * If the DNS name service switch routines are used in a binary that depends
447c478bd9Sstevel@tonic-gate  * on an older libresolv (libresolv.so.1, say), then having nss_dns.so.1 or
457c478bd9Sstevel@tonic-gate  * libnss_dns.a depend on a newer libresolv (libresolv.so.2) will cause
467c478bd9Sstevel@tonic-gate  * relocation problems. In particular, copy relocation of the _res structure
477c478bd9Sstevel@tonic-gate  * (which changes in size from libresolv.so.1 to libresolv.so.2) could
487c478bd9Sstevel@tonic-gate  * cause corruption, and result in a number of strange problems, including
497c478bd9Sstevel@tonic-gate  * core dumps. Hence, we check if a libresolv is already loaded.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #pragma weak	res_endhostent
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate extern struct hostent *_gethostbyname(int *, const char *);
567c478bd9Sstevel@tonic-gate extern struct hostent *_nss_dns_gethostbyname2(int *, const char *);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate typedef union {
597c478bd9Sstevel@tonic-gate 	long al;
607c478bd9Sstevel@tonic-gate 	char ac;
617c478bd9Sstevel@tonic-gate } align;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate static void
_endhostent(errp)657c478bd9Sstevel@tonic-gate _endhostent(errp)
667c478bd9Sstevel@tonic-gate 	nss_status_t	*errp;
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	int	ret;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	ret = endhostent();
717c478bd9Sstevel@tonic-gate 	if (ret == 0)
727c478bd9Sstevel@tonic-gate 		*errp = NSS_SUCCESS;
737c478bd9Sstevel@tonic-gate 	else
747c478bd9Sstevel@tonic-gate 		*errp = NSS_UNAVAIL;
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #ifdef	RNDUP
797c478bd9Sstevel@tonic-gate #undef	RNDUP
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate #define	RNDUP(x)	((1 + (((x)-1)/sizeof (void *))) * sizeof (void *))
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #ifdef	PTROFF
847c478bd9Sstevel@tonic-gate #undef	PTROFF
857c478bd9Sstevel@tonic-gate #endif
867c478bd9Sstevel@tonic-gate #define	PTROFF(p, o)	(((o) == 0) ? 0 : (void *)((char *)(p) + (o)))
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate  * Make a copy of h->h_name.
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate static char *
cloneName(struct hostent * h,int * outerr)937c478bd9Sstevel@tonic-gate cloneName(struct hostent *h, int *outerr) {
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	char	*name;
967c478bd9Sstevel@tonic-gate 	int	len;
977c478bd9Sstevel@tonic-gate 	int	error, *errp;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	if (outerr)
1007c478bd9Sstevel@tonic-gate 		errp = outerr;
1017c478bd9Sstevel@tonic-gate 	else
1027c478bd9Sstevel@tonic-gate 		errp = &error;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (h == 0 || h->h_name == 0) {
1057c478bd9Sstevel@tonic-gate 		*errp = 0;
1067c478bd9Sstevel@tonic-gate 		return (0);
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	len = strlen(h->h_name);
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	if ((name = malloc(len+1)) == 0) {
1127c478bd9Sstevel@tonic-gate 		*errp = 1;
1137c478bd9Sstevel@tonic-gate 		return (0);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
116cb5caa98Sdjl 	(void) memcpy(name, h->h_name, len+1);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	*errp = 0;
1197c478bd9Sstevel@tonic-gate 	return (name);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate  * Copy the h->h_addr_list[] array to a new array, and append the
1257c478bd9Sstevel@tonic-gate  * moreAddrs[] list. If h->h_addr_list[] contains IPv4 addresses,
1267c478bd9Sstevel@tonic-gate  * convert them to v4 mapped IPv6 addresses.
1277c478bd9Sstevel@tonic-gate  *
1287c478bd9Sstevel@tonic-gate  * Note: The pointers to the addresses in the moreAddrs[] array are copied,
1297c478bd9Sstevel@tonic-gate  *       but not the IP addresses themselves.
1307c478bd9Sstevel@tonic-gate  */
131cb5caa98Sdjl static struct in6_addr **
cloneAddrList(struct hostent * h,struct in6_addr ** moreAddrs,int * outerr)1327c478bd9Sstevel@tonic-gate cloneAddrList(struct hostent *h, struct in6_addr **moreAddrs, int *outerr) {
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	struct in6_addr	**addrArray, *addrList;
1357c478bd9Sstevel@tonic-gate 	int		domap, addrlen, i, j, addrCount, moreAddrCount = 0;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	int	error, *errp;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	if (outerr)
1407c478bd9Sstevel@tonic-gate 		errp = outerr;
1417c478bd9Sstevel@tonic-gate 	else
1427c478bd9Sstevel@tonic-gate 		errp = &error;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (h == 0 || h->h_addr_list == 0) {
1457c478bd9Sstevel@tonic-gate 		*errp = 0;
1467c478bd9Sstevel@tonic-gate 		return (0);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* Should we map v4 to IPv6 ? */
1507c478bd9Sstevel@tonic-gate 	domap = (h->h_length == sizeof (struct in_addr)) &&
1517c478bd9Sstevel@tonic-gate 		(h->h_addrtype == AF_INET);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/* If mapping, make sure we allocate enough memory for addresses */
1547c478bd9Sstevel@tonic-gate 	addrlen = h->h_length;
1557c478bd9Sstevel@tonic-gate 	if (domap && addrlen < sizeof (struct in6_addr))
1567c478bd9Sstevel@tonic-gate 		addrlen = sizeof (struct in6_addr);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	for (addrCount = 0; h->h_addr_list[addrCount]; addrCount++);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	if (moreAddrs != 0) {
1617c478bd9Sstevel@tonic-gate 		for (moreAddrCount = 0; moreAddrs[moreAddrCount];
1627c478bd9Sstevel@tonic-gate 			moreAddrCount++);
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	if ((addrArray = malloc((addrCount+moreAddrCount+1)*sizeof (addrList) +
1667c478bd9Sstevel@tonic-gate 				addrCount*addrlen)) == 0) {
1677c478bd9Sstevel@tonic-gate 		*errp = 1;
1687c478bd9Sstevel@tonic-gate 		return (0);
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	addrList = PTROFF(addrArray, (addrCount+moreAddrCount+1) *
1727c478bd9Sstevel@tonic-gate 					sizeof (addrList));
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	for (i = 0; i < addrCount; i++) {
1757c478bd9Sstevel@tonic-gate 		addrArray[i] = addrList;
1767c478bd9Sstevel@tonic-gate 		if (domap) {
177cb5caa98Sdjl 			/* LINTED: E_BAD_PTR_CAST_ALIGN */
1787c478bd9Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(
1797c478bd9Sstevel@tonic-gate 			(struct in_addr *)h->h_addr_list[i], addrArray[i]);
1807c478bd9Sstevel@tonic-gate 		} else {
181cb5caa98Sdjl 			(void) memcpy(addrArray[i], h->h_addr_list[i],
182cb5caa98Sdjl 				addrlen);
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 		addrList = PTROFF(addrList, addrlen);
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	for (j = 0; j < moreAddrCount; j++, i++) {
1887c478bd9Sstevel@tonic-gate 		addrArray[i] = moreAddrs[j];
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* Last pointer should be NULL */
1927c478bd9Sstevel@tonic-gate 	addrArray[i] = 0;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	*errp = 0;
1957c478bd9Sstevel@tonic-gate 	return (addrArray);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate  * Create a new alias array that is is a copy of h->h_aliases[] plus
2017c478bd9Sstevel@tonic-gate  * the aliases in mergeAliases[] which aren't duplicates of any alias
2027c478bd9Sstevel@tonic-gate  * in h->h_aliases[].
2037c478bd9Sstevel@tonic-gate  *
2047c478bd9Sstevel@tonic-gate  * Note 1: Only the string pointers (NOT the strings) in the mergeAliases[]
2057c478bd9Sstevel@tonic-gate  *         array are copied.
2067c478bd9Sstevel@tonic-gate  *
2077c478bd9Sstevel@tonic-gate  * Note 2: The duplicate aliases in mergeAliases[] are replaced by NULL
2087c478bd9Sstevel@tonic-gate  *         pointers.
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate static char **
cloneAliasList(struct hostent * h,char ** mergeAliases,int * outerr)2117c478bd9Sstevel@tonic-gate cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	char	**aliasArray, *aliasList;
214cb5caa98Sdjl 	int	i, j, aliasCount, mergeAliasCount = 0, realMac = 0;
2157c478bd9Sstevel@tonic-gate 	int	stringSize = 0;
2167c478bd9Sstevel@tonic-gate 	int	error, *errp;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	if (outerr)
2197c478bd9Sstevel@tonic-gate 		errp = outerr;
2207c478bd9Sstevel@tonic-gate 	else
2217c478bd9Sstevel@tonic-gate 		errp = &error;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (h == 0 || h->h_aliases == 0) {
2257c478bd9Sstevel@tonic-gate 		*errp = 0;
2267c478bd9Sstevel@tonic-gate 		return (0);
2277c478bd9Sstevel@tonic-gate 	}
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	for (aliasCount = 0; h->h_aliases[aliasCount]; aliasCount++) {
2307c478bd9Sstevel@tonic-gate 		stringSize += RNDUP(strlen(h->h_aliases[aliasCount])+1);
2317c478bd9Sstevel@tonic-gate 	}
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (mergeAliases != 0) {
2347c478bd9Sstevel@tonic-gate 		for (; mergeAliases[mergeAliasCount]; mergeAliasCount++) {
2357c478bd9Sstevel@tonic-gate 			int	countThis = 1;
2367c478bd9Sstevel@tonic-gate 			/* Skip duplicates */
2377c478bd9Sstevel@tonic-gate 			for (j = 0; j < aliasCount; j++) {
2387c478bd9Sstevel@tonic-gate 				if (strcmp(mergeAliases[mergeAliasCount],
2397c478bd9Sstevel@tonic-gate 						h->h_aliases[j]) == 0) {
2407c478bd9Sstevel@tonic-gate 					countThis = 0;
2417c478bd9Sstevel@tonic-gate 					break;
2427c478bd9Sstevel@tonic-gate 				}
2437c478bd9Sstevel@tonic-gate 			}
2447c478bd9Sstevel@tonic-gate 			if (countThis)
2457c478bd9Sstevel@tonic-gate 				realMac++;
2467c478bd9Sstevel@tonic-gate 			else
2477c478bd9Sstevel@tonic-gate 				mergeAliases[mergeAliasCount] = 0;
2487c478bd9Sstevel@tonic-gate 		}
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if ((aliasArray = malloc((aliasCount+realMac+1)*sizeof (char **)+
2527c478bd9Sstevel@tonic-gate 				stringSize)) == 0) {
2537c478bd9Sstevel@tonic-gate 		*errp = 1;
2547c478bd9Sstevel@tonic-gate 		return (0);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	aliasList = PTROFF(aliasArray,
2587c478bd9Sstevel@tonic-gate 				(aliasCount+realMac+1)*sizeof (char **));
2597c478bd9Sstevel@tonic-gate 	for (i = 0; i < aliasCount; i++) {
2607c478bd9Sstevel@tonic-gate 		int	len = strlen(h->h_aliases[i]);
2617c478bd9Sstevel@tonic-gate 		aliasArray[i] = aliasList;
262cb5caa98Sdjl 		(void) memcpy(aliasArray[i], h->h_aliases[i], len+1);
2637c478bd9Sstevel@tonic-gate 		aliasList = PTROFF(aliasList, RNDUP(len+1));
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	for (j = 0; j < mergeAliasCount; j++) {
2677c478bd9Sstevel@tonic-gate 		if (mergeAliases[j] != 0) {
2687c478bd9Sstevel@tonic-gate 			aliasArray[i++] = mergeAliases[j];
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	aliasArray[i] = 0;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	*errp = 0;
2757c478bd9Sstevel@tonic-gate 	return (aliasArray);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
278cb5caa98Sdjl /*ARGSUSED*/
2797c478bd9Sstevel@tonic-gate static nss_status_t
getbyname(be,a)2807c478bd9Sstevel@tonic-gate getbyname(be, a)
2817c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
2827c478bd9Sstevel@tonic-gate 	void			*a;
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	struct hostent	*he = NULL;
2857c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2867c478bd9Sstevel@tonic-gate 	int		ret, mt_disabled;
2877c478bd9Sstevel@tonic-gate 	sigset_t	oldmask;
2887c478bd9Sstevel@tonic-gate 	int		converr = 0, gotv6 = 0;
2897c478bd9Sstevel@tonic-gate 	struct hostent	v6he;
29080b80bf0Smichen 	struct hostent	mhe;
2917c478bd9Sstevel@tonic-gate 	char		*v6Name = 0;
2927c478bd9Sstevel@tonic-gate 	struct in6_addr	**v6Addrs = 0, **mergeAddrs = 0;
2937c478bd9Sstevel@tonic-gate 	char		**v6Aliases = 0, **mergeAliases = 0;
2947c478bd9Sstevel@tonic-gate 	int		v6_h_errno;
2957c478bd9Sstevel@tonic-gate 	int		old_retry;
2967c478bd9Sstevel@tonic-gate 	int		af = argp->key.ipnode.af_family;
2977c478bd9Sstevel@tonic-gate 	int		flags = argp->key.ipnode.flags;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	/* Now get the AAAA records */
3027c478bd9Sstevel@tonic-gate 	if (af == AF_INET6)
3037c478bd9Sstevel@tonic-gate 		he = _nss_dns_gethostbyname2(&argp->h_errno,
3047c478bd9Sstevel@tonic-gate 					argp->key.ipnode.name);
3057c478bd9Sstevel@tonic-gate 	if (he != NULL) {
3067c478bd9Sstevel@tonic-gate 		/*
3077c478bd9Sstevel@tonic-gate 		 * pointer in "he" is part of a static pthread key in libresolv
3087c478bd9Sstevel@tonic-gate 		 * It should be treated as read only.
3097c478bd9Sstevel@tonic-gate 		 * So clone a copy first.
3107c478bd9Sstevel@tonic-gate 		 */
3117c478bd9Sstevel@tonic-gate 		v6Name = cloneName(he, &converr);
3127c478bd9Sstevel@tonic-gate 		if (converr) {
3137c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3147c478bd9Sstevel@tonic-gate 			argp->erange = 1;
3157c478bd9Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3167c478bd9Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 		v6Addrs = cloneAddrList(he, 0, &converr);
3197c478bd9Sstevel@tonic-gate 		if (converr) {
3207c478bd9Sstevel@tonic-gate 			if (v6Name != 0)
3217c478bd9Sstevel@tonic-gate 				free(v6Name);
3227c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3237c478bd9Sstevel@tonic-gate 			argp->erange = 1;
3247c478bd9Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3257c478bd9Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3267c478bd9Sstevel@tonic-gate 		}
3277c478bd9Sstevel@tonic-gate 		v6Aliases = cloneAliasList(he, 0, &converr);
3287c478bd9Sstevel@tonic-gate 		if (converr) {
3297c478bd9Sstevel@tonic-gate 			if (v6Name != 0)
3307c478bd9Sstevel@tonic-gate 				free(v6Name);
3317c478bd9Sstevel@tonic-gate 			if (v6Addrs != 0)
3327c478bd9Sstevel@tonic-gate 				free(v6Addrs);
3337c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3347c478bd9Sstevel@tonic-gate 			argp->erange = 1;
3357c478bd9Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3367c478bd9Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3377c478bd9Sstevel@tonic-gate 		}
3387c478bd9Sstevel@tonic-gate 		v6_h_errno = argp->h_errno;
3397c478bd9Sstevel@tonic-gate 		gotv6 = 1;
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/*
3437c478bd9Sstevel@tonic-gate 	 * The conditions to search "A" records:
3447c478bd9Sstevel@tonic-gate 	 * 1. af is AF_INET
3457c478bd9Sstevel@tonic-gate 	 * 2. if af is AF_INET6
3467c478bd9Sstevel@tonic-gate 	 *    then flags are either
3477c478bd9Sstevel@tonic-gate 	 *	1) (AI_ALL | AI_V4MAPPED) or
3487c478bd9Sstevel@tonic-gate 	 *	2) AI_V4MAPPED and he == NULL
3497c478bd9Sstevel@tonic-gate 	 *	    (No V6 addresses found or no search for V6 at all)
3507c478bd9Sstevel@tonic-gate 	 */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* Get the A records, and store the information */
3537c478bd9Sstevel@tonic-gate 	if ((af == AF_INET) ||
3547c478bd9Sstevel@tonic-gate 	    ((af == AF_INET6) &&
3557c478bd9Sstevel@tonic-gate 		((flags & (AI_ALL | AI_V4MAPPED)) ||
3567c478bd9Sstevel@tonic-gate 		((flags & AI_V4MAPPED) && he == NULL))))
3577c478bd9Sstevel@tonic-gate 		he = _gethostbyname(&argp->h_errno, argp->key.ipnode.name);
3587c478bd9Sstevel@tonic-gate 	else
3597c478bd9Sstevel@tonic-gate 		he = NULL;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/* Merge the results */
3627c478bd9Sstevel@tonic-gate 	if (he != NULL) {
36380b80bf0Smichen 		mhe = *he;
3647c478bd9Sstevel@tonic-gate 		mergeAddrs = cloneAddrList(he, v6Addrs, &converr);
3657c478bd9Sstevel@tonic-gate 		if (converr) {
3667c478bd9Sstevel@tonic-gate 			if (v6Name != 0)
3677c478bd9Sstevel@tonic-gate 				free(v6Name);
3687c478bd9Sstevel@tonic-gate 			if (v6Addrs != 0)
3697c478bd9Sstevel@tonic-gate 				free(v6Addrs);
3707c478bd9Sstevel@tonic-gate 			if (v6Aliases != 0)
3717c478bd9Sstevel@tonic-gate 				free(v6Aliases);
3727c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3737c478bd9Sstevel@tonic-gate 			argp->erange = 1;
3747c478bd9Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3757c478bd9Sstevel@tonic-gate 						old_retry);
3767c478bd9Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3777c478bd9Sstevel@tonic-gate 		}
37880b80bf0Smichen 		mhe.h_addr_list = (char **)mergeAddrs;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 		mergeAliases = cloneAliasList(he, v6Aliases, &converr);
3817c478bd9Sstevel@tonic-gate 		if (converr) {
3827c478bd9Sstevel@tonic-gate 			if (v6Name != 0)
3837c478bd9Sstevel@tonic-gate 				free(v6Name);
3847c478bd9Sstevel@tonic-gate 			if (v6Addrs != 0)
3857c478bd9Sstevel@tonic-gate 				free(v6Addrs);
3867c478bd9Sstevel@tonic-gate 			if (v6Aliases != 0)
3877c478bd9Sstevel@tonic-gate 				free(v6Aliases);
3887c478bd9Sstevel@tonic-gate 			if (mergeAddrs != 0)
3897c478bd9Sstevel@tonic-gate 				free(mergeAddrs);
3907c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3917c478bd9Sstevel@tonic-gate 			argp->erange = 1;
3927c478bd9Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3937c478bd9Sstevel@tonic-gate 						old_retry);
3947c478bd9Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3957c478bd9Sstevel@tonic-gate 		}
39680b80bf0Smichen 		mhe.h_aliases = mergeAliases;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 		/* reset h_length, h_addrtype */
39980b80bf0Smichen 		mhe.h_length = sizeof (struct in6_addr);
40080b80bf0Smichen 		mhe.h_addrtype = AF_INET6;
40180b80bf0Smichen 		he = &mhe;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	} else if (gotv6) {
4047c478bd9Sstevel@tonic-gate 		v6he.h_name = v6Name;
4057c478bd9Sstevel@tonic-gate 		v6he.h_length = sizeof (struct in6_addr);
4067c478bd9Sstevel@tonic-gate 		v6he.h_addrtype = AF_INET6;
4077c478bd9Sstevel@tonic-gate 		v6he.h_addr_list = (char **)v6Addrs;
4087c478bd9Sstevel@tonic-gate 		v6he.h_aliases = v6Aliases;
4097c478bd9Sstevel@tonic-gate 		he = &v6he;
4107c478bd9Sstevel@tonic-gate 		argp->h_errno = v6_h_errno;
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
413cb5caa98Sdjl 	if (he != NULL) {
414cb5caa98Sdjl 		/*
415cb5caa98Sdjl 		 * if asked to return data in string,
416cb5caa98Sdjl 		 * convert the hostent structure into
417cb5caa98Sdjl 		 * string data
418cb5caa98Sdjl 		 */
419cb5caa98Sdjl 		if (argp->buf.result == NULL) {
420cb5caa98Sdjl 			ret = ent2str(he, a, AF_INET6);
421cb5caa98Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
422cb5caa98Sdjl 				argp->returnval = argp->buf.buffer;
4237c478bd9Sstevel@tonic-gate 		} else {
424cb5caa98Sdjl 			ret = ent2result(he, a, AF_INET6);
425cb5caa98Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
426cb5caa98Sdjl 				argp->returnval = argp->buf.result;
427cb5caa98Sdjl 		}
428cb5caa98Sdjl 
429cb5caa98Sdjl 		if (ret != NSS_STR_PARSE_SUCCESS) {
4307c478bd9Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
4317c478bd9Sstevel@tonic-gate 			if (ret == NSS_STR_PARSE_ERANGE) {
4327c478bd9Sstevel@tonic-gate 				argp->erange = 1;
4337c478bd9Sstevel@tonic-gate 			}
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (v6Name != 0)
4387c478bd9Sstevel@tonic-gate 		free(v6Name);
4397c478bd9Sstevel@tonic-gate 	if (v6Addrs != 0)
4407c478bd9Sstevel@tonic-gate 		free(v6Addrs);
4417c478bd9Sstevel@tonic-gate 	if (v6Aliases != 0)
4427c478bd9Sstevel@tonic-gate 		free(v6Aliases);
4437c478bd9Sstevel@tonic-gate 	if (mergeAddrs != 0)
4447c478bd9Sstevel@tonic-gate 		free(mergeAddrs);
4457c478bd9Sstevel@tonic-gate 	if (mergeAliases != 0)
4467c478bd9Sstevel@tonic-gate 		free(mergeAliases);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	switch_resolver_reset(mt_disabled, oldmask, old_retry);
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	return (_herrno2nss(argp->h_errno));
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate extern nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate static nss_status_t
getbyaddr(be,a)4577c478bd9Sstevel@tonic-gate getbyaddr(be, a)
4587c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4597c478bd9Sstevel@tonic-gate 	void			*a;
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate 	/* uses the same getbyaddr from IPv4 */
4627c478bd9Sstevel@tonic-gate 	return (__nss_dns_getbyaddr(be, a));
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4677c478bd9Sstevel@tonic-gate static nss_status_t
_nss_dns_getent(be,args)4687c478bd9Sstevel@tonic-gate _nss_dns_getent(be, args)
4697c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4707c478bd9Sstevel@tonic-gate 	void			*args;
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4777c478bd9Sstevel@tonic-gate static nss_status_t
_nss_dns_setent(be,dummy)4787c478bd9Sstevel@tonic-gate _nss_dns_setent(be, dummy)
4797c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4807c478bd9Sstevel@tonic-gate 	void			*dummy;
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4837c478bd9Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4887c478bd9Sstevel@tonic-gate static nss_status_t
_nss_dns_endent(be,dummy)4897c478bd9Sstevel@tonic-gate _nss_dns_endent(be, dummy)
4907c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4917c478bd9Sstevel@tonic-gate 	void			*dummy;
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4947c478bd9Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4997c478bd9Sstevel@tonic-gate static nss_status_t
_nss_dns_destr(be,dummy)5007c478bd9Sstevel@tonic-gate _nss_dns_destr(be, dummy)
5017c478bd9Sstevel@tonic-gate 	dns_backend_ptr_t	be;
5027c478bd9Sstevel@tonic-gate 	void			*dummy;
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	nss_status_t	errp;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (be != 0) {
5077c478bd9Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
5087c478bd9Sstevel@tonic-gate 		sigset_t	oldmask, newmask;
5097c478bd9Sstevel@tonic-gate 		int		mt_disabled = 1;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 		if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
5127c478bd9Sstevel@tonic-gate 			(void) sigfillset(&newmask);
513*7257d1b4Sraf 			(void) thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
514*7257d1b4Sraf 			(void) mutex_lock(&one_lane);
5157c478bd9Sstevel@tonic-gate 		}
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 		_endhostent(&errp);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		if (mt_disabled) {
520*7257d1b4Sraf 			(void) mutex_unlock(&one_lane);
521*7257d1b4Sraf 			(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
5227c478bd9Sstevel@tonic-gate 		} else {
5237c478bd9Sstevel@tonic-gate 			(void) (*disable_mt)();
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		free(be);
5277c478bd9Sstevel@tonic-gate 	}
5287c478bd9Sstevel@tonic-gate 	return (NSS_SUCCESS);   /* In case anyone is dumb enough to check */
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate static dns_backend_op_t ipnodes_ops[] = {
5347c478bd9Sstevel@tonic-gate 	_nss_dns_destr,
5357c478bd9Sstevel@tonic-gate 	_nss_dns_endent,
5367c478bd9Sstevel@tonic-gate 	_nss_dns_setent,
5377c478bd9Sstevel@tonic-gate 	_nss_dns_getent,
5387c478bd9Sstevel@tonic-gate 	getbyname,
5397c478bd9Sstevel@tonic-gate 	getbyaddr,
5407c478bd9Sstevel@tonic-gate };
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5437c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_dns_ipnodes_constr(dummy1,dummy2,dummy3)5447c478bd9Sstevel@tonic-gate _nss_dns_ipnodes_constr(dummy1, dummy2, dummy3)
5457c478bd9Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
5467c478bd9Sstevel@tonic-gate {
5477c478bd9Sstevel@tonic-gate 	return (_nss_dns_constr(ipnodes_ops,
5487c478bd9Sstevel@tonic-gate 		sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
5497c478bd9Sstevel@tonic-gate }
550cb5caa98Sdjl 
551cb5caa98Sdjl /*
552cb5caa98Sdjl  * optional NSS2 packed backend gethostsbyipnode with ttl
553cb5caa98Sdjl  * entry point.
554cb5caa98Sdjl  *
555cb5caa98Sdjl  * Returns:
556cb5caa98Sdjl  *	NSS_SUCCESS - successful
557cb5caa98Sdjl  *	NSS_NOTFOUND - successful but nothing found
558cb5caa98Sdjl  *	NSS_ERROR - fallback to NSS backend lookup mode
559cb5caa98Sdjl  * If successful, buffer will be filled with valid data
560cb5caa98Sdjl  *
561cb5caa98Sdjl  */
562cb5caa98Sdjl 
563cb5caa98Sdjl /*ARGSUSED*/
564cb5caa98Sdjl nss_status_t
_nss_get_dns_ipnodes_name(dns_backend_ptr_t * be,void ** bufp,size_t * sizep)565cb5caa98Sdjl _nss_get_dns_ipnodes_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep)
566cb5caa98Sdjl {
567cb5caa98Sdjl 	return (_nss_dns_gethost_withttl(*bufp, *sizep, 1));
568cb5caa98Sdjl }
569