xref: /onnv-gate/usr/src/lib/nsswitch/dns/common/gethostent6.c (revision 5161:6118969b7712)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*5161Smichen  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
242830Sdjl  */
252830Sdjl /*
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 
1182830Sdjl 	(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  */
1332830Sdjl 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) {
1792830Sdjl 			/* 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 {
1832830Sdjl 			(void) memcpy(addrArray[i], h->h_addr_list[i],
1842830Sdjl 				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;
2162830Sdjl 	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;
2642830Sdjl 		(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 
2802830Sdjl /*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;
292*5161Smichen 	struct hostent	mhe;
2930Sstevel@tonic-gate 	char		*v6Name = 0;
2940Sstevel@tonic-gate 	struct in6_addr	**v6Addrs = 0, **mergeAddrs = 0;
2950Sstevel@tonic-gate 	char		**v6Aliases = 0, **mergeAliases = 0;
2960Sstevel@tonic-gate 	int		v6_h_errno;
2970Sstevel@tonic-gate 	int		old_retry;
2980Sstevel@tonic-gate 	int		af = argp->key.ipnode.af_family;
2990Sstevel@tonic-gate 	int		flags = argp->key.ipnode.flags;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	/* Now get the AAAA records */
3040Sstevel@tonic-gate 	if (af == AF_INET6)
3050Sstevel@tonic-gate 		he = _nss_dns_gethostbyname2(&argp->h_errno,
3060Sstevel@tonic-gate 					argp->key.ipnode.name);
3070Sstevel@tonic-gate 	if (he != NULL) {
3080Sstevel@tonic-gate 		/*
3090Sstevel@tonic-gate 		 * pointer in "he" is part of a static pthread key in libresolv
3100Sstevel@tonic-gate 		 * It should be treated as read only.
3110Sstevel@tonic-gate 		 * So clone a copy first.
3120Sstevel@tonic-gate 		 */
3130Sstevel@tonic-gate 		v6Name = cloneName(he, &converr);
3140Sstevel@tonic-gate 		if (converr) {
3150Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3160Sstevel@tonic-gate 			argp->erange = 1;
3170Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3180Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3190Sstevel@tonic-gate 		}
3200Sstevel@tonic-gate 		v6Addrs = cloneAddrList(he, 0, &converr);
3210Sstevel@tonic-gate 		if (converr) {
3220Sstevel@tonic-gate 			if (v6Name != 0)
3230Sstevel@tonic-gate 				free(v6Name);
3240Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3250Sstevel@tonic-gate 			argp->erange = 1;
3260Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3270Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3280Sstevel@tonic-gate 		}
3290Sstevel@tonic-gate 		v6Aliases = cloneAliasList(he, 0, &converr);
3300Sstevel@tonic-gate 		if (converr) {
3310Sstevel@tonic-gate 			if (v6Name != 0)
3320Sstevel@tonic-gate 				free(v6Name);
3330Sstevel@tonic-gate 			if (v6Addrs != 0)
3340Sstevel@tonic-gate 				free(v6Addrs);
3350Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3360Sstevel@tonic-gate 			argp->erange = 1;
3370Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask, old_retry);
3380Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 		v6_h_errno = argp->h_errno;
3410Sstevel@tonic-gate 		gotv6 = 1;
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	/*
3450Sstevel@tonic-gate 	 * The conditions to search "A" records:
3460Sstevel@tonic-gate 	 * 1. af is AF_INET
3470Sstevel@tonic-gate 	 * 2. if af is AF_INET6
3480Sstevel@tonic-gate 	 *    then flags are either
3490Sstevel@tonic-gate 	 *	1) (AI_ALL | AI_V4MAPPED) or
3500Sstevel@tonic-gate 	 *	2) AI_V4MAPPED and he == NULL
3510Sstevel@tonic-gate 	 *	    (No V6 addresses found or no search for V6 at all)
3520Sstevel@tonic-gate 	 */
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	/* Get the A records, and store the information */
3550Sstevel@tonic-gate 	if ((af == AF_INET) ||
3560Sstevel@tonic-gate 	    ((af == AF_INET6) &&
3570Sstevel@tonic-gate 		((flags & (AI_ALL | AI_V4MAPPED)) ||
3580Sstevel@tonic-gate 		((flags & AI_V4MAPPED) && he == NULL))))
3590Sstevel@tonic-gate 		he = _gethostbyname(&argp->h_errno, argp->key.ipnode.name);
3600Sstevel@tonic-gate 	else
3610Sstevel@tonic-gate 		he = NULL;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	/* Merge the results */
3640Sstevel@tonic-gate 	if (he != NULL) {
365*5161Smichen 		mhe = *he;
3660Sstevel@tonic-gate 		mergeAddrs = cloneAddrList(he, v6Addrs, &converr);
3670Sstevel@tonic-gate 		if (converr) {
3680Sstevel@tonic-gate 			if (v6Name != 0)
3690Sstevel@tonic-gate 				free(v6Name);
3700Sstevel@tonic-gate 			if (v6Addrs != 0)
3710Sstevel@tonic-gate 				free(v6Addrs);
3720Sstevel@tonic-gate 			if (v6Aliases != 0)
3730Sstevel@tonic-gate 				free(v6Aliases);
3740Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3750Sstevel@tonic-gate 			argp->erange = 1;
3760Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3770Sstevel@tonic-gate 						old_retry);
3780Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3790Sstevel@tonic-gate 		}
380*5161Smichen 		mhe.h_addr_list = (char **)mergeAddrs;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 		mergeAliases = cloneAliasList(he, v6Aliases, &converr);
3830Sstevel@tonic-gate 		if (converr) {
3840Sstevel@tonic-gate 			if (v6Name != 0)
3850Sstevel@tonic-gate 				free(v6Name);
3860Sstevel@tonic-gate 			if (v6Addrs != 0)
3870Sstevel@tonic-gate 				free(v6Addrs);
3880Sstevel@tonic-gate 			if (v6Aliases != 0)
3890Sstevel@tonic-gate 				free(v6Aliases);
3900Sstevel@tonic-gate 			if (mergeAddrs != 0)
3910Sstevel@tonic-gate 				free(mergeAddrs);
3920Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
3930Sstevel@tonic-gate 			argp->erange = 1;
3940Sstevel@tonic-gate 			switch_resolver_reset(mt_disabled, oldmask,
3950Sstevel@tonic-gate 						old_retry);
3960Sstevel@tonic-gate 			return (_herrno2nss(argp->h_errno));
3970Sstevel@tonic-gate 		}
398*5161Smichen 		mhe.h_aliases = mergeAliases;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 		/* reset h_length, h_addrtype */
401*5161Smichen 		mhe.h_length = sizeof (struct in6_addr);
402*5161Smichen 		mhe.h_addrtype = AF_INET6;
403*5161Smichen 		he = &mhe;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	} else if (gotv6) {
4060Sstevel@tonic-gate 		v6he.h_name = v6Name;
4070Sstevel@tonic-gate 		v6he.h_length = sizeof (struct in6_addr);
4080Sstevel@tonic-gate 		v6he.h_addrtype = AF_INET6;
4090Sstevel@tonic-gate 		v6he.h_addr_list = (char **)v6Addrs;
4100Sstevel@tonic-gate 		v6he.h_aliases = v6Aliases;
4110Sstevel@tonic-gate 		he = &v6he;
4120Sstevel@tonic-gate 		argp->h_errno = v6_h_errno;
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 
4152830Sdjl 	if (he != NULL) {
4162830Sdjl 		/*
4172830Sdjl 		 * if asked to return data in string,
4182830Sdjl 		 * convert the hostent structure into
4192830Sdjl 		 * string data
4202830Sdjl 		 */
4212830Sdjl 		if (argp->buf.result == NULL) {
4222830Sdjl 			ret = ent2str(he, a, AF_INET6);
4232830Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
4242830Sdjl 				argp->returnval = argp->buf.buffer;
4250Sstevel@tonic-gate 		} else {
4262830Sdjl 			ret = ent2result(he, a, AF_INET6);
4272830Sdjl 			if (ret == NSS_STR_PARSE_SUCCESS)
4282830Sdjl 				argp->returnval = argp->buf.result;
4292830Sdjl 		}
4302830Sdjl 
4312830Sdjl 		if (ret != NSS_STR_PARSE_SUCCESS) {
4320Sstevel@tonic-gate 			argp->h_errno = HOST_NOT_FOUND;
4330Sstevel@tonic-gate 			if (ret == NSS_STR_PARSE_ERANGE) {
4340Sstevel@tonic-gate 				argp->erange = 1;
4350Sstevel@tonic-gate 			}
4360Sstevel@tonic-gate 		}
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	if (v6Name != 0)
4400Sstevel@tonic-gate 		free(v6Name);
4410Sstevel@tonic-gate 	if (v6Addrs != 0)
4420Sstevel@tonic-gate 		free(v6Addrs);
4430Sstevel@tonic-gate 	if (v6Aliases != 0)
4440Sstevel@tonic-gate 		free(v6Aliases);
4450Sstevel@tonic-gate 	if (mergeAddrs != 0)
4460Sstevel@tonic-gate 		free(mergeAddrs);
4470Sstevel@tonic-gate 	if (mergeAliases != 0)
4480Sstevel@tonic-gate 		free(mergeAliases);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	switch_resolver_reset(mt_disabled, oldmask, old_retry);
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	return (_herrno2nss(argp->h_errno));
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate extern nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate static nss_status_t
4590Sstevel@tonic-gate getbyaddr(be, a)
4600Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4610Sstevel@tonic-gate 	void			*a;
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate 	/* uses the same getbyaddr from IPv4 */
4640Sstevel@tonic-gate 	return (__nss_dns_getbyaddr(be, a));
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate /*ARGSUSED*/
4690Sstevel@tonic-gate static nss_status_t
4700Sstevel@tonic-gate _nss_dns_getent(be, args)
4710Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4720Sstevel@tonic-gate 	void			*args;
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate /*ARGSUSED*/
4790Sstevel@tonic-gate static nss_status_t
4800Sstevel@tonic-gate _nss_dns_setent(be, dummy)
4810Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4820Sstevel@tonic-gate 	void			*dummy;
4830Sstevel@tonic-gate {
4840Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4850Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate /*ARGSUSED*/
4900Sstevel@tonic-gate static nss_status_t
4910Sstevel@tonic-gate _nss_dns_endent(be, dummy)
4920Sstevel@tonic-gate 	dns_backend_ptr_t	be;
4930Sstevel@tonic-gate 	void			*dummy;
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate 	/* XXXX not implemented at this point */
4960Sstevel@tonic-gate 	return (NSS_UNAVAIL);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate /*ARGSUSED*/
5010Sstevel@tonic-gate static nss_status_t
5020Sstevel@tonic-gate _nss_dns_destr(be, dummy)
5030Sstevel@tonic-gate 	dns_backend_ptr_t	be;
5040Sstevel@tonic-gate 	void			*dummy;
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate 	nss_status_t	errp;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	if (be != 0) {
5090Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
5100Sstevel@tonic-gate 		sigset_t	oldmask, newmask;
5110Sstevel@tonic-gate 		int		mt_disabled = 1;
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 		if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
5140Sstevel@tonic-gate 			(void) sigfillset(&newmask);
5150Sstevel@tonic-gate 			_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
5160Sstevel@tonic-gate 			_mutex_lock(&one_lane);
5170Sstevel@tonic-gate 		}
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 		_endhostent(&errp);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 		if (mt_disabled) {
5220Sstevel@tonic-gate 			_mutex_unlock(&one_lane);
5230Sstevel@tonic-gate 			_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
5240Sstevel@tonic-gate 		} else {
5250Sstevel@tonic-gate 			(void) (*disable_mt)();
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		free(be);
5290Sstevel@tonic-gate 	}
5300Sstevel@tonic-gate 	return (NSS_SUCCESS);   /* In case anyone is dumb enough to check */
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate static dns_backend_op_t ipnodes_ops[] = {
5360Sstevel@tonic-gate 	_nss_dns_destr,
5370Sstevel@tonic-gate 	_nss_dns_endent,
5380Sstevel@tonic-gate 	_nss_dns_setent,
5390Sstevel@tonic-gate 	_nss_dns_getent,
5400Sstevel@tonic-gate 	getbyname,
5410Sstevel@tonic-gate 	getbyaddr,
5420Sstevel@tonic-gate };
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate /*ARGSUSED*/
5450Sstevel@tonic-gate nss_backend_t *
5460Sstevel@tonic-gate _nss_dns_ipnodes_constr(dummy1, dummy2, dummy3)
5470Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate 	return (_nss_dns_constr(ipnodes_ops,
5500Sstevel@tonic-gate 		sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
5510Sstevel@tonic-gate }
5522830Sdjl 
5532830Sdjl /*
5542830Sdjl  * optional NSS2 packed backend gethostsbyipnode with ttl
5552830Sdjl  * entry point.
5562830Sdjl  *
5572830Sdjl  * Returns:
5582830Sdjl  *	NSS_SUCCESS - successful
5592830Sdjl  *	NSS_NOTFOUND - successful but nothing found
5602830Sdjl  *	NSS_ERROR - fallback to NSS backend lookup mode
5612830Sdjl  * If successful, buffer will be filled with valid data
5622830Sdjl  *
5632830Sdjl  */
5642830Sdjl 
5652830Sdjl /*ARGSUSED*/
5662830Sdjl nss_status_t
5672830Sdjl _nss_get_dns_ipnodes_name(dns_backend_ptr_t *be, void **bufp, size_t *sizep)
5682830Sdjl {
5692830Sdjl 	return (_nss_dns_gethost_withttl(*bufp, *sizep, 1));
5702830Sdjl }
571