summaryrefslogtreecommitdiff
path: root/usr/src/lib/nsswitch/dns
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/nsswitch/dns
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/nsswitch/dns')
-rw-r--r--usr/src/lib/nsswitch/dns/Makefile47
-rw-r--r--usr/src/lib/nsswitch/dns/Makefile.com49
-rw-r--r--usr/src/lib/nsswitch/dns/amd64/Makefile36
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_common.c167
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_common.h88
-rw-r--r--usr/src/lib/nsswitch/dns/common/dns_mt.c312
-rw-r--r--usr/src/lib/nsswitch/dns/common/gethostent.c416
-rw-r--r--usr/src/lib/nsswitch/dns/common/gethostent6.c534
-rw-r--r--usr/src/lib/nsswitch/dns/common/mapfile-vers46
-rw-r--r--usr/src/lib/nsswitch/dns/i386/Makefile36
-rw-r--r--usr/src/lib/nsswitch/dns/sparc/Makefile36
-rw-r--r--usr/src/lib/nsswitch/dns/sparcv9/Makefile37
12 files changed, 1804 insertions, 0 deletions
diff --git a/usr/src/lib/nsswitch/dns/Makefile b/usr/src/lib/nsswitch/dns/Makefile
new file mode 100644
index 0000000000..9fc3326ce3
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/Makefile
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1991 - 1996, by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/nsswitch/dns/Makefile
+
+include ../../../Makefile.master
+
+FILES_SUBDIRS= $(MACH) $(BUILD64) $(MACH64)
+
+all:= TARGET= all
+clean:= TARGET= clean
+clobber:= TARGET= clobber
+install:= TARGET= install
+lint:= TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(FILES_SUBDIRS)
+
+$(MACH) $(MACH64): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/nsswitch/dns/Makefile.com b/usr/src/lib/nsswitch/dns/Makefile.com
new file mode 100644
index 0000000000..f4aa3f433c
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/Makefile.com
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/nsswitch/dns/Makefile.com
+
+LIBRARY = libnss_dns.a
+VERS = .1
+
+OBJECTS = gethostent.o \
+ gethostent6.o \
+ dns_mt.o \
+ dns_common.o
+
+# include common nsswitch library definitions.
+include ../../Makefile.com
+
+# install this library in the root filesystem
+include ../../../Makefile.rootfs
+
+# Appropriate libresolv loaded at runtime. This is the default, to be dlopened
+# if no libresolv was provided by the application.
+CPPFLAGS += -DNSS_DNS_LIBRESOLV=\"libresolv.so.2\"
+
+LDLIBS += -lnsl
+DYNLIB1 = nss_dns.so$(VERS)
diff --git a/usr/src/lib/nsswitch/dns/amd64/Makefile b/usr/src/lib/nsswitch/dns/amd64/Makefile
new file mode 100644
index 0000000000..1334471b25
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/amd64/Makefile
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+LIBS = $(DYNLIB1)
+
+include ../../Makefile.targ
+
+install: all $(ROOT64DYNLIB)
diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.c b/usr/src/lib/nsswitch/dns/common/dns_common.c
new file mode 100644
index 0000000000..da766c4d12
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c
@@ -0,0 +1,167 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * dns_common.c
+ *
+ * Copyright (c) 1993,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "dns_common.h"
+
+#define DNS_ALIASES 0
+#define DNS_ADDRLIST 1
+#define DNS_MAPDLIST 2
+
+static int
+dns_netdb_aliases(from_list, to_list, aliaspp, type, count, af_type)
+ char **from_list, **to_list, **aliaspp;
+ int type, *count, af_type;
+{
+ char *fstr;
+ int cnt = 0;
+ size_t len;
+
+ *count = 0;
+ if ((char *)to_list >= *aliaspp)
+ return (NSS_STR_PARSE_ERANGE);
+
+ for (fstr = from_list[cnt]; fstr != NULL; fstr = from_list[cnt]) {
+ if (type == DNS_ALIASES)
+ len = strlen(fstr) + 1;
+ else
+ len = (af_type == AF_INET) ? sizeof (struct in_addr)
+ : sizeof (struct in6_addr);
+ *aliaspp -= len;
+ to_list[cnt] = *aliaspp;
+ if (*aliaspp <= (char *)&to_list[cnt+1])
+ return (NSS_STR_PARSE_ERANGE);
+ if (type == DNS_MAPDLIST) {
+ struct in6_addr *addr6p = (struct in6_addr *) *aliaspp;
+
+ (void) memset(addr6p, '\0', sizeof (struct in6_addr));
+ (void) memcpy(&addr6p->s6_addr[12], fstr,
+ sizeof (struct in_addr));
+ addr6p->s6_addr[10] = 0xffU;
+ addr6p->s6_addr[11] = 0xffU;
+ ++cnt;
+ } else {
+ (void) memcpy (*aliaspp, fstr, len);
+ ++cnt;
+ }
+ }
+ to_list[cnt] = NULL;
+
+ *count = cnt;
+ if (cnt == 0)
+ return (NSS_STR_PARSE_PARSE);
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
+
+
+int
+ent2result(he, argp, af_type)
+ struct hostent *he;
+ nss_XbyY_args_t *argp;
+ int af_type;
+{
+ char *buffer, *limit;
+ int buflen = argp->buf.buflen;
+ int ret, count;
+ size_t len;
+ struct hostent *host;
+ struct in_addr *addrp;
+ struct in6_addr *addrp6;
+
+ limit = argp->buf.buffer + buflen;
+ host = (struct hostent *) argp->buf.result;
+ buffer = argp->buf.buffer;
+
+ /* h_addrtype and h_length */
+ host->h_addrtype = af_type;
+ host->h_length = (af_type == AF_INET) ? sizeof (struct in_addr)
+ : sizeof (struct in6_addr);
+
+ /* h_name */
+ len = strlen(he->h_name) + 1;
+ host->h_name = buffer;
+ if (host->h_name + len >= limit)
+ return (NSS_STR_PARSE_ERANGE);
+ (void) memcpy(host->h_name, he->h_name, len);
+ buffer += len;
+
+ /* h_addr_list */
+ if (af_type == AF_INET) {
+ addrp = (struct in_addr *) ROUND_DOWN(limit, sizeof (*addrp));
+ host->h_addr_list = (char **)
+ ROUND_UP(buffer, sizeof (char **));
+ ret = dns_netdb_aliases(he->h_addr_list, host->h_addr_list,
+ (char **)&addrp, DNS_ADDRLIST, &count, af_type);
+ if (ret != NSS_STR_PARSE_SUCCESS)
+ return (ret);
+ /* h_aliases */
+ host->h_aliases = host->h_addr_list + count + 1;
+ ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
+ (char **)&addrp, DNS_ALIASES, &count, af_type);
+ } else {
+ addrp6 = (struct in6_addr *)
+ ROUND_DOWN(limit, sizeof (*addrp6));
+ host->h_addr_list = (char **)
+ ROUND_UP(buffer, sizeof (char **));
+ if (he->h_addrtype == AF_INET && af_type == AF_INET6) {
+ ret = dns_netdb_aliases(he->h_addr_list,
+ host->h_addr_list, (char **)&addrp6,
+ DNS_MAPDLIST, &count, af_type);
+ } else {
+ ret = dns_netdb_aliases(he->h_addr_list,
+ host->h_addr_list, (char **)&addrp6,
+ DNS_ADDRLIST, &count, af_type);
+ }
+ if (ret != NSS_STR_PARSE_SUCCESS)
+ return (ret);
+ /* h_aliases */
+ host->h_aliases = host->h_addr_list + count + 1;
+ ret = dns_netdb_aliases(he->h_aliases, host->h_aliases,
+ (char **)&addrp6, DNS_ALIASES, &count, af_type);
+ }
+ if (ret == NSS_STR_PARSE_PARSE)
+ ret = NSS_STR_PARSE_SUCCESS;
+
+ return (ret);
+}
+
+
+nss_backend_t *
+_nss_dns_constr(dns_backend_op_t ops[], int n_ops)
+{
+ dns_backend_ptr_t be;
+
+ if ((be = (dns_backend_ptr_t) malloc(sizeof (*be))) == 0)
+ return (0);
+
+ be->ops = ops;
+ be->n_ops = n_ops;
+ return ((nss_backend_t *) be);
+}
diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.h b/usr/src/lib/nsswitch/dns/common/dns_common.h
new file mode 100644
index 0000000000..7861cbb683
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.h
@@ -0,0 +1,88 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1993, 1998-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Common code and structures used by name-service-switch "dns" backends.
+ */
+
+#ifndef _DNS_COMMON_H
+#define _DNS_COMMON_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <strings.h>
+#include <thread.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <syslog.h>
+#include <nsswitch.h>
+#include <nss_dbdefs.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct dns_backend *dns_backend_ptr_t;
+typedef nss_status_t (*dns_backend_op_t)(dns_backend_ptr_t, void *);
+
+struct dns_backend {
+ dns_backend_op_t *ops;
+ nss_dbop_t n_ops;
+};
+
+/* multithreaded libresolv2 related functions and variables */
+extern void (*set_no_hosts_fallback)(void);
+extern void (*unset_no_hosts_fallback)(void);
+extern struct __res_state *(*set_res_retry)();
+extern int (*enable_mt)();
+extern int (*disable_mt)();
+extern int *(*get_h_errno)();
+extern int (*override_retry)(int);
+extern void switch_resolver_setup(int *, sigset_t *, int *);
+extern void switch_resolver_reset(int, sigset_t, int);
+extern mutex_t one_lane;
+
+extern int _thr_sigsetmask(int, const sigset_t *, sigset_t *);
+extern int _mutex_lock(mutex_t *);
+extern int _mutex_unlock(mutex_t *);
+extern const char *inet_ntop(int, const void *, char *, size_t);
+
+extern int ent2result(struct hostent *, nss_XbyY_args_t *, int);
+
+nss_backend_t *_nss_dns_constr(dns_backend_op_t *, int);
+extern nss_status_t _herrno2nss(int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DNS_COMMON_H */
diff --git a/usr/src/lib/nsswitch/dns/common/dns_mt.c b/usr/src/lib/nsswitch/dns/common/dns_mt.c
new file mode 100644
index 0000000000..7e236c40eb
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/dns_mt.c
@@ -0,0 +1,312 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1993, 1998-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * dns_mt.c
+ *
+ * This file contains all the MT related routines for the DNS backend.
+ */
+
+#include "dns_common.h"
+#include <dlfcn.h>
+
+/*
+ * If the DNS name service switch routines are used in a binary that depends
+ * on an older libresolv (libresolv.so.1, say), then having nss_dns.so.1 or
+ * libnss_dns.a depend on a newer libresolv (libresolv.so.2) will cause
+ * relocation problems. In particular, copy relocation of the _res structure
+ * (which changes in size from libresolv.so.1 to libresolv.so.2) could
+ * cause corruption, and result in a number of strange problems, including
+ * core dumps. Hence, we check if a libresolv is already loaded.
+ */
+
+#pragma init(_nss_dns_init)
+static void _nss_dns_init(void);
+
+extern struct hostent *res_gethostbyname(const char *);
+#pragma weak res_gethostbyname
+
+#define RES_SET_NO_HOSTS_FALLBACK "__res_set_no_hosts_fallback"
+extern void __res_set_no_hosts_fallback(void);
+#pragma weak __res_set_no_hosts_fallback
+
+#define RES_UNSET_NO_HOSTS_FALLBACK "__res_unset_no_hosts_fallback"
+extern void __res_unset_no_hosts_fallback(void);
+#pragma weak __res_unset_no_hosts_fallback
+
+#define RES_GET_RES "__res_get_res"
+extern struct __res_state *__res_get_res(void);
+#pragma weak __res_get_res
+
+#define RES_ENABLE_MT "__res_enable_mt"
+extern int __res_enable_mt(void);
+#pragma weak __res_enable_mt
+
+#define RES_DISABLE_MT "__res_disable_mt"
+extern int __res_disable_mt(void);
+#pragma weak __res_disable_mt
+
+#define RES_GET_H_ERRNO "__res_get_h_errno"
+extern int *__res_get_h_errno();
+#pragma weak __res_get_h_errno
+
+#define __H_ERRNO "__h_errno"
+extern int *__h_errno(void);
+#pragma weak __h_errno
+
+#define RES_OVERRIDE_RETRY "__res_override_retry"
+extern int __res_override_retry(int);
+#pragma weak __res_override_retry
+
+static void __fallback_set_no_hosts(void);
+static int *__fallback_h_errno(void);
+static int __fallback_override_retry(int);
+static int __is_mt_safe(void);
+
+void (*set_no_hosts_fallback)(void) = __fallback_set_no_hosts;
+void (*unset_no_hosts_fallback)(void) = __fallback_set_no_hosts;
+struct __res_state *(*set_res_retry)() = 0;
+int (*enable_mt)() = 0;
+int (*disable_mt)() = 0;
+int *(*get_h_errno)(void) = 0;
+int (*override_retry)(int) = 0;
+
+/* Usually set from the Makefile */
+#ifndef NSS_DNS_LIBRESOLV
+#define NSS_DNS_LIBRESOLV "libresolv.so.2"
+#endif
+
+/* From libresolv */
+extern int h_errno;
+
+mutex_t one_lane = DEFAULTMUTEX;
+
+void
+_nss_dns_init(void)
+{
+ struct hostent *(*f_hostent_ptr)();
+ void *reslib, (*f_void_ptr)();
+
+ /* If no libresolv library, then load one */
+ if ((f_hostent_ptr = res_gethostbyname) == 0) {
+ if ((reslib =
+ dlopen(NSS_DNS_LIBRESOLV, RTLD_LAZY|RTLD_GLOBAL)) != 0) {
+ /* Turn off /etc/hosts fall back in libresolv */
+ if ((f_void_ptr = (void (*)(void))dlsym(reslib,
+ RES_SET_NO_HOSTS_FALLBACK)) != 0) {
+ set_no_hosts_fallback = f_void_ptr;
+ }
+ if ((f_void_ptr = (void (*)(void))dlsym(reslib,
+ RES_SET_NO_HOSTS_FALLBACK)) != 0) {
+ unset_no_hosts_fallback = f_void_ptr;
+ }
+ /* Set number of resolver retries */
+ if ((override_retry = (int (*)(int))dlsym(reslib,
+ RES_OVERRIDE_RETRY)) == 0) {
+ set_res_retry =
+ (struct __res_state *(*)(void))dlsym(reslib,
+ RES_GET_RES);
+ override_retry = __fallback_override_retry;
+ }
+ /*
+ * Select h_errno retrieval function. A BIND 8.2.2
+ * libresolv.so.2 will have __h_errno, a BIND 8.1.2
+ * one will have __res_get_h_errno, and other
+ * versions may have nothing at all.
+ *
+ * Also try to bind to the relevant MT enable/disable
+ * functions which are also dependent on the version
+ * of the BIND libresolv.so.2 being used.
+ */
+ if ((get_h_errno = (int *(*)(void))dlsym(reslib,
+ __H_ERRNO)) != 0) {
+ /* BIND 8.2.2 libresolv.so.2 is MT safe. */
+ enable_mt = __is_mt_safe;
+ disable_mt = __is_mt_safe;
+ } else {
+ if ((get_h_errno =
+ (int *(*)(void))dlsym(reslib,
+ RES_GET_H_ERRNO)) == 0) {
+ get_h_errno = __fallback_h_errno;
+ }
+ /*
+ * Pre-BIND 8.2.2 was not MT safe. Try to
+ * bind the MT enable/disable functions.
+ */
+ if ((enable_mt = (int (*)(void))dlsym(reslib,
+ RES_ENABLE_MT)) != 0 &&
+ (disable_mt = (int (*)(void))dlsym(reslib,
+ RES_DISABLE_MT)) == 0) {
+ enable_mt = 0;
+ }
+ }
+ }
+ } else {
+ /* Libresolv already loaded */
+ if ((f_void_ptr = __res_set_no_hosts_fallback) != 0) {
+ set_no_hosts_fallback = f_void_ptr;
+ }
+ if ((f_void_ptr = __res_unset_no_hosts_fallback) != 0) {
+ unset_no_hosts_fallback = f_void_ptr;
+ }
+ if ((override_retry = __res_override_retry) == 0) {
+ set_res_retry = __res_get_res;
+ override_retry = __fallback_override_retry;
+ }
+ if ((get_h_errno = __h_errno) == 0 &&
+ (get_h_errno = __res_get_h_errno) == 0) {
+ get_h_errno = __fallback_h_errno;
+ }
+ if (get_h_errno == __h_errno) {
+ enable_mt = __is_mt_safe;
+ disable_mt = __is_mt_safe;
+ } else {
+ if ((enable_mt = __res_enable_mt) != 0 &&
+ (disable_mt = __res_disable_mt) == 0) {
+ enable_mt = 0;
+ }
+ }
+ }
+}
+
+
+/*
+ *
+ * Integration of BIND 8.1.2 introduced two new Sun private functions,
+ * __res_enable_mt() and __res_disable_mt(), that enabled and disabled
+ * MT mode per-thread. These functions are in the private libresolv.so.2
+ * interface, and intended for use by nss_dns.so.1.
+ *
+ * BIND 8.2.2 removed the need for those two functions. As similar
+ * functionality was provided in BIND further up the stack. However the
+ * functions remain to satisfy any application that directly called upon
+ * them. Only, __res_enable_mt() was modified to return failure.
+ * Indicated by a non-zero return value. So that those unconventional
+ * applications would not then presume that res_send() and friends are
+ * MT-safe, when in fact they are not.
+ *
+ * To prevent nss_dns from locking inappropriately __is_mt_safe() is
+ * called in place of __res_enable_mt() and __res_disable_mt() if BIND
+ * 8.2.2 libresolv.so.2 being used. __is_mt_safe() returns success
+ * indicated by a return code of zero. Signifying that no locking is
+ * necessary.
+ *
+ * MT applications making calls to gethostby*_r() or getipnodeby*()
+ * linked to libresolv.so.1 or linked statically with pre-BIND 8.2.2
+ * libresolv.a, doubtful as we don't ship a static version, would require
+ * locking within the nsswitch back-end. Hence the mechanism can not
+ * simply be removed.
+ *
+ */
+static int
+__is_mt_safe(void) {
+ return (0);
+}
+
+
+/*
+ * Return pointer to the global h_errno variable
+ */
+static int *
+__fallback_h_errno(void) {
+ return (&h_errno);
+}
+
+
+/*
+ * This function is called when the resolver library doesn't provide its
+ * own function to establish an override retry. If we can get a pointer
+ * to the per-thread _res (i.e., set_res_retry != 0), we set the retries
+ * directly, and return the previous number of retries. Otherwise, there's
+ * nothing to do.
+ */
+static int
+__fallback_override_retry(int retry) {
+ struct __res_state *res;
+ int old_retry = 0;
+
+ if (set_res_retry != 0) {
+ res = set_res_retry();
+ old_retry = res->retry;
+ res->retry = retry;
+ }
+ return (old_retry);
+}
+
+
+static void
+__fallback_set_no_hosts(void) {
+}
+
+
+/*
+ * Common code to enable/disable MT mode, set/unset no-/etc/hosts fallback,
+ * and to set the number of retries.
+ */
+void
+switch_resolver_setup(int *mt_disabled, sigset_t *oldmask, int *old_retry) {
+
+ /*
+ * Try to enable MT mode. If that isn't possible, mask signals,
+ * and mutex_lock.
+ */
+ *mt_disabled = 1;
+ if (enable_mt == 0 || (*mt_disabled = (*enable_mt)()) != 0) {
+ sigset_t newmask;
+ (void) sigfillset(&newmask);
+ _thr_sigsetmask(SIG_SETMASK, &newmask, oldmask);
+ _mutex_lock(&one_lane);
+ }
+
+ /*
+ * Disable any fallback to /etc/hosts (or /etc/inet/ipnodes, when
+ * libresolv knows about that file).
+ */
+ (*set_no_hosts_fallback)();
+
+ /*
+ * The NS switch wants to handle retries on its own.
+ */
+ *old_retry = (*override_retry)(1);
+}
+
+
+void
+switch_resolver_reset(int mt_disabled, sigset_t oldmask, int old_retry) {
+
+ if (mt_disabled) {
+ _mutex_unlock(&one_lane);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
+ } else {
+ (void) (*disable_mt)();
+ }
+
+ (*unset_no_hosts_fallback)();
+
+ (void) (*override_retry)(old_retry);
+}
diff --git a/usr/src/lib/nsswitch/dns/common/gethostent.c b/usr/src/lib/nsswitch/dns/common/gethostent.c
new file mode 100644
index 0000000000..38c8a44a3a
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/gethostent.c
@@ -0,0 +1,416 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1993, 1998-2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * gethostent.c
+ *
+ * In order to avoid duplicating libresolv code here, and since libresolv.so.2
+ * provides res_-equivalents of the getXbyY and {set,get}Xent, lets call
+ * re_gethostbyaddr() and so on from this file. Among other things, this
+ * should help us avoid problems like the one described in bug 1264386,
+ * where the internal getanswer() acquired new functionality in BIND 4.9.3,
+ * but the local copy of getanswer() in this file wasn't updated, so that new
+ * functionality wasn't available to the name service switch.
+ */
+
+#define gethostbyaddr res_gethostbyaddr
+#define gethostbyname res_gethostbyname
+#define gethostbyname2 res_gethostbyname2
+#define sethostent res_sethostent
+#define endhostent res_endhostent
+
+#include "dns_common.h"
+
+extern char *inet_ntoa(struct in_addr in);
+
+struct hostent *_gethostbyname(int *h_errnop, const char *name);
+static struct hostent *_gethostbyaddr(int *h_errnop, const char *addr,
+ int len, int type);
+struct hostent *_nss_dns_gethostbyname2(int *h_errnop, const char *name);
+
+#pragma weak res_gethostbyname
+#pragma weak res_gethostbyname2
+#pragma weak res_gethostbyaddr
+#pragma weak res_sethostent
+#pragma weak res_endhostent
+
+nss_backend_t *_nss_dns_constr(dns_backend_op_t ops[], int n_ops);
+nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *);
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+/*
+ * Internet Name Domain Server (DNS) only implementation.
+ */
+static struct hostent *
+_gethostbyaddr(int *h_errnop, const char *addr, int len, int type)
+{
+ struct hostent *hp;
+
+ hp = gethostbyaddr(addr, len, type);
+ *h_errnop = *get_h_errno();
+ return (hp);
+}
+
+struct hostent *
+_nss_dns_gethostbyname2(int *h_errnop, const char *name)
+{
+ struct hostent *hp;
+
+ hp = gethostbyname2(name, AF_INET6);
+ *h_errnop = *get_h_errno();
+ return (hp);
+}
+
+struct hostent *
+_gethostbyname(int *h_errnop, const char *name)
+{
+ struct hostent *hp;
+
+ hp = gethostbyname(name);
+ *h_errnop = *get_h_errno();
+ return (hp);
+}
+
+static void
+_sethostent(errp, stayopen)
+ nss_status_t *errp;
+ int stayopen;
+{
+ int ret;
+
+ ret = sethostent(stayopen);
+ if (ret == 0)
+ *errp = NSS_SUCCESS;
+ else
+ *errp = NSS_UNAVAIL;
+}
+
+static void
+_endhostent(errp)
+ nss_status_t *errp;
+{
+ int ret;
+
+ ret = endhostent();
+ if (ret == 0)
+ *errp = NSS_SUCCESS;
+ else
+ *errp = NSS_UNAVAIL;
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+getbyname(be, a)
+ dns_backend_ptr_t be;
+ void *a;
+{
+ struct hostent *he;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ int ret, mt_disabled;
+ int old_retry;
+ sigset_t oldmask;
+
+ switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
+
+ he = _gethostbyname(&argp->h_errno, argp->key.name);
+ if (he != NULL) {
+ ret = ent2result(he, a, AF_INET);
+ if (ret == NSS_STR_PARSE_SUCCESS) {
+ argp->returnval = argp->buf.result;
+ } else {
+ argp->h_errno = HOST_NOT_FOUND;
+ if (ret == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ }
+ }
+ }
+
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+
+ return (_herrno2nss(argp->h_errno));
+}
+
+
+
+/*ARGSUSED*/
+static nss_status_t
+getbyaddr(be, a)
+ dns_backend_ptr_t be;
+ void *a;
+{
+ return (__nss_dns_getbyaddr(be, a));
+}
+
+
+/*
+ * Exposing a DNS backend specific interface so that it doesn't conflict
+ * with other getbyaddr() routines from other switch backends.
+ */
+nss_status_t
+__nss_dns_getbyaddr(be, a)
+ dns_backend_ptr_t be;
+ void *a;
+{
+ size_t n;
+ struct hostent *he, *he2;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ int ret, save_h_errno, mt_disabled;
+ char **ans, hbuf[MAXHOSTNAMELEN];
+ char dst[INET6_ADDRSTRLEN];
+ struct in_addr unmapv4;
+ sigset_t oldmask;
+ int af, addrlen;
+ void *addrp;
+ int old_retry;
+
+ switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
+
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)argp->key.hostaddr.addr)) {
+ addrp = &unmapv4;
+ addrlen = sizeof (unmapv4);
+ af = AF_INET;
+ memcpy(addrp, &argp->key.hostaddr.addr[12], addrlen);
+ } else {
+ addrp = (void *)argp->key.hostaddr.addr;
+ addrlen = argp->key.hostaddr.len;
+ af = argp->key.hostaddr.type;
+ }
+ he = _gethostbyaddr(&argp->h_errno, addrp, addrlen, af);
+
+ if (he != NULL) {
+ if (strlen(he->h_name) >= MAXHOSTNAMELEN)
+ ret = NSS_STR_PARSE_ERANGE;
+ else {
+ /* save a copy of the (alleged) hostname */
+ (void) strcpy(hbuf, he->h_name);
+ n = strlen(hbuf);
+ if (n < MAXHOSTNAMELEN-1 && hbuf[n-1] != '.') {
+ (void) strcat(hbuf, ".");
+ }
+ ret = ent2result(he, a, argp->key.hostaddr.type);
+ save_h_errno = argp->h_errno;
+ }
+ if (ret == NSS_STR_PARSE_SUCCESS) {
+ /*
+ * check to make sure by doing a forward query
+ * We use _gethostbyname() to avoid the stack, and
+ * then we throw the result from argp->h_errno away,
+ * becase we don't care. And besides you want the
+ * return code from _gethostbyaddr() anyway.
+ */
+
+ if (af == AF_INET)
+ he2 = _gethostbyname(&argp->h_errno, hbuf);
+ else
+ he2 = _nss_dns_gethostbyname2(&argp->h_errno,
+ hbuf);
+ if (he2 != (struct hostent *)NULL) {
+
+ /* until we prove name and addr match */
+ argp->h_errno = HOST_NOT_FOUND;
+ for (ans = he2->h_addr_list; *ans; ans++)
+ if (memcmp(*ans, addrp, addrlen) ==
+ 0) {
+ argp->h_errno = save_h_errno;
+ argp->returnval = argp->buf.result;
+ break;
+ }
+ } else {
+
+ /*
+ * What to do if _gethostbyname() fails ???
+ * We assume they are doing something stupid
+ * like registering addresses but not names
+ * (some people actually think that provides
+ * some "security", through obscurity). So for
+ * these poor lost souls, because we can't
+ * PROVE spoofing and because we did try (and
+ * we don't want a bug filed on this), we let
+ * this go. And return the name from byaddr.
+ */
+ argp->h_errno = save_h_errno;
+ argp->returnval = argp->buf.result;
+ }
+ /* we've been spoofed, make sure to log it. */
+ if (argp->h_errno == HOST_NOT_FOUND) {
+ if (argp->key.hostaddr.type == AF_INET)
+ syslog(LOG_NOTICE, "gethostbyaddr: %s != %s",
+ hbuf, inet_ntoa(*(struct in_addr *)argp->key.hostaddr.addr));
+ else
+ syslog(LOG_NOTICE, "gethostbyaddr: %s != %s",
+ hbuf, inet_ntop(AF_INET6, (void *) argp->key.hostaddr.addr,
+ dst, sizeof (dst)));
+ }
+ } else {
+ argp->h_errno = HOST_NOT_FOUND;
+ if (ret == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ }
+ }
+ }
+
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+
+ return (_herrno2nss(argp->h_errno));
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_getent(be, args)
+ dns_backend_ptr_t be;
+ void *args;
+{
+ return (NSS_UNAVAIL);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_setent(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ nss_status_t errp;
+
+ sigset_t oldmask, newmask;
+ int mt_disabled = 1;
+
+ /*
+ * Try to enable MT; if not, we have to single-thread libresolv
+ * access
+ */
+ if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
+ (void) sigfillset(&newmask);
+ _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
+ _mutex_lock(&one_lane);
+ }
+
+ _sethostent(&errp, 1);
+
+ if (mt_disabled) {
+ _mutex_unlock(&one_lane);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
+ } else {
+ (void) (*disable_mt)();
+ }
+
+ return (errp);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_endent(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ nss_status_t errp;
+
+ sigset_t oldmask, newmask;
+ int mt_disabled = 1;
+
+ /*
+ * Try to enable MT; if not, we have to single-thread libresolv
+ * access
+ */
+ if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
+ (void) sigfillset(&newmask);
+ _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
+ _mutex_lock(&one_lane);
+ }
+
+ _endhostent(&errp);
+
+ if (mt_disabled) {
+ _mutex_unlock(&one_lane);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
+ } else {
+ (void) (*disable_mt)();
+ }
+
+ return (errp);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_destr(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ nss_status_t errp;
+
+ if (be != 0) {
+ /* === Should change to invoke ops[ENDENT] ? */
+ sigset_t oldmask, newmask;
+ int mt_disabled = 1;
+
+ if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
+ (void) sigfillset(&newmask);
+ _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
+ _mutex_lock(&one_lane);
+ }
+
+ _endhostent(&errp);
+
+ if (mt_disabled) {
+ _mutex_unlock(&one_lane);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
+ } else {
+ (void) (*disable_mt)();
+ }
+
+ free(be);
+ }
+ return (NSS_SUCCESS); /* In case anyone is dumb enough to check */
+}
+
+
+static dns_backend_op_t host_ops[] = {
+ _nss_dns_destr,
+ _nss_dns_endent,
+ _nss_dns_setent,
+ _nss_dns_getent,
+ getbyname,
+ getbyaddr,
+};
+
+/*ARGSUSED*/
+nss_backend_t *
+_nss_dns_hosts_constr(dummy1, dummy2, dummy3)
+ const char *dummy1, *dummy2, *dummy3;
+{
+ return (_nss_dns_constr(host_ops,
+ sizeof (host_ops) / sizeof (host_ops[0])));
+}
diff --git a/usr/src/lib/nsswitch/dns/common/gethostent6.c b/usr/src/lib/nsswitch/dns/common/gethostent6.c
new file mode 100644
index 0000000000..e92ce6a356
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/gethostent6.c
@@ -0,0 +1,534 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1993-2000, 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * gethostent6.c
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This is the DNS backend for IPv6 addresses.
+ * getbyname() is a local routine, but getbyaddr() actually shares the
+ * same codes as the one in gethostent.c.
+ */
+
+#define endhostent res_endhostent
+
+#include <malloc.h>
+#include <stddef.h>
+#include <string.h>
+#include "dns_common.h"
+
+/*
+ * If the DNS name service switch routines are used in a binary that depends
+ * on an older libresolv (libresolv.so.1, say), then having nss_dns.so.1 or
+ * libnss_dns.a depend on a newer libresolv (libresolv.so.2) will cause
+ * relocation problems. In particular, copy relocation of the _res structure
+ * (which changes in size from libresolv.so.1 to libresolv.so.2) could
+ * cause corruption, and result in a number of strange problems, including
+ * core dumps. Hence, we check if a libresolv is already loaded.
+ */
+
+
+#pragma weak res_endhostent
+
+extern struct hostent *_gethostbyname(int *, const char *);
+extern struct hostent *_nss_dns_gethostbyname2(int *, const char *);
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+
+static void
+_endhostent(errp)
+ nss_status_t *errp;
+{
+ int ret;
+
+ ret = endhostent();
+ if (ret == 0)
+ *errp = NSS_SUCCESS;
+ else
+ *errp = NSS_UNAVAIL;
+}
+
+
+#ifdef RNDUP
+#undef RNDUP
+#endif
+#define RNDUP(x) ((1 + (((x)-1)/sizeof (void *))) * sizeof (void *))
+
+#ifdef PTROFF
+#undef PTROFF
+#endif
+#define PTROFF(p, o) (((o) == 0) ? 0 : (void *)((char *)(p) + (o)))
+
+
+/*
+ * Make a copy of h->h_name.
+ */
+static char *
+cloneName(struct hostent *h, int *outerr) {
+
+ char *name;
+ int len;
+ int error, *errp;
+
+ if (outerr)
+ errp = outerr;
+ else
+ errp = &error;
+
+ if (h == 0 || h->h_name == 0) {
+ *errp = 0;
+ return (0);
+ }
+
+ len = strlen(h->h_name);
+
+ if ((name = malloc(len+1)) == 0) {
+ *errp = 1;
+ return (0);
+ }
+
+ memcpy(name, h->h_name, len+1);
+
+ *errp = 0;
+ return (name);
+}
+
+
+/*
+ * Copy the h->h_addr_list[] array to a new array, and append the
+ * moreAddrs[] list. If h->h_addr_list[] contains IPv4 addresses,
+ * convert them to v4 mapped IPv6 addresses.
+ *
+ * Note: The pointers to the addresses in the moreAddrs[] array are copied,
+ * but not the IP addresses themselves.
+ */
+struct in6_addr **
+cloneAddrList(struct hostent *h, struct in6_addr **moreAddrs, int *outerr) {
+
+ struct in6_addr **addrArray, *addrList;
+ int domap, addrlen, i, j, addrCount, moreAddrCount = 0;
+
+ int error, *errp;
+
+ if (outerr)
+ errp = outerr;
+ else
+ errp = &error;
+
+ if (h == 0 || h->h_addr_list == 0) {
+ *errp = 0;
+ return (0);
+ }
+
+ /* Should we map v4 to IPv6 ? */
+ domap = (h->h_length == sizeof (struct in_addr)) &&
+ (h->h_addrtype == AF_INET);
+
+ /* If mapping, make sure we allocate enough memory for addresses */
+ addrlen = h->h_length;
+ if (domap && addrlen < sizeof (struct in6_addr))
+ addrlen = sizeof (struct in6_addr);
+
+ for (addrCount = 0; h->h_addr_list[addrCount]; addrCount++);
+
+ if (moreAddrs != 0) {
+ for (moreAddrCount = 0; moreAddrs[moreAddrCount];
+ moreAddrCount++);
+ }
+
+ if ((addrArray = malloc((addrCount+moreAddrCount+1)*sizeof (addrList) +
+ addrCount*addrlen)) == 0) {
+ *errp = 1;
+ return (0);
+ }
+
+ addrList = PTROFF(addrArray, (addrCount+moreAddrCount+1) *
+ sizeof (addrList));
+
+ for (i = 0; i < addrCount; i++) {
+ addrArray[i] = addrList;
+ if (domap) {
+ IN6_INADDR_TO_V4MAPPED(
+ (struct in_addr *)h->h_addr_list[i], addrArray[i]);
+ } else {
+ memcpy(addrArray[i], h->h_addr_list[i], addrlen);
+ }
+ addrList = PTROFF(addrList, addrlen);
+ }
+
+ for (j = 0; j < moreAddrCount; j++, i++) {
+ addrArray[i] = moreAddrs[j];
+ }
+
+ /* Last pointer should be NULL */
+ addrArray[i] = 0;
+
+ *errp = 0;
+ return (addrArray);
+}
+
+
+/*
+ * Create a new alias array that is is a copy of h->h_aliases[] plus
+ * the aliases in mergeAliases[] which aren't duplicates of any alias
+ * in h->h_aliases[].
+ *
+ * Note 1: Only the string pointers (NOT the strings) in the mergeAliases[]
+ * array are copied.
+ *
+ * Note 2: The duplicate aliases in mergeAliases[] are replaced by NULL
+ * pointers.
+ */
+static char **
+cloneAliasList(struct hostent *h, char **mergeAliases, int *outerr) {
+
+ char **aliasArray, *aliasList;
+ int i, j, k, aliasCount, mergeAliasCount = 0, realMac = 0;
+ int stringSize = 0;
+ int error, *errp;
+
+ if (outerr)
+ errp = outerr;
+ else
+ errp = &error;
+
+
+ if (h == 0 || h->h_aliases == 0) {
+ *errp = 0;
+ return (0);
+ }
+
+ for (aliasCount = 0; h->h_aliases[aliasCount]; aliasCount++) {
+ stringSize += RNDUP(strlen(h->h_aliases[aliasCount])+1);
+ }
+
+ if (mergeAliases != 0) {
+ for (; mergeAliases[mergeAliasCount]; mergeAliasCount++) {
+ int countThis = 1;
+ /* Skip duplicates */
+ for (j = 0; j < aliasCount; j++) {
+ if (strcmp(mergeAliases[mergeAliasCount],
+ h->h_aliases[j]) == 0) {
+ countThis = 0;
+ break;
+ }
+ }
+ if (countThis)
+ realMac++;
+ else
+ mergeAliases[mergeAliasCount] = 0;
+ }
+ }
+
+ if ((aliasArray = malloc((aliasCount+realMac+1)*sizeof (char **)+
+ stringSize)) == 0) {
+ *errp = 1;
+ return (0);
+ }
+
+ aliasList = PTROFF(aliasArray,
+ (aliasCount+realMac+1)*sizeof (char **));
+ for (i = 0; i < aliasCount; i++) {
+ int len = strlen(h->h_aliases[i]);
+ aliasArray[i] = aliasList;
+ memcpy(aliasArray[i], h->h_aliases[i], len+1);
+ aliasList = PTROFF(aliasList, RNDUP(len+1));
+ }
+
+ for (j = 0; j < mergeAliasCount; j++) {
+ if (mergeAliases[j] != 0) {
+ aliasArray[i++] = mergeAliases[j];
+ }
+ }
+
+ aliasArray[i] = 0;
+
+ *errp = 0;
+ return (aliasArray);
+}
+
+
+static nss_status_t
+getbyname(be, a)
+ dns_backend_ptr_t be;
+ void *a;
+{
+ struct hostent *he = NULL;
+ nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
+ int ret, mt_disabled;
+ sigset_t oldmask;
+ int converr = 0, gotv6 = 0;
+ struct hostent v6he;
+ char *v6Name = 0;
+ struct in6_addr **v6Addrs = 0, **mergeAddrs = 0;
+ char **v6Aliases = 0, **mergeAliases = 0;
+ int v6_h_errno;
+ int old_retry;
+ int af = argp->key.ipnode.af_family;
+ int flags = argp->key.ipnode.flags;
+
+ switch_resolver_setup(&mt_disabled, &oldmask, &old_retry);
+
+ /* Now get the AAAA records */
+ if (af == AF_INET6)
+ he = _nss_dns_gethostbyname2(&argp->h_errno,
+ argp->key.ipnode.name);
+ if (he != NULL) {
+ /*
+ * pointer in "he" is part of a static pthread key in libresolv
+ * It should be treated as read only.
+ * So clone a copy first.
+ */
+ v6Name = cloneName(he, &converr);
+ if (converr) {
+ argp->h_errno = HOST_NOT_FOUND;
+ argp->erange = 1;
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+ return (_herrno2nss(argp->h_errno));
+ }
+ v6Addrs = cloneAddrList(he, 0, &converr);
+ if (converr) {
+ if (v6Name != 0)
+ free(v6Name);
+ argp->h_errno = HOST_NOT_FOUND;
+ argp->erange = 1;
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+ return (_herrno2nss(argp->h_errno));
+ }
+ v6Aliases = cloneAliasList(he, 0, &converr);
+ if (converr) {
+ if (v6Name != 0)
+ free(v6Name);
+ if (v6Addrs != 0)
+ free(v6Addrs);
+ argp->h_errno = HOST_NOT_FOUND;
+ argp->erange = 1;
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+ return (_herrno2nss(argp->h_errno));
+ }
+ v6_h_errno = argp->h_errno;
+ gotv6 = 1;
+ }
+
+ /*
+ * The conditions to search "A" records:
+ * 1. af is AF_INET
+ * 2. if af is AF_INET6
+ * then flags are either
+ * 1) (AI_ALL | AI_V4MAPPED) or
+ * 2) AI_V4MAPPED and he == NULL
+ * (No V6 addresses found or no search for V6 at all)
+ */
+
+ /* Get the A records, and store the information */
+ if ((af == AF_INET) ||
+ ((af == AF_INET6) &&
+ ((flags & (AI_ALL | AI_V4MAPPED)) ||
+ ((flags & AI_V4MAPPED) && he == NULL))))
+ he = _gethostbyname(&argp->h_errno, argp->key.ipnode.name);
+ else
+ he = NULL;
+
+ /* Merge the results */
+ if (he != NULL) {
+ mergeAddrs = cloneAddrList(he, v6Addrs, &converr);
+ if (converr) {
+ if (v6Name != 0)
+ free(v6Name);
+ if (v6Addrs != 0)
+ free(v6Addrs);
+ if (v6Aliases != 0)
+ free(v6Aliases);
+ argp->h_errno = HOST_NOT_FOUND;
+ argp->erange = 1;
+ switch_resolver_reset(mt_disabled, oldmask,
+ old_retry);
+ return (_herrno2nss(argp->h_errno));
+ }
+ he->h_addr_list = (char **)mergeAddrs;
+
+ mergeAliases = cloneAliasList(he, v6Aliases, &converr);
+ if (converr) {
+ if (v6Name != 0)
+ free(v6Name);
+ if (v6Addrs != 0)
+ free(v6Addrs);
+ if (v6Aliases != 0)
+ free(v6Aliases);
+ if (mergeAddrs != 0)
+ free(mergeAddrs);
+ argp->h_errno = HOST_NOT_FOUND;
+ argp->erange = 1;
+ switch_resolver_reset(mt_disabled, oldmask,
+ old_retry);
+ return (_herrno2nss(argp->h_errno));
+ }
+ he->h_aliases = mergeAliases;
+
+ /* reset h_length, h_addrtype */
+ he->h_length = sizeof (struct in6_addr);
+ he->h_addrtype = AF_INET6;
+
+ } else if (gotv6) {
+ v6he.h_name = v6Name;
+ v6he.h_length = sizeof (struct in6_addr);
+ v6he.h_addrtype = AF_INET6;
+ v6he.h_addr_list = (char **)v6Addrs;
+ v6he.h_aliases = v6Aliases;
+ he = &v6he;
+ argp->h_errno = v6_h_errno;
+ }
+
+ if (he != 0) {
+ ret = ent2result(he, a, AF_INET6);
+ if (ret == NSS_STR_PARSE_SUCCESS) {
+ argp->returnval = argp->buf.result;
+ } else {
+ argp->h_errno = HOST_NOT_FOUND;
+ if (ret == NSS_STR_PARSE_ERANGE) {
+ argp->erange = 1;
+ }
+ }
+ }
+
+ if (v6Name != 0)
+ free(v6Name);
+ if (v6Addrs != 0)
+ free(v6Addrs);
+ if (v6Aliases != 0)
+ free(v6Aliases);
+ if (mergeAddrs != 0)
+ free(mergeAddrs);
+ if (mergeAliases != 0)
+ free(mergeAliases);
+
+ switch_resolver_reset(mt_disabled, oldmask, old_retry);
+
+ return (_herrno2nss(argp->h_errno));
+}
+
+
+extern nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *);
+
+static nss_status_t
+getbyaddr(be, a)
+ dns_backend_ptr_t be;
+ void *a;
+{
+ /* uses the same getbyaddr from IPv4 */
+ return (__nss_dns_getbyaddr(be, a));
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_getent(be, args)
+ dns_backend_ptr_t be;
+ void *args;
+{
+ return (NSS_UNAVAIL);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_setent(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ /* XXXX not implemented at this point */
+ return (NSS_UNAVAIL);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_endent(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ /* XXXX not implemented at this point */
+ return (NSS_UNAVAIL);
+}
+
+
+/*ARGSUSED*/
+static nss_status_t
+_nss_dns_destr(be, dummy)
+ dns_backend_ptr_t be;
+ void *dummy;
+{
+ nss_status_t errp;
+
+ if (be != 0) {
+ /* === Should change to invoke ops[ENDENT] ? */
+ sigset_t oldmask, newmask;
+ int mt_disabled = 1;
+
+ if (enable_mt == 0 || (mt_disabled = (*enable_mt)()) != 0) {
+ (void) sigfillset(&newmask);
+ _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
+ _mutex_lock(&one_lane);
+ }
+
+ _endhostent(&errp);
+
+ if (mt_disabled) {
+ _mutex_unlock(&one_lane);
+ _thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
+ } else {
+ (void) (*disable_mt)();
+ }
+
+ free(be);
+ }
+ return (NSS_SUCCESS); /* In case anyone is dumb enough to check */
+}
+
+
+
+static dns_backend_op_t ipnodes_ops[] = {
+ _nss_dns_destr,
+ _nss_dns_endent,
+ _nss_dns_setent,
+ _nss_dns_getent,
+ getbyname,
+ getbyaddr,
+};
+
+/*ARGSUSED*/
+nss_backend_t *
+_nss_dns_ipnodes_constr(dummy1, dummy2, dummy3)
+ const char *dummy1, *dummy2, *dummy3;
+{
+ return (_nss_dns_constr(ipnodes_ops,
+ sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
+}
diff --git a/usr/src/lib/nsswitch/dns/common/mapfile-vers b/usr/src/lib/nsswitch/dns/common/mapfile-vers
new file mode 100644
index 0000000000..6e44ffe568
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/common/mapfile-vers
@@ -0,0 +1,46 @@
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Generic interface definition for usr/src/lib/nsswitch/dns.
+#
+# For information regarding the establishment of versioned definitions see:
+# The Linker and Libraries Manual (version 2.5 or greater)
+# This is part of the Developers Guide in the Answerbook. Specifically refer
+# to Chapter 2 under section "Defining Additional Symbols" through section
+# "Reducing Symbol Scope", and Chapter 5 "Versioning".
+#
+# For specific OSNET rules for the modification (evolution) of these version
+# definitions see:
+# Policy for Shared Library Version Names and Interface Definitions
+
+
+SUNWprivate_1.1 {
+ global:
+ _nss_dns_hosts_constr;
+ _nss_dns_ipnodes_constr;
+ local:
+ *;
+};
diff --git a/usr/src/lib/nsswitch/dns/i386/Makefile b/usr/src/lib/nsswitch/dns/i386/Makefile
new file mode 100644
index 0000000000..164288fc1d
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/i386/Makefile
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 1993,2001-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/nsswitch/dns/i386/Makefile
+
+include ../Makefile.com
+
+LIBS = $(DYNLIB1)
+
+include ../../Makefile.targ
+
+install: all $(ROOTLIBS)
diff --git a/usr/src/lib/nsswitch/dns/sparc/Makefile b/usr/src/lib/nsswitch/dns/sparc/Makefile
new file mode 100644
index 0000000000..9ea99483e7
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/sparc/Makefile
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 1993,2001-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/nsswitch/dns/sparc/Makefile
+
+include ../Makefile.com
+
+LIBS = $(DYNLIB1)
+
+include ../../Makefile.targ
+
+install: all $(ROOTLIBS)
diff --git a/usr/src/lib/nsswitch/dns/sparcv9/Makefile b/usr/src/lib/nsswitch/dns/sparcv9/Makefile
new file mode 100644
index 0000000000..dbcedcf28e
--- /dev/null
+++ b/usr/src/lib/nsswitch/dns/sparcv9/Makefile
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1993,2001 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+# lib/nsswitch/dns/sparcv9/Makefile
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+LIBS = $(DYNLIB1)
+
+include ../../Makefile.targ
+
+install: all $(ROOT64DYNLIB)