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