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