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