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