10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2830Sdjl  * Common Development and Distribution License (the "License").
6*2830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2830Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
24*2830Sdjl  */
25*2830Sdjl /*
260Sstevel@tonic-gate  *	gethostent6.c
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * This is the DNS backend for IPv6 addresses.
330Sstevel@tonic-gate  * getbyname() is a local routine, but getbyaddr() actually shares the
340Sstevel@tonic-gate  * same codes as the one in gethostent.c.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define	endhostent	res_endhostent
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include <malloc.h>
400Sstevel@tonic-gate #include <stddef.h>
410Sstevel@tonic-gate #include <string.h>
420Sstevel@tonic-gate #include "dns_common.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  * If the DNS name service switch routines are used in a binary that depends
460Sstevel@tonic-gate  * on an older libresolv (libresolv.so.1, say), then having nss_dns.so.1 or
470Sstevel@tonic-gate  * libnss_dns.a depend on a newer libresolv (libresolv.so.2) will cause
480Sstevel@tonic-gate  * relocation problems. In particular, copy relocation of the _res structure
490Sstevel@tonic-gate  * (which changes in size from libresolv.so.1 to libresolv.so.2) could
500Sstevel@tonic-gate  * cause corruption, and result in a number of strange problems, including
510Sstevel@tonic-gate  * core dumps. Hence, we check if a libresolv is already loaded.
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 
550Sstevel@tonic-gate #pragma weak	res_endhostent
560Sstevel@tonic-gate 
570Sstevel@tonic-gate extern struct hostent *_gethostbyname(int *, const char *);
580Sstevel@tonic-gate extern struct hostent *_nss_dns_gethostbyname2(int *, const char *);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate typedef union {
610Sstevel@tonic-gate 	long al;
620Sstevel@tonic-gate 	char ac;
630Sstevel@tonic-gate } align;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static void
670Sstevel@tonic-gate _endhostent(errp)
680Sstevel@tonic-gate 	nss_status_t	*errp;
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	int	ret;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	ret = endhostent();
730Sstevel@tonic-gate 	if (ret == 0)
740Sstevel@tonic-gate 		*errp = NSS_SUCCESS;
750Sstevel@tonic-gate 	else
760Sstevel@tonic-gate 		*errp = NSS_UNAVAIL;
770Sstevel@tonic-gate }
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 
800Sstevel@tonic-gate #ifdef	RNDUP
810Sstevel@tonic-gate #undef	RNDUP
820Sstevel@tonic-gate #endif
830Sstevel@tonic-gate #define	RNDUP(x)	((1 + (((x)-1)/sizeof (void *))) * sizeof (void *))
840Sstevel@tonic-gate 
850Sstevel@tonic-gate #ifdef	PTROFF
860Sstevel@tonic-gate #undef	PTROFF
870Sstevel@tonic-gate #endif
880Sstevel@tonic-gate #define	PTROFF(p, o)	(((o) == 0) ? 0 : (void *)((char *)(p) + (o)))
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * Make a copy of h->h_name.
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate static char *
950Sstevel@tonic-gate cloneName(struct hostent *h, int *outerr) {
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	char	*name;
980Sstevel@tonic-gate 	int	len;
990Sstevel@tonic-gate 	int	error, *errp;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	if (outerr)
1020Sstevel@tonic-gate 		errp = outerr;
1030Sstevel@tonic-gate 	else
1040Sstevel@tonic-gate 		errp = &error;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	if (h == 0 || h->h_name == 0) {
1070Sstevel@tonic-gate 		*errp = 0;
1080Sstevel@tonic-gate 		return (0);
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	len = strlen(h->h_name);
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if ((name = malloc(len+1)) == 0) {
1140Sstevel@tonic-gate 		*errp = 1;
1150Sstevel@tonic-gate 		return (0);
1160Sstevel@tonic-gate 	}
1170Sstevel@tonic-gate 
118*2830Sdjl 	(void) memcpy(name, h->h_name, len+1);
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	*errp = 0;
1210Sstevel@tonic-gate 	return (name);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate  * Copy the h->h_addr_list[] array to a new array, and append the
1270Sstevel@tonic-gate  * moreAddrs[] list. If h->h_addr_list[] contains IPv4 addresses,
1280Sstevel@tonic-gate  * convert them to v4 mapped IPv6 addresses.
1290Sstevel@tonic-gate  *
1300Sstevel@tonic-gate  * Note: The pointers to the addresses in the moreAddrs[] array are copied,
1310Sstevel@tonic-gate  *       but not the IP addresses themselves.
1320Sstevel@tonic-gate  */
133*2830Sdjl static struct in6_addr **
1340Sstevel@tonic-gate cloneAddrList(struct hostent *h, struct in6_addr **moreAddrs, int *outerr) {
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	struct in6_addr	**addrArray, *addrList;
1370Sstevel@tonic-gate 	int		domap, addrlen, i, j, addrCount, moreAddrCount = 0;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	int	error, *errp;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if (outerr)
1420Sstevel@tonic-gate 		errp = outerr;
1430Sstevel@tonic-gate 	else
1440Sstevel@tonic-gate 		errp = &error;
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	if (h == 0 || h->h_addr_list == 0) {
1470Sstevel@tonic-gate 		*errp = 0;
1480Sstevel@tonic-gate 		return (0);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	/* Should we map v4 to IPv6 ? */
1520Sstevel@tonic-gate 	domap = (h->h_length == sizeof (struct in_addr)) &&
1530Sstevel@tonic-gate 		(h->h_addrtype == AF_INET);
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	/* If mapping, make sure we allocate enough memory for addresses */
1560Sstevel@tonic-gate 	addrlen = h->h_length;
1570Sstevel@tonic-gate 	if (domap && addrlen < sizeof (struct in6_addr))
1580Sstevel@tonic-gate 		addrlen = sizeof (struct in6_addr);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	for (addrCount = 0; h->h_addr_list[addrCount]; addrCount++);
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	if (moreAddrs != 0) {
1630Sstevel@tonic-gate 		for (moreAddrCount = 0; moreAddrs[moreAddrCount];
1640Sstevel@tonic-gate 			moreAddrCount++);
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if ((addrArray = malloc((addrCount+moreAddrCount+1)*sizeof (addrList) +
1680Sstevel@tonic-gate 				addrCount*addrlen)) == 0) {
1690Sstevel@tonic-gate 		*errp = 1;
1700Sstevel@tonic-gate 		return (0);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	addrList = PTROFF(addrArray, (addrCount+moreAddrCount+1) *
1740Sstevel@tonic-gate 					sizeof (addrList));
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	for (i = 0; i < addrCount; i++) {
1770Sstevel@tonic-gate 		addrArray[i] = addrList;
1780Sstevel@tonic-gate 		if (domap) {
179*2830Sdjl 			/* LINTED: E_BAD_PTR_CAST_ALIGN */
1800Sstevel@tonic-gate 			IN6_INADDR_TO_V4MAPPED(
1810Sstevel@tonic-gate 			(struct in_addr *)h->h_addr_list[i], addrArray[i]);
1820Sstevel@tonic-gate 		} else {
183*2830Sdjl 			(void) memcpy(addrArray[i], h->h_addr_list[i],
184*2830Sdjl 				addrlen);
1850Sstevel@tonic-gate 		}
1860Sstevel@tonic-gate 		addrList = PTROFF(addrList, addrlen);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	for (j = 0; j < moreAddrCount; j++, i++) {
1900Sstevel@tonic-gate 		addrArray[i] = moreAddrs[j];
1910Sstevel@tonic-gate 	}
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	/* Last pointer should be NULL */
1940Sstevel@tonic-gate 	addrArray[i] = 0;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	*errp = 0;
1970Sstevel@tonic-gate 	return (addrArray);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate  * Create a new alias array that is is a copy of h->h_aliases[] plus
2030Sstevel@tonic-gate  * the aliases in mergeAliases[] which aren't duplicates of any alias
2040Sstevel@tonic-gate  * in h->h_aliases[].
2050Sstevel@tonic-gate  *
2060Sstevel@tonic-gate  * Note 1: Only the string pointers (NOT the strings) in the mergeAliases[]
2070Sstevel@tonic-gate  *         array are copied.
2080Sstevel@tonic-gate  *
2090Sstevel@tonic-gate  * Note 2: The duplicate aliases in mergeAliases[] are replaced by NULL
2100Sstevel@tonic-gate  *         pointers.
2110Sstevel@tonic-gate  */
2120Sstevel@tonic-gate static char **
2130Sstevel@tonic-gate cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	char	**aliasArray, *aliasList;
216*2830Sdjl 	int	i, j, aliasCount, mergeAliasCount = 0, realMac = 0;
2170Sstevel@tonic-gate 	int	stringSize = 0;
2180Sstevel@tonic-gate 	int	error, *errp;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	if (outerr)
2210Sstevel@tonic-gate 		errp = outerr;
2220Sstevel@tonic-gate 	else
2230Sstevel@tonic-gate 		errp = &error;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	if (h == 0 || h->h_aliases == 0) {
2270Sstevel@tonic-gate 		*errp = 0;
2280Sstevel@tonic-gate 		return (0);
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	for (aliasCount = 0; h->h_aliases[aliasCount]; aliasCount++) {
2320Sstevel@tonic-gate 		stringSize += RNDUP(strlen(h->h_aliases[aliasCount])+1);
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	if (mergeAliases != 0) {
2360Sstevel@tonic-gate 		for (; mergeAliases[mergeAliasCount]; mergeAliasCount++) {
2370Sstevel@tonic-gate 			int	countThis = 1;
2380Sstevel@tonic-gate 			/* Skip duplicates */
2390Sstevel@tonic-gate 			for (j = 0; j < aliasCount; j++) {
2400Sstevel@tonic-gate 				if (strcmp(mergeAliases[mergeAliasCount],
2410Sstevel@tonic-gate 						h->h_aliases[j]) == 0) {
2420Sstevel@tonic-gate 					countThis = 0;
2430Sstevel@tonic-gate 					break;
2440Sstevel@tonic-gate 				}
2450Sstevel@tonic-gate 			}
2460Sstevel@tonic-gate 			if (countThis)
2470Sstevel@tonic-gate 				realMac++;
2480Sstevel@tonic-gate 			else
2490Sstevel@tonic-gate 				mergeAliases[mergeAliasCount] = 0;
2500Sstevel@tonic-gate 		}
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	if ((aliasArray = malloc((aliasCount+realMac+1)*sizeof (char **)+
2540Sstevel@tonic-gate 				stringSize)) == 0) {
2550Sstevel@tonic-gate 		*errp = 1;
2560Sstevel@tonic-gate 		return (0);
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	aliasList = PTROFF(aliasArray,
2600Sstevel@tonic-gate 				(aliasCount+realMac+1)*sizeof (char **));
2610Sstevel@tonic-gate 	for (i = 0; i < aliasCount; i++) {
2620Sstevel@tonic-gate 		int	len = strlen(h->h_aliases[i]);
2630Sstevel@tonic-gate 		aliasArray[i] = aliasList;
264*2830Sdjl 		(void) memcpy(aliasArray[i], h->h_aliases[i], len+1);
2650Sstevel@tonic-gate 		aliasList = PTROFF(aliasList, RNDUP(len+1));
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	for (j = 0; j < mergeAliasCount; j++) {
2690Sstevel@tonic-gate 		if (mergeAliases[j] != 0) {
2700Sstevel@tonic-gate 			aliasArray[i++] = mergeAliases[j];
2710Sstevel@tonic-gate 		}
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	aliasArray[i] = 0;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	*errp = 0;
2770Sstevel@tonic-gate 	return (aliasArray);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
280*2830Sdjl /*ARGSUSED*/
2810Sstevel@tonic-gate static nss_status_t
2820Sstevel@tonic-gate getbyname(be, a)
2830Sstevel@tonic-gate 	dns_backend_ptr_t	be;
2840Sstevel@tonic-gate 	void			*a;
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	struct hostent	*he = NULL;
2870Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
2880Sstevel@tonic-gate 	int		ret, mt_disabled;
2890Sstevel@tonic-gate 	sigset_t	oldmask;
2900Sstevel@tonic-gate 	int		converr = 0, gotv6 = 0;
2910Sstevel@tonic-gate 	struct hostent	v6he;
2920Sstevel@tonic-gate 	char		*v6Name = 0;
2930Sstevel@tonic-gate 	struct in6_addr	**v6Addrs = 0, **mergeAddrs = 0;
2940Sstevel@tonic-gate 	char		**v6Aliases = 0, **mergeAliases = 0;
2950Sstevel@tonic-gate 	int		v6_h_errno;
2960Sstevel@tonic-gate 	int		old_retry;
2970Sstevel@tonic-gate 	int		af = argp->key.ipnode.af_family;
2980Sstevel@tonic-gate 	int		flags = argp->key.ipnode.flags;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	/* Now get the AAAA records */
3030Sstevel@tonic-gate 	if (af == AF_INET6)
3040Sstevel@tonic-gate 		he = _nss_dns_gethostbyname2(&argp->h_errno,
3050Sstevel@tonic-gate 					argp->key.ipnode.name);
3060Sstevel@tonic-gate 	if (he != NULL) {
3070Sstevel@tonic-gate 		/*
3080Sstevel@tonic-gate 		 * pointer in "he" is part of a static pthread key in libresolv
3090Sstevel@tonic-gate 		 * It should be treated as read only.
3100Sstevel@tonic-gate 		 * So clone a copy first.
3110Sstevel@tonic-gate 		 */
3120Sstevel@tonic-gate 		v6Name = cloneName(he, &converr);
3130Sstevel@tonic-gate 		if (converr) {
3140Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3150Sstevel@tonic-gate 			argp->erange = 1;
3160Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3170Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 		v6Addrs = cloneAddrList(he, 0, &converr);
3200Sstevel@tonic-gate 		if (converr) {
3210Sstevel@tonic-gate 			if (v6Name != 0)
3220Sstevel@tonic-gate 				free(v6Name);
3230Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3240Sstevel@tonic-gate 			argp->erange = 1;
3250Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3260Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3270Sstevel@tonic-gate 		}
3280Sstevel@tonic-gate 		v6Aliases = cloneAliasList(he, 0, &converr);
3290Sstevel@tonic-gate 		if (converr) {
3300Sstevel@tonic-gate 			if (v6Name != 0)
3310Sstevel@tonic-gate 				free(v6Name);
3320Sstevel@tonic-gate 			if (v6Addrs != 0)
3330Sstevel@tonic-gate 				free(v6Addrs);
3340Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3350Sstevel@tonic-gate 			argp->erange = 1;
3360Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3370Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 		v6_h_errno = argp->h_errno;
3400Sstevel@tonic-gate 		gotv6 = 1;
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	/*
3440Sstevel@tonic-gate 	 * The conditions to search "A" records:
3450Sstevel@tonic-gate 	 * 1. af is AF_INET
3460Sstevel@tonic-gate 	 * 2. if af is AF_INET6
3470Sstevel@tonic-gate 	 *    then flags are either
3480Sstevel@tonic-gate 	 *	1) (AI_ALL | AI_V4MAPPED) or
3490Sstevel@tonic-gate 	 *	2) AI_V4MAPPED and he == NULL
3500Sstevel@tonic-gate 	 *	    (No V6 addresses found or no search for V6 at all)
3510Sstevel@tonic-gate 	 */
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	/* Get the A records, and store the information */
3540Sstevel@tonic-gate 	if ((af == AF_INET) ||
3550Sstevel@tonic-gate 	    ((af == AF_INET6) &&
3560Sstevel@tonic-gate 		((flags & (AI_ALL | AI_V4MAPPED)) ||
3570Sstevel@tonic-gate 		((flags & AI_V4MAPPED) && he == NULL))))
3580Sstevel@tonic-gate 		he = _gethostbyname(&argp->h_errno, argp->key.ipnode.name);
3590Sstevel@tonic-gate 	else
3600Sstevel@tonic-gate 		he = NULL;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	/* Merge the results */
3630Sstevel@tonic-gate 	if (he != NULL) {
3640Sstevel@tonic-gate 		mergeAddrs = cloneAddrList(he, v6Addrs, &converr);
3650Sstevel@tonic-gate 		if (converr) {
3660Sstevel@tonic-gate 			if (v6Name != 0)
3670Sstevel@tonic-gate 				free(v6Name);
3680Sstevel@tonic-gate 			if (v6Addrs != 0)
3690Sstevel@tonic-gate 				free(v6Addrs);
3700Sstevel@tonic-gate 			if (v6Aliases != 0)
3710Sstevel@tonic-gate 				free(v6Aliases);
3720Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3730Sstevel@tonic-gate 			argp->erange = 1;
3740Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3750Sstevel@tonic-gate 						old_retry);
3760Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		he->h_addr_list = (char **)mergeAddrs;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 		mergeAliases = cloneAliasList(he, v6Aliases, &converr);
3810Sstevel@tonic-gate 		if (converr) {
3820Sstevel@tonic-gate 			if (v6Name != 0)
3830Sstevel@tonic-gate 				free(v6Name);
3840Sstevel@tonic-gate 			if (v6Addrs != 0)
3850Sstevel@tonic-gate 				free(v6Addrs);
3860Sstevel@tonic-gate 			if (v6Aliases != 0)
3870Sstevel@tonic-gate 				free(v6Aliases);
3880Sstevel@tonic-gate 			if (mergeAddrs != 0)
3890Sstevel@tonic-gate 				free(mergeAddrs);
3900Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3910Sstevel@tonic-gate 			argp->erange = 1;
3920Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3930Sstevel@tonic-gate 						old_retry);
3940Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3950Sstevel@tonic-gate 		}
3960Sstevel@tonic-gate 		he->h_aliases = mergeAliases;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 		/* reset h_length, h_addrtype */
3990Sstevel@tonic-gate 		he->h_length = sizeof (struct in6_addr);
4000Sstevel@tonic-gate 		he->h_addrtype = AF_INET6;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	} else if (gotv6) {
4030Sstevel@tonic-gate 		v6he.h_name = v6Name;
4040Sstevel@tonic-gate 		v6he.h_length = sizeof (struct in6_addr);
4050Sstevel@tonic-gate 		v6he.h_addrtype = AF_INET6;
4060Sstevel@tonic-gate 		v6he.h_addr_list = (char **)v6Addrs;
4070Sstevel@tonic-gate 		v6he.h_aliases = v6Aliases;
4080Sstevel@tonic-gate 		he = &v6he;
4090Sstevel@tonic-gate 		argp->h_errno = v6_h_errno;
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
412*2830Sdjl 	if (he != NULL) {
413*2830Sdjl 		/*
414*2830Sdjl 		 * if asked to return data in string,
415*2830Sdjl 		 * convert the hostent structure into
416*2830Sdjl 		 * string data
417*2830Sdjl 		 */
418*2830Sdjl 		if (argp->buf.result == NULL) {
419*2830Sdjl 			ret = ent2str(he, a, AF_INET6);
420*2830Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
421*2830Sdjl 				argp->returnval = argp->buf.buffer;
4220Sstevel@tonic-gate 		} else {
423*2830Sdjl 			ret = ent2result(he, a, AF_INET6);
424*2830Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
425*2830Sdjl 				argp->returnval = argp->buf.result;
426*2830Sdjl 		}
427*2830Sdjl 
428*2830Sdjl 		if (ret != NSS_STR_PARSE_SUCCESS) {
4290Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
4300Sstevel@tonic-gate 			if (ret == NSS_STR_PARSE_ERANGE) {
4310Sstevel@tonic-gate 				argp->erange = 1;
4320Sstevel@tonic-gate 			}
4330Sstevel@tonic-gate 		}
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	if (v6Name != 0)
4370Sstevel@tonic-gate 		free(v6Name);
4380Sstevel@tonic-gate 	if (v6Addrs != 0)
4390Sstevel@tonic-gate 		free(v6Addrs);
4400Sstevel@tonic-gate 	if (v6Aliases != 0)
4410Sstevel@tonic-gate 		free(v6Aliases);
4420Sstevel@tonic-gate 	if (mergeAddrs != 0)
4430Sstevel@tonic-gate 		free(mergeAddrs);
4440Sstevel@tonic-gate 	if (mergeAliases != 0)
4450Sstevel@tonic-gate 		free(mergeAliases);
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	switch_resolver_reset(mt_disabled, oldmask, old_retry);
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	return (_herrno2nss(argp->h_errno));
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate extern nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *);
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate static nss_status_t
4560Sstevel@tonic-gate getbyaddr(be, a)
4570Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4580Sstevel@tonic-gate 	void			*a;
4590Sstevel@tonic-gate {
4600Sstevel@tonic-gate 	/* uses the same getbyaddr from IPv4 */
4610Sstevel@tonic-gate 	return (__nss_dns_getbyaddr(be, a));
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate /*ARGSUSED*/
4660Sstevel@tonic-gate static nss_status_t
4670Sstevel@tonic-gate _nss_dns_getent(be, args)
4680Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4690Sstevel@tonic-gate 	void			*args;
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate /*ARGSUSED*/
4760Sstevel@tonic-gate static nss_status_t
4770Sstevel@tonic-gate _nss_dns_setent(be, dummy)
4780Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4790Sstevel@tonic-gate 	void			*dummy;
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4820Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate /*ARGSUSED*/
4870Sstevel@tonic-gate static nss_status_t
4880Sstevel@tonic-gate _nss_dns_endent(be, dummy)
4890Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4900Sstevel@tonic-gate 	void			*dummy;
4910Sstevel@tonic-gate {
4920Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4930Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate /*ARGSUSED*/
4980Sstevel@tonic-gate static nss_status_t
4990Sstevel@tonic-gate _nss_dns_destr(be, dummy)
5000Sstevel@tonic-gate 	dns_backend_ptr_t	be;
5010Sstevel@tonic-gate 	void			*dummy;
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate 	nss_status_t	errp;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	if (be != 0) {
5060Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
5070Sstevel@tonic-gate 		sigset_t	oldmask, newmask;
5080Sstevel@tonic-gate 		int		mt_disabled = 1;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 		if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
5110Sstevel@tonic-gate 			(void) sigfillset(&newmask);
5120Sstevel@tonic-gate 			_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
5130Sstevel@tonic-gate 			_mutex_lock(&one_lane);
5140Sstevel@tonic-gate 		}
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		_endhostent(&errp);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 		if (mt_disabled) {
5190Sstevel@tonic-gate 			_mutex_unlock(&one_lane);
5200Sstevel@tonic-gate 			_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
5210Sstevel@tonic-gate 		} else {
5220Sstevel@tonic-gate 			(void) (*disable_mt)();
5230Sstevel@tonic-gate 		}
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 		free(be);
5260Sstevel@tonic-gate 	}
5270Sstevel@tonic-gate 	return (NSS_SUCCESS);   /* In case anyone is dumb enough to check */
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate static dns_backend_op_t ipnodes_ops[] = {
5330Sstevel@tonic-gate 	_nss_dns_destr,
5340Sstevel@tonic-gate 	_nss_dns_endent,
5350Sstevel@tonic-gate 	_nss_dns_setent,
5360Sstevel@tonic-gate 	_nss_dns_getent,
5370Sstevel@tonic-gate 	getbyname,
5380Sstevel@tonic-gate 	getbyaddr,
5390Sstevel@tonic-gate };
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate /*ARGSUSED*/
5420Sstevel@tonic-gate nss_backend_t *
5430Sstevel@tonic-gate _nss_dns_ipnodes_constr(dummy1, dummy2, dummy3)
5440Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
5450Sstevel@tonic-gate {
5460Sstevel@tonic-gate 	return (_nss_dns_constr(ipnodes_ops,
5470Sstevel@tonic-gate 		sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
5480Sstevel@tonic-gate }
549*2830Sdjl 
550*2830Sdjl /*
551*2830Sdjl  * optional NSS2 packed backend gethostsbyipnode with ttl
552*2830Sdjl  * entry point.
553*2830Sdjl  *
554*2830Sdjl  * Returns:
555*2830Sdjl  *	NSS_SUCCESS - successful
556*2830Sdjl  *	NSS_NOTFOUND - successful but nothing found
557*2830Sdjl  *	NSS_ERROR - fallback to NSS backend lookup mode
558*2830Sdjl  * If successful, buffer will be filled with valid data
559*2830Sdjl  *
560*2830Sdjl  */
561*2830Sdjl 
562*2830Sdjl /*ARGSUSED*/
563*2830Sdjl nss_status_t
564*2830Sdjl _nss_get_dns_ipnodes_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep)
565*2830Sdjl {
566*2830Sdjl 	return (_nss_dns_gethost_withttl(*bufp, *sizep, 1));
567*2830Sdjl }
568