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
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * 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  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
23ba2b2c94SVitaliy Gusev  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
246392794bSMichen Chang  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26*d81a47b3SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
276c740c0aSraf  */
286c740c0aSraf 
296c740c0aSraf /*
307c478bd9Sstevel@tonic-gate  * This is where we have chosen to combine every useful bit of code for
317c478bd9Sstevel@tonic-gate  * all the Solaris frontends to lookup hosts, services, and netdir information
327c478bd9Sstevel@tonic-gate  * for inet family (udp, tcp) transports. gethostbyYY(), getservbyYY(), and
337c478bd9Sstevel@tonic-gate  * netdir_getbyYY() are all implemented on top of this code. Similarly,
347c478bd9Sstevel@tonic-gate  * netdir_options, taddr2uaddr, and uaddr2taddr for inet transports also
357c478bd9Sstevel@tonic-gate  * find a home here.
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * If the netconfig structure supplied has NO nametoaddr libs (i.e. a "-"
387c478bd9Sstevel@tonic-gate  * in /etc/netconfig), this code calls the name service switch, and
397c478bd9Sstevel@tonic-gate  * therefore, /etc/nsswitch.conf is effectively the only place that
407c478bd9Sstevel@tonic-gate  * dictates hosts/serv lookup policy.
417c478bd9Sstevel@tonic-gate  * If an administrator chooses to bypass the name service switch by
427c478bd9Sstevel@tonic-gate  * specifying third party supplied nametoaddr libs in /etc/netconfig, this
437c478bd9Sstevel@tonic-gate  * implementation does NOT call the name service switch, it merely loops
447c478bd9Sstevel@tonic-gate  * through the nametoaddr libs. In this case, if this code was called
457c478bd9Sstevel@tonic-gate  * from gethost/servbyYY() we marshal the inet specific struct into
467c478bd9Sstevel@tonic-gate  * transport independent netbuf or hostserv, and unmarshal the resulting
477c478bd9Sstevel@tonic-gate  * nd_addrlist or hostservlist back into hostent and servent, as the case
487c478bd9Sstevel@tonic-gate  * may be.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * Goes without saying that most of the future bugs in gethost/servbyYY
517c478bd9Sstevel@tonic-gate  * and netdir_getbyYY are lurking somewhere here.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include "mt.h"
557c478bd9Sstevel@tonic-gate #include <ctype.h>
567c478bd9Sstevel@tonic-gate #include <stdio.h>
577c478bd9Sstevel@tonic-gate #include <stdlib.h>
587c478bd9Sstevel@tonic-gate #include <string.h>
597c478bd9Sstevel@tonic-gate #include <unistd.h>
607c478bd9Sstevel@tonic-gate #include <stropts.h>
617c478bd9Sstevel@tonic-gate #include <sys/types.h>
627c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
637c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
647c478bd9Sstevel@tonic-gate #include <sys/param.h>
657c478bd9Sstevel@tonic-gate #include <sys/time.h>
667c478bd9Sstevel@tonic-gate #include <errno.h>
677c478bd9Sstevel@tonic-gate #include <fcntl.h>
687c478bd9Sstevel@tonic-gate #include <thread.h>
697c478bd9Sstevel@tonic-gate #include <synch.h>
707c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
717c478bd9Sstevel@tonic-gate #include <netdb.h>
727c478bd9Sstevel@tonic-gate #include <netconfig.h>
737c478bd9Sstevel@tonic-gate #include <netdir.h>
747c478bd9Sstevel@tonic-gate #include <tiuser.h>
757c478bd9Sstevel@tonic-gate #include <sys/socket.h>
767c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
777c478bd9Sstevel@tonic-gate #include <netinet/in.h>
787c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
797c478bd9Sstevel@tonic-gate #include <net/if.h>
807c478bd9Sstevel@tonic-gate #include <inet/ip.h>
817c478bd9Sstevel@tonic-gate #include <inet/ip6_asp.h>
827c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
837c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
847c478bd9Sstevel@tonic-gate #include <nss_netdir.h>
857c478bd9Sstevel@tonic-gate #include <syslog.h>
867c478bd9Sstevel@tonic-gate #include <nsswitch.h>
877c478bd9Sstevel@tonic-gate #include "nss.h"
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #define	MAXIFS 32
907c478bd9Sstevel@tonic-gate #define	UDPDEV	"/dev/udp"
917c478bd9Sstevel@tonic-gate #define	UDP6DEV	"/dev/udp6"
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate #define	DOOR_GETHOSTBYNAME_R	_switch_gethostbyname_r
947c478bd9Sstevel@tonic-gate #define	DOOR_GETHOSTBYADDR_R	_switch_gethostbyaddr_r
957c478bd9Sstevel@tonic-gate #define	DOOR_GETIPNODEBYNAME_R	_switch_getipnodebyname_r
967c478bd9Sstevel@tonic-gate #define	DOOR_GETIPNODEBYADDR_R	_switch_getipnodebyaddr_r
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	DONT_SORT	"SORT_ADDRS=NO"
997c478bd9Sstevel@tonic-gate #define	DONT_SORT2	"SORT_ADDRS=FALSE"
1007c478bd9Sstevel@tonic-gate #define	LINESIZE	100
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * constant values of addresses for HOST_SELF_BIND, HOST_SELF_CONNECT
1047c478bd9Sstevel@tonic-gate  * and localhost.
1057c478bd9Sstevel@tonic-gate  *
1067c478bd9Sstevel@tonic-gate  * The following variables are static to the extent that they should
1077c478bd9Sstevel@tonic-gate  * not be visible outside of this file.
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate static char *localaddr[] = {"\000\000\000\000", NULL};
1107c478bd9Sstevel@tonic-gate static char *connectaddr[] = {"\177\000\000\001", NULL};
1117c478bd9Sstevel@tonic-gate static char *localaddr6[] =
1127c478bd9Sstevel@tonic-gate {"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", NULL};
1137c478bd9Sstevel@tonic-gate static char *connectaddr6[] =
1147c478bd9Sstevel@tonic-gate {"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", NULL};
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /* IPv4 nd_addrlist */
1177c478bd9Sstevel@tonic-gate static mutex_t	nd_addr_lock = DEFAULTMUTEX;
1187c478bd9Sstevel@tonic-gate static struct sockaddr_in sa_con;
1197c478bd9Sstevel@tonic-gate static struct netbuf nd_conbuf = {sizeof (sa_con),\
1207c478bd9Sstevel@tonic-gate     sizeof (sa_con), (char *)&sa_con};
1217c478bd9Sstevel@tonic-gate static struct nd_addrlist nd_conaddrlist = {1, &nd_conbuf};
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /* IPv6 nd_addrlist */
1247c478bd9Sstevel@tonic-gate static mutex_t	nd6_addr_lock = DEFAULTMUTEX;
1257c478bd9Sstevel@tonic-gate static struct sockaddr_in6 sa6_con;
1267c478bd9Sstevel@tonic-gate static struct netbuf nd6_conbuf = {sizeof (sa6_con),\
1277c478bd9Sstevel@tonic-gate 	sizeof (sa6_con), (char *)&sa6_con};
1287c478bd9Sstevel@tonic-gate static struct nd_addrlist nd6_conaddrlist = {1, &nd6_conbuf};
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate #define	LOCALHOST "localhost"
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate struct servent *_switch_getservbyname_r(const char *, const char *,
1337c478bd9Sstevel@tonic-gate     struct servent *, char *, int);
1347c478bd9Sstevel@tonic-gate struct servent *_switch_getservbyport_r(int, const char *, struct servent *,
1357c478bd9Sstevel@tonic-gate     char *, int);
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate static int __herrno2netdir(int h_errnop);
1387c478bd9Sstevel@tonic-gate static struct ifinfo *get_local_info(void);
1397c478bd9Sstevel@tonic-gate static int getbroadcastnets(struct netconfig *, struct in_addr **);
1407c478bd9Sstevel@tonic-gate static int hent2ndaddr(int, char **, int *, struct nd_addrlist **);
1417c478bd9Sstevel@tonic-gate static int ndaddr2hent(int, const char *, struct nd_addrlist *,
1427c478bd9Sstevel@tonic-gate     struct hostent *, char *, int);
1437c478bd9Sstevel@tonic-gate static int hsents2ndhostservs(struct hostent *, struct servent *, ushort_t,
1447c478bd9Sstevel@tonic-gate     struct nd_hostservlist **);
1457c478bd9Sstevel@tonic-gate static int ndaddr2srent(const char *, const char *, ushort_t, struct servent *,
1467c478bd9Sstevel@tonic-gate     char *, int);
1477c478bd9Sstevel@tonic-gate static int ndhostserv2hent(struct netbuf *, struct nd_hostservlist *,
1487c478bd9Sstevel@tonic-gate     struct hostent *, char *, int);
1497c478bd9Sstevel@tonic-gate static int ndhostserv2srent(int, const char *, struct nd_hostservlist *,
1507c478bd9Sstevel@tonic-gate     struct servent *, char *, int);
1517c478bd9Sstevel@tonic-gate static int nd2herrno(int nerr);
1527c478bd9Sstevel@tonic-gate static void order_haddrlist_inet(char **haddrlist, size_t addrcount);
1537c478bd9Sstevel@tonic-gate static void order_haddrlist_inet6(char **haddrlist, size_t addrcount);
1547c478bd9Sstevel@tonic-gate static int dstcmp(const void *, const void *);
1557c478bd9Sstevel@tonic-gate static int nss_strioctl(int af, int cmd, void *ptr, int ilen);
1567c478bd9Sstevel@tonic-gate static struct in_addr _inet_makeaddr(in_addr_t, in_addr_t);
1577c478bd9Sstevel@tonic-gate static boolean_t _read_nsw_file(void);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate  * Begin: PART I
1617c478bd9Sstevel@tonic-gate  * Top Level Interfaces that gethost/serv/netdir funnel through.
1627c478bd9Sstevel@tonic-gate  */
1637c478bd9Sstevel@tonic-gate 
164*d81a47b3SMilan Jurik static int
inetdir_free(int ret,struct in_addr * inaddrs,char ** baddrlist)165*d81a47b3SMilan Jurik inetdir_free(int ret, struct in_addr *inaddrs, char **baddrlist)
166*d81a47b3SMilan Jurik {
167*d81a47b3SMilan Jurik 	if (inaddrs)
168*d81a47b3SMilan Jurik 		free(inaddrs);
169*d81a47b3SMilan Jurik 	if (baddrlist)
170*d81a47b3SMilan Jurik 		free(baddrlist);
171*d81a47b3SMilan Jurik 	_nderror = ret;
172*d81a47b3SMilan Jurik 	return (ret);
173*d81a47b3SMilan Jurik }
174*d81a47b3SMilan Jurik 
1757c478bd9Sstevel@tonic-gate /*
1767c478bd9Sstevel@tonic-gate  * gethost/servbyname always call this function; if they call
1777c478bd9Sstevel@tonic-gate  * with nametoaddr libs in nconf, we call netdir_getbyname
1787c478bd9Sstevel@tonic-gate  * implementation: __classic_netdir_getbyname, otherwise nsswitch.
1797c478bd9Sstevel@tonic-gate  *
1807c478bd9Sstevel@tonic-gate  * netdir_getbyname calls this only if nametoaddr libs are NOT
1817c478bd9Sstevel@tonic-gate  * specified for inet transports; i.e. it's supposed to follow
1827c478bd9Sstevel@tonic-gate  * the name service switch.
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate int
_get_hostserv_inetnetdir_byname(struct netconfig * nconf,struct nss_netdirbyname_in * args,union nss_netdirbyname_out * res)1857c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byname(struct netconfig *nconf,
1867c478bd9Sstevel@tonic-gate     struct nss_netdirbyname_in *args, union nss_netdirbyname_out *res)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	int	server_port;
1897c478bd9Sstevel@tonic-gate 	int *servp = &server_port;
1907c478bd9Sstevel@tonic-gate 	char	**haddrlist;
1917c478bd9Sstevel@tonic-gate 	uint32_t dotnameaddr;
1927c478bd9Sstevel@tonic-gate 	char	*dotnamelist[2];
1937c478bd9Sstevel@tonic-gate 	struct in_addr	*inaddrs = NULL;
1947c478bd9Sstevel@tonic-gate 	struct in6_addr	v6nameaddr;
1957c478bd9Sstevel@tonic-gate 	char	**baddrlist = NULL;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (nconf == NULL) {
1987c478bd9Sstevel@tonic-gate 		_nderror = ND_BADARG;
1997c478bd9Sstevel@tonic-gate 		return (ND_BADARG);
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/*
2037c478bd9Sstevel@tonic-gate 	 * 1. gethostbyname()/netdir_getbyname() special cases:
2047c478bd9Sstevel@tonic-gate 	 */
2057c478bd9Sstevel@tonic-gate 	switch (args->op_t) {
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		case NSS_HOST:
2087c478bd9Sstevel@tonic-gate 		/*
2097c478bd9Sstevel@tonic-gate 		 * Worth the performance gain -- assuming a lot of inet apps
2107c478bd9Sstevel@tonic-gate 		 * actively use "localhost".
2117c478bd9Sstevel@tonic-gate 		 */
2127c478bd9Sstevel@tonic-gate 		if (strcmp(args->arg.nss.host.name, LOCALHOST) == 0) {
2137c478bd9Sstevel@tonic-gate 
21461961e0fSrobinson 			(void) mutex_lock(&nd_addr_lock);
2157c478bd9Sstevel@tonic-gate 			IN_SET_LOOPBACK_ADDR(&sa_con);
2167c478bd9Sstevel@tonic-gate 			_nderror = ndaddr2hent(AF_INET, args->arg.nss.host.name,
2177c478bd9Sstevel@tonic-gate 			    &nd_conaddrlist, res->nss.host.hent,
2187c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buf,
2197c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buflen);
22061961e0fSrobinson 			(void) mutex_unlock(&nd_addr_lock);
2217c478bd9Sstevel@tonic-gate 			if (_nderror != ND_OK)
2227c478bd9Sstevel@tonic-gate 				*(res->nss.host.herrno_p) =
2237c478bd9Sstevel@tonic-gate 				    nd2herrno(_nderror);
2247c478bd9Sstevel@tonic-gate 			return (_nderror);
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 		/*
2277c478bd9Sstevel@tonic-gate 		 * If the caller passed in a dot separated IP notation to
2287c478bd9Sstevel@tonic-gate 		 * gethostbyname, return that back as the address.
2297c478bd9Sstevel@tonic-gate 		 * The nd_addr_lock mutex was added to be truely re-entrant.
2307c478bd9Sstevel@tonic-gate 		 */
2316c740c0aSraf 		if (inet_aton(args->arg.nss.host.name,
2327c478bd9Sstevel@tonic-gate 		    (struct in_addr *)&dotnameaddr)) {
23361961e0fSrobinson 			(void) mutex_lock(&nd_addr_lock);
23461961e0fSrobinson 			(void) memset(&sa_con, 0, sizeof (sa_con));
2357c478bd9Sstevel@tonic-gate 			sa_con.sin_family = AF_INET;
2367c478bd9Sstevel@tonic-gate 			sa_con.sin_addr.s_addr = dotnameaddr;
2377c478bd9Sstevel@tonic-gate 			_nderror = ndaddr2hent(AF_INET, args->arg.nss.host.name,
2387c478bd9Sstevel@tonic-gate 			    &nd_conaddrlist, res->nss.host.hent,
2397c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buf,
2407c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buflen);
24161961e0fSrobinson 			(void) mutex_unlock(&nd_addr_lock);
2427c478bd9Sstevel@tonic-gate 			if (_nderror != ND_OK)
2437c478bd9Sstevel@tonic-gate 				*(res->nss.host.herrno_p) =
2447c478bd9Sstevel@tonic-gate 				    nd2herrno(_nderror);
2457c478bd9Sstevel@tonic-gate 			return (_nderror);
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 		break;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		case NSS_HOST6:
2507c478bd9Sstevel@tonic-gate 		/*
2517c478bd9Sstevel@tonic-gate 		 * Handle case of literal address string.
2527c478bd9Sstevel@tonic-gate 		 */
2537c478bd9Sstevel@tonic-gate 		if (strchr(args->arg.nss.host6.name, ':') != NULL &&
2547c478bd9Sstevel@tonic-gate 		    (inet_pton(AF_INET6, args->arg.nss.host6.name,
2557c478bd9Sstevel@tonic-gate 		    &v6nameaddr) != 0)) {
2567c478bd9Sstevel@tonic-gate 			int	ret;
2577c478bd9Sstevel@tonic-gate 
25861961e0fSrobinson 			(void) mutex_lock(&nd6_addr_lock);
25961961e0fSrobinson 			(void) memset(&sa6_con, 0, sizeof (sa6_con));
2607c478bd9Sstevel@tonic-gate 			sa6_con.sin6_family = AF_INET6;
26161961e0fSrobinson 			(void) memcpy(&(sa6_con.sin6_addr.s6_addr),
2627c478bd9Sstevel@tonic-gate 			    &v6nameaddr, sizeof (struct in6_addr));
2637c478bd9Sstevel@tonic-gate 			ret = ndaddr2hent(AF_INET6,
2647c478bd9Sstevel@tonic-gate 			    args->arg.nss.host6.name,
2657c478bd9Sstevel@tonic-gate 			    &nd6_conaddrlist, res->nss.host.hent,
2667c478bd9Sstevel@tonic-gate 			    args->arg.nss.host6.buf,
2677c478bd9Sstevel@tonic-gate 			    args->arg.nss.host6.buflen);
26861961e0fSrobinson 			(void) mutex_unlock(&nd6_addr_lock);
2697c478bd9Sstevel@tonic-gate 			if (ret != ND_OK)
2707c478bd9Sstevel@tonic-gate 				*(res->nss.host.herrno_p) = nd2herrno(ret);
2717c478bd9Sstevel@tonic-gate 			else
2727c478bd9Sstevel@tonic-gate 				res->nss.host.hent->h_aliases = NULL;
2737c478bd9Sstevel@tonic-gate 			return (ret);
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 		break;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 		case NETDIR_BY:
2787c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs == 0) {
2797c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
2807c478bd9Sstevel@tonic-gate 				return (ND_BADARG);
2817c478bd9Sstevel@tonic-gate 			}
2827c478bd9Sstevel@tonic-gate 			/*
2837c478bd9Sstevel@tonic-gate 			 * If servname is NULL, return 0 as the port number
2847c478bd9Sstevel@tonic-gate 			 * If servname is rpcbind, return 111 as the port number
2857c478bd9Sstevel@tonic-gate 			 * If servname is a number, return it back as the port
2867c478bd9Sstevel@tonic-gate 			 * number.
2877c478bd9Sstevel@tonic-gate 			 */
2887c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs->h_serv == 0) {
2897c478bd9Sstevel@tonic-gate 				*servp = htons(0);
2906392794bSMichen Chang 			} else if (strcmp(args->arg.nd_hs->h_serv,
2916392794bSMichen Chang 			    "rpcbind") == 0) {
2927c478bd9Sstevel@tonic-gate 				*servp = htons(111);
2936392794bSMichen Chang 			} else if (strspn(args->arg.nd_hs->h_serv,
2946392794bSMichen Chang 			    "0123456789") ==
2956392794bSMichen Chang 			    strlen(args->arg.nd_hs->h_serv)) {
2967c478bd9Sstevel@tonic-gate 				*servp = htons(atoi(args->arg.nd_hs->h_serv));
2977c478bd9Sstevel@tonic-gate 			} else {
2987c478bd9Sstevel@tonic-gate 				/* i.e. need to call a name service on this */
2997c478bd9Sstevel@tonic-gate 				servp = NULL;
3007c478bd9Sstevel@tonic-gate 			}
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 			/*
3037c478bd9Sstevel@tonic-gate 			 * If the hostname is HOST_SELF_BIND, we return 0.0.0.0
3047c478bd9Sstevel@tonic-gate 			 * so the  binding can be contacted through all
3057c478bd9Sstevel@tonic-gate 			 * interfaces. If the hostname is HOST_SELF_CONNECT,
3067c478bd9Sstevel@tonic-gate 			 * we return 127.0.0.1 so the address can be connected
3077c478bd9Sstevel@tonic-gate 			 * to locally. If the hostname is HOST_ANY, we return
3087c478bd9Sstevel@tonic-gate 			 * no addresses because IP doesn't know how to specify
3097c478bd9Sstevel@tonic-gate 			 * a service without a host. And finally if we specify
3107c478bd9Sstevel@tonic-gate 			 * HOST_BROADCAST then we ask a tli fd to tell us what
3117c478bd9Sstevel@tonic-gate 			 * the broadcast addresses are for any udp
3127c478bd9Sstevel@tonic-gate 			 * interfaces on this machine.
3137c478bd9Sstevel@tonic-gate 			 */
3147c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs->h_host == 0) {
3157c478bd9Sstevel@tonic-gate 				_nderror = ND_NOHOST;
3167c478bd9Sstevel@tonic-gate 				return (ND_NOHOST);
3177c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
3187c478bd9Sstevel@tonic-gate 			    HOST_SELF_BIND) == 0)) {
3197c478bd9Sstevel@tonic-gate 				haddrlist = localaddr;
3207c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
3216392794bSMichen Chang 			    HOST_SELF_CONNECT) == 0)) {
3227c478bd9Sstevel@tonic-gate 				haddrlist = connectaddr;
3237c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
3246392794bSMichen Chang 			    LOCALHOST) == 0)) {
3257c478bd9Sstevel@tonic-gate 				haddrlist = connectaddr;
3267c478bd9Sstevel@tonic-gate 			} else if ((int)(dotnameaddr =
3276392794bSMichen Chang 			    inet_addr(args->arg.nd_hs->h_host)) != -1) {
3287c478bd9Sstevel@tonic-gate 				/*
3297c478bd9Sstevel@tonic-gate 				 * If the caller passed in a dot separated IP
3307c478bd9Sstevel@tonic-gate 				 * notation to netdir_getbyname, convert that
3317c478bd9Sstevel@tonic-gate 				 * back into address.
3327c478bd9Sstevel@tonic-gate 				 */
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 				dotnamelist[0] = (char *)&dotnameaddr;
3357c478bd9Sstevel@tonic-gate 				dotnamelist[1] = NULL;
3367c478bd9Sstevel@tonic-gate 				haddrlist = dotnamelist;
3377c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
3386392794bSMichen Chang 			    HOST_BROADCAST) == 0)) {
3397c478bd9Sstevel@tonic-gate 				/*
3407c478bd9Sstevel@tonic-gate 				 * Now that inaddrs and baddrlist are
3417c478bd9Sstevel@tonic-gate 				 * dynamically allocated, care must be
3427c478bd9Sstevel@tonic-gate 				 * taken in freeing up the
3437c478bd9Sstevel@tonic-gate 				 * memory at each 'return()' point.
3447c478bd9Sstevel@tonic-gate 				 *
3457c478bd9Sstevel@tonic-gate 				 * Early return protection (using
346*d81a47b3SMilan Jurik 				 * inetdir_free()) is needed only in NETDIR_BY
3477c478bd9Sstevel@tonic-gate 				 * cases because dynamic allocation is used
3487c478bd9Sstevel@tonic-gate 				 * when args->op_t == NETDIR_BY.
3497c478bd9Sstevel@tonic-gate 				 *
3507c478bd9Sstevel@tonic-gate 				 * Early return protection is not needed in
3517c478bd9Sstevel@tonic-gate 				 * haddrlist==0 conditionals because dynamic
3527c478bd9Sstevel@tonic-gate 				 * allocation guarantees haddrlist!=0.
3537c478bd9Sstevel@tonic-gate 				 *
3547c478bd9Sstevel@tonic-gate 				 * Early return protection is not needed in most
3557c478bd9Sstevel@tonic-gate 				 * servp!=0 conditionals because this is handled
3567c478bd9Sstevel@tonic-gate 				 * (and returned) first.
3577c478bd9Sstevel@tonic-gate 				 */
3587c478bd9Sstevel@tonic-gate 				int i, bnets;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 				bnets = getbroadcastnets(nconf, &inaddrs);
3617c478bd9Sstevel@tonic-gate 				if (bnets == 0) {
3627c478bd9Sstevel@tonic-gate 					_nderror = ND_NOHOST;
3637c478bd9Sstevel@tonic-gate 					return (ND_NOHOST);
3647c478bd9Sstevel@tonic-gate 				}
36561961e0fSrobinson 				baddrlist = malloc((bnets+1)*sizeof (char *));
3667c478bd9Sstevel@tonic-gate 				if (baddrlist == NULL)
367*d81a47b3SMilan Jurik 					return (inetdir_free(ND_NOMEM, inaddrs,
368*d81a47b3SMilan Jurik 					    baddrlist));
3697c478bd9Sstevel@tonic-gate 				for (i = 0; i < bnets; i++)
3707c478bd9Sstevel@tonic-gate 					baddrlist[i] = (char *)&inaddrs[i];
3717c478bd9Sstevel@tonic-gate 				baddrlist[i] = NULL;
3727c478bd9Sstevel@tonic-gate 				haddrlist = baddrlist;
3737c478bd9Sstevel@tonic-gate 			} else {
3747c478bd9Sstevel@tonic-gate 				/* i.e. need to call a name service on this */
3757c478bd9Sstevel@tonic-gate 				haddrlist = 0;
3767c478bd9Sstevel@tonic-gate 			}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 			if (haddrlist && servp) {
3797c478bd9Sstevel@tonic-gate 				int ret;
3807c478bd9Sstevel@tonic-gate 				/*
3817c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
3827c478bd9Sstevel@tonic-gate 				 * malloc's will be done, freed using
3837c478bd9Sstevel@tonic-gate 				 * netdir_free.
3847c478bd9Sstevel@tonic-gate 				 */
3857c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET, haddrlist, servp,
3866392794bSMichen Chang 				    res->nd_alist);
387*d81a47b3SMilan Jurik 				return (inetdir_free(ret, inaddrs, baddrlist));
3886392794bSMichen Chang 			}
3897c478bd9Sstevel@tonic-gate 			break;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 		case NETDIR_BY6:
3937c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs == 0) {
3947c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
3957c478bd9Sstevel@tonic-gate 				return (ND_BADARG);
3967c478bd9Sstevel@tonic-gate 			}
3977c478bd9Sstevel@tonic-gate 			/*
3987c478bd9Sstevel@tonic-gate 			 * If servname is NULL, return 0 as the port number.
3997c478bd9Sstevel@tonic-gate 			 * If servname is rpcbind, return 111 as the port number
4007c478bd9Sstevel@tonic-gate 			 * If servname is a number, return it back as the port
4017c478bd9Sstevel@tonic-gate 			 * number.
4027c478bd9Sstevel@tonic-gate 			 */
4037c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs->h_serv == 0) {
4047c478bd9Sstevel@tonic-gate 				*servp = htons(0);
4057c478bd9Sstevel@tonic-gate 			} else if (strcmp(args->arg.nd_hs->h_serv,
4066392794bSMichen Chang 			    "rpcbind") == 0) {
4077c478bd9Sstevel@tonic-gate 				*servp = htons(111);
4087c478bd9Sstevel@tonic-gate 			} else if (strspn(args->arg.nd_hs->h_serv, "0123456789")
4096392794bSMichen Chang 			    == strlen(args->arg.nd_hs->h_serv)) {
4107c478bd9Sstevel@tonic-gate 				*servp = htons(atoi(args->arg.nd_hs->h_serv));
4117c478bd9Sstevel@tonic-gate 			} else {
4127c478bd9Sstevel@tonic-gate 				/* i.e. need to call a name service on this */
4137c478bd9Sstevel@tonic-gate 				servp = NULL;
4147c478bd9Sstevel@tonic-gate 			}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 			/*
4177c478bd9Sstevel@tonic-gate 			 * If the hostname is HOST_SELF_BIND, we return ipv6
4187c478bd9Sstevel@tonic-gate 			 * localaddress so the binding can be contacted through
4197c478bd9Sstevel@tonic-gate 			 * all interfaces.
4207c478bd9Sstevel@tonic-gate 			 * If the hostname is HOST_SELF_CONNECT, we return
4217c478bd9Sstevel@tonic-gate 			 * ipv6 loopback address so the address can be connected
4227c478bd9Sstevel@tonic-gate 			 * to locally.
4237c478bd9Sstevel@tonic-gate 			 * If the hostname is HOST_ANY, we return no addresses
4247c478bd9Sstevel@tonic-gate 			 * because IP doesn't know how to specify a service
4257c478bd9Sstevel@tonic-gate 			 * without a host.
4267c478bd9Sstevel@tonic-gate 			 * And finally if we specify HOST_BROADCAST then we
4277c478bd9Sstevel@tonic-gate 			 * disallow since IPV6 does not have any
4287c478bd9Sstevel@tonic-gate 			 * broadcast concept.
4297c478bd9Sstevel@tonic-gate 			 */
4307c478bd9Sstevel@tonic-gate 			if (args->arg.nd_hs->h_host == 0) {
4317c478bd9Sstevel@tonic-gate 				return (ND_NOHOST);
4327c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
4336392794bSMichen Chang 			    HOST_SELF_BIND) == 0)) {
4347c478bd9Sstevel@tonic-gate 				haddrlist = localaddr6;
4357c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
4366392794bSMichen Chang 			    HOST_SELF_CONNECT) == 0)) {
4377c478bd9Sstevel@tonic-gate 				haddrlist = connectaddr6;
4387c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
4396392794bSMichen Chang 			    LOCALHOST) == 0)) {
4407c478bd9Sstevel@tonic-gate 				haddrlist = connectaddr6;
4417c478bd9Sstevel@tonic-gate 			} else if (strchr(args->arg.nd_hs->h_host, ':')
4426392794bSMichen Chang 			    != NULL) {
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 			/*
4457c478bd9Sstevel@tonic-gate 			 * If the caller passed in a dot separated IP notation
4467c478bd9Sstevel@tonic-gate 			 * to netdir_getbyname, convert that back into address.
4477c478bd9Sstevel@tonic-gate 			 */
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				if ((inet_pton(AF_INET6,
4506392794bSMichen Chang 				    args->arg.nd_hs->h_host,
4516392794bSMichen Chang 				    &v6nameaddr)) != 0) {
4527c478bd9Sstevel@tonic-gate 					dotnamelist[0] = (char *)&v6nameaddr;
4537c478bd9Sstevel@tonic-gate 					dotnamelist[1] = NULL;
4547c478bd9Sstevel@tonic-gate 					haddrlist = dotnamelist;
4557c478bd9Sstevel@tonic-gate 				}
4567c478bd9Sstevel@tonic-gate 				else
4577c478bd9Sstevel@tonic-gate 					/* not sure what to return */
4587c478bd9Sstevel@tonic-gate 					return (ND_NOHOST);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 			} else if ((strcmp(args->arg.nd_hs->h_host,
4616392794bSMichen Chang 			    HOST_BROADCAST) == 0)) {
4627c478bd9Sstevel@tonic-gate 				/*
4637c478bd9Sstevel@tonic-gate 				 * Don't support broadcast in
4647c478bd9Sstevel@tonic-gate 				 * IPV6
4657c478bd9Sstevel@tonic-gate 				 */
4667c478bd9Sstevel@tonic-gate 				return (ND_NOHOST);
4677c478bd9Sstevel@tonic-gate 			} else {
4687c478bd9Sstevel@tonic-gate 				/* i.e. need to call a name service on this */
4697c478bd9Sstevel@tonic-gate 				haddrlist = 0;
4707c478bd9Sstevel@tonic-gate 			}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 			if (haddrlist && servp) {
4737c478bd9Sstevel@tonic-gate 				int ret;
4747c478bd9Sstevel@tonic-gate 				/*
4757c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
4767c478bd9Sstevel@tonic-gate 				 * malloc's will be done, freed
4777c478bd9Sstevel@tonic-gate 				 * using netdir_free.
4787c478bd9Sstevel@tonic-gate 				 */
4797c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET6, haddrlist,
4807c478bd9Sstevel@tonic-gate 				    servp, res->nd_alist);
481*d81a47b3SMilan Jurik 				return (inetdir_free(ret, inaddrs, baddrlist));
4826392794bSMichen Chang 			}
4837c478bd9Sstevel@tonic-gate 			break;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/*
4897c478bd9Sstevel@tonic-gate 	 * 2. Most common scenario. This is the way we ship /etc/netconfig.
4907c478bd9Sstevel@tonic-gate 	 *    Emphasis on improving performance in the "if" part.
4917c478bd9Sstevel@tonic-gate 	 */
4927c478bd9Sstevel@tonic-gate 	if (nconf->nc_nlookups == 0) {
4937c478bd9Sstevel@tonic-gate 		struct hostent	*he = NULL, *tmphe;
4947c478bd9Sstevel@tonic-gate 		struct servent	*se;
4957c478bd9Sstevel@tonic-gate 		int	ret;
4967c478bd9Sstevel@tonic-gate 		nss_XbyY_buf_t	*ndbuf4switch = 0;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	switch (args->op_t) {
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		case NSS_HOST:
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 		he = DOOR_GETHOSTBYNAME_R(args->arg.nss.host.name,
5037c478bd9Sstevel@tonic-gate 		    res->nss.host.hent, args->arg.nss.host.buf,
5047c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.buflen,
5057c478bd9Sstevel@tonic-gate 		    res->nss.host.herrno_p);
5067c478bd9Sstevel@tonic-gate 		if (he == NULL)
5077c478bd9Sstevel@tonic-gate 			return (_nderror = ND_NOHOST);
5087c478bd9Sstevel@tonic-gate 		return (_nderror = ND_OK);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		case NSS_HOST6:
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		he = DOOR_GETIPNODEBYNAME_R(args->arg.nss.host6.name,
5137c478bd9Sstevel@tonic-gate 		    res->nss.host.hent, args->arg.nss.host.buf,
5147c478bd9Sstevel@tonic-gate 		    args->arg.nss.host6.buflen,
5157c478bd9Sstevel@tonic-gate 		    args->arg.nss.host6.af_family,
5167c478bd9Sstevel@tonic-gate 		    args->arg.nss.host6.flags,
5177c478bd9Sstevel@tonic-gate 		    res->nss.host.herrno_p);
5187c478bd9Sstevel@tonic-gate 
51961961e0fSrobinson 		if (he == NULL)
5207c478bd9Sstevel@tonic-gate 			return (_nderror = ND_NOHOST);
5217c478bd9Sstevel@tonic-gate 		return (_nderror = ND_OK);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 		case NSS_SERV:
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		se = _switch_getservbyname_r(args->arg.nss.serv.name,
5267c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.proto,
5277c478bd9Sstevel@tonic-gate 		    res->nss.serv, args->arg.nss.serv.buf,
5287c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.buflen);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		_nderror = ND_OK;
5317c478bd9Sstevel@tonic-gate 		if (se == 0)
5327c478bd9Sstevel@tonic-gate 			_nderror = ND_NOSERV;
5337c478bd9Sstevel@tonic-gate 		return (_nderror);
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 		case NETDIR_BY:
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		if (servp == 0) {
5386392794bSMichen Chang 			char	*proto = (strcmp(nconf->nc_proto,
5396392794bSMichen Chang 			    NC_TCP) == 0) ? NC_TCP : NC_UDP;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 			/*
5427c478bd9Sstevel@tonic-gate 			 * We go through all this for just one port number,
5437c478bd9Sstevel@tonic-gate 			 * which is most often constant. How about linking in
5447c478bd9Sstevel@tonic-gate 			 * an indexed database of well-known ports in the name
5457c478bd9Sstevel@tonic-gate 			 * of performance ?
5467c478bd9Sstevel@tonic-gate 			 */
54761961e0fSrobinson 			ndbuf4switch = _nss_XbyY_buf_alloc(
5486392794bSMichen Chang 			    sizeof (struct servent), NSS_BUFLEN_SERVICES);
5497c478bd9Sstevel@tonic-gate 			if (ndbuf4switch == 0)
550*d81a47b3SMilan Jurik 				return (inetdir_free(ND_NOMEM, inaddrs,
551*d81a47b3SMilan Jurik 				    baddrlist));
5527c478bd9Sstevel@tonic-gate 			se = _switch_getservbyname_r(args->arg.nd_hs->h_serv,
5536392794bSMichen Chang 			    proto, ndbuf4switch->result,
5546392794bSMichen Chang 			    ndbuf4switch->buffer, ndbuf4switch->buflen);
5557c478bd9Sstevel@tonic-gate 			if (!se) {
5567c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4switch);
557*d81a47b3SMilan Jurik 				return (inetdir_free(ND_NOSERV, inaddrs,
558*d81a47b3SMilan Jurik 				    baddrlist));
5597c478bd9Sstevel@tonic-gate 			}
5607c478bd9Sstevel@tonic-gate 			server_port = se->s_port;
5617c478bd9Sstevel@tonic-gate 			NSS_XbyY_FREE(&ndbuf4switch);
5627c478bd9Sstevel@tonic-gate 		}
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		if (haddrlist == 0) {
5657c478bd9Sstevel@tonic-gate 			int	h_errnop = 0;
5667c478bd9Sstevel@tonic-gate 
56761961e0fSrobinson 			ndbuf4switch = _nss_XbyY_buf_alloc(
5686392794bSMichen Chang 			    sizeof (struct hostent),
5696392794bSMichen Chang 			    NSS_BUFLEN_HOSTS);
5707c478bd9Sstevel@tonic-gate 			if (ndbuf4switch == 0) {
5717c478bd9Sstevel@tonic-gate 				_nderror = ND_NOMEM;
5727c478bd9Sstevel@tonic-gate 				return (ND_NOMEM);
5737c478bd9Sstevel@tonic-gate 			}
5747c478bd9Sstevel@tonic-gate 			/*
5757c478bd9Sstevel@tonic-gate 			 * Search the ipnodes (v6) path first,
5767c478bd9Sstevel@tonic-gate 			 * search will return the v4 addresses
5777c478bd9Sstevel@tonic-gate 			 * as v4mapped addresses.
5787c478bd9Sstevel@tonic-gate 			 */
5797c478bd9Sstevel@tonic-gate 			if ((tmphe = DOOR_GETIPNODEBYNAME_R(
5807c478bd9Sstevel@tonic-gate 			    args->arg.nd_hs->h_host,
5817c478bd9Sstevel@tonic-gate 			    ndbuf4switch->result, ndbuf4switch->buffer,
5827c478bd9Sstevel@tonic-gate 			    ndbuf4switch->buflen, args->arg.nss.host6.af_family,
5837c478bd9Sstevel@tonic-gate 			    args->arg.nss.host6.flags, &h_errnop)) != NULL)
5847c478bd9Sstevel@tonic-gate 				he = __mappedtov4(tmphe, &h_errnop);
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 			if (he == NULL) {
5877c478bd9Sstevel@tonic-gate 				/* Failover case, try hosts db for v4 address */
5887c478bd9Sstevel@tonic-gate 				he = DOOR_GETHOSTBYNAME_R(
5896392794bSMichen Chang 				    args->arg.nd_hs->h_host,
5906392794bSMichen Chang 				    ndbuf4switch->result, ndbuf4switch->buffer,
5916392794bSMichen Chang 				    ndbuf4switch->buflen, &h_errnop);
5927c478bd9Sstevel@tonic-gate 				if (he == NULL) {
5937c478bd9Sstevel@tonic-gate 					NSS_XbyY_FREE(&ndbuf4switch);
594ba2b2c94SVitaliy Gusev 					_nderror = __herrno2netdir(h_errnop);
5957c478bd9Sstevel@tonic-gate 					return (_nderror);
5967c478bd9Sstevel@tonic-gate 				}
5977c478bd9Sstevel@tonic-gate 				/*
5987c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
5997c478bd9Sstevel@tonic-gate 				 * malloc's will be done, freed using
6007c478bd9Sstevel@tonic-gate 				 * netdir_free.
6017c478bd9Sstevel@tonic-gate 				 */
6027c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET, he->h_addr_list,
6036392794bSMichen Chang 				    &server_port, res->nd_alist);
6047c478bd9Sstevel@tonic-gate 			} else {
6057c478bd9Sstevel@tonic-gate 				/*
6067c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
6077c478bd9Sstevel@tonic-gate 				 * malloc's will be done, freed using
6087c478bd9Sstevel@tonic-gate 				 * netdir_free.
6097c478bd9Sstevel@tonic-gate 				 */
6107c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET, he->h_addr_list,
6116392794bSMichen Chang 				    &server_port, res->nd_alist);
6127c478bd9Sstevel@tonic-gate 				freehostent(he);
6137c478bd9Sstevel@tonic-gate 			}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 			_nderror = ret;
6167c478bd9Sstevel@tonic-gate 			NSS_XbyY_FREE(&ndbuf4switch);
6177c478bd9Sstevel@tonic-gate 			return (ret);
6187c478bd9Sstevel@tonic-gate 		} else {
6197c478bd9Sstevel@tonic-gate 			int ret;
6207c478bd9Sstevel@tonic-gate 			/*
6217c478bd9Sstevel@tonic-gate 			 * Convert h_addr_list into nd_addrlist.
6227c478bd9Sstevel@tonic-gate 			 * malloc's will be done, freed using netdir_free.
6237c478bd9Sstevel@tonic-gate 			 */
6247c478bd9Sstevel@tonic-gate 			ret = hent2ndaddr(AF_INET, haddrlist,
6256392794bSMichen Chang 			    &server_port, res->nd_alist);
626*d81a47b3SMilan Jurik 			return (inetdir_free(ret, inaddrs, baddrlist));
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 		case NETDIR_BY6:
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 			if (servp == 0) {
6336392794bSMichen Chang 				char	*proto = (strcmp(nconf->nc_proto,
6346392794bSMichen Chang 				    NC_TCP) == 0) ? NC_TCP : NC_UDP;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 				/*
6377c478bd9Sstevel@tonic-gate 				 * We go through all this for just
6387c478bd9Sstevel@tonic-gate 				 * one port number,
6397c478bd9Sstevel@tonic-gate 				 * which is most often constant.
6407c478bd9Sstevel@tonic-gate 				 * How about linking in
6417c478bd9Sstevel@tonic-gate 				 * an indexed database of well-known
6427c478bd9Sstevel@tonic-gate 				 * ports in the name
6437c478bd9Sstevel@tonic-gate 				 * of performance ?
6447c478bd9Sstevel@tonic-gate 				 */
64561961e0fSrobinson 				ndbuf4switch = _nss_XbyY_buf_alloc(
6466392794bSMichen Chang 				    sizeof (struct servent),
6476392794bSMichen Chang 				    NSS_BUFLEN_SERVICES);
6487c478bd9Sstevel@tonic-gate 				if (ndbuf4switch == 0)
649*d81a47b3SMilan Jurik 					return (inetdir_free(ND_NOMEM, inaddrs,
650*d81a47b3SMilan Jurik 					    baddrlist));
6517c478bd9Sstevel@tonic-gate 				se = _switch_getservbyname_r(
6526392794bSMichen Chang 				    args->arg.nd_hs->h_serv,
6537c478bd9Sstevel@tonic-gate 				    proto, ndbuf4switch->result,
6547c478bd9Sstevel@tonic-gate 				    ndbuf4switch->buffer, ndbuf4switch->buflen);
6557c478bd9Sstevel@tonic-gate 				if (!se) {
6567c478bd9Sstevel@tonic-gate 					NSS_XbyY_FREE(&ndbuf4switch);
657*d81a47b3SMilan Jurik 					return (inetdir_free(ND_NOSERV, inaddrs,
658*d81a47b3SMilan Jurik 					    baddrlist));
6597c478bd9Sstevel@tonic-gate 				}
6607c478bd9Sstevel@tonic-gate 				server_port = se->s_port;
6617c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4switch);
6627c478bd9Sstevel@tonic-gate 			}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 			if (haddrlist == 0) {
6657c478bd9Sstevel@tonic-gate 				int	h_errnop = 0;
6667c478bd9Sstevel@tonic-gate 
66761961e0fSrobinson 				ndbuf4switch = _nss_XbyY_buf_alloc(
6686392794bSMichen Chang 				    sizeof (struct hostent),
6696392794bSMichen Chang 				    NSS_BUFLEN_HOSTS);
6707c478bd9Sstevel@tonic-gate 				if (ndbuf4switch == 0) {
6717c478bd9Sstevel@tonic-gate 					_nderror = ND_NOMEM;
6727c478bd9Sstevel@tonic-gate 					return (ND_NOMEM);
6737c478bd9Sstevel@tonic-gate 				}
6747c478bd9Sstevel@tonic-gate 				he = DOOR_GETIPNODEBYNAME_R(
6757c478bd9Sstevel@tonic-gate 				    args->arg.nd_hs->h_host,
6767c478bd9Sstevel@tonic-gate 				    ndbuf4switch->result, ndbuf4switch->buffer,
6777c478bd9Sstevel@tonic-gate 				    ndbuf4switch->buflen,
6787c478bd9Sstevel@tonic-gate 				    args->arg.nss.host6.af_family,
6797c478bd9Sstevel@tonic-gate 				    args->arg.nss.host6.flags, &h_errnop);
6807c478bd9Sstevel@tonic-gate 				if (he == NULL) {
6817c478bd9Sstevel@tonic-gate 					NSS_XbyY_FREE(&ndbuf4switch);
682ba2b2c94SVitaliy Gusev 					_nderror = __herrno2netdir(h_errnop);
6837c478bd9Sstevel@tonic-gate 					return (_nderror);
6847c478bd9Sstevel@tonic-gate 				}
6857c478bd9Sstevel@tonic-gate 				/*
6867c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
6877c478bd9Sstevel@tonic-gate 				 * malloc's will be done,
6887c478bd9Sstevel@tonic-gate 				 * freed using netdir_free.
6897c478bd9Sstevel@tonic-gate 				 */
6907c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET6,
6916392794bSMichen Chang 				    ((struct hostent *)
6926392794bSMichen Chang 				    (ndbuf4switch->result))->h_addr_list,
6937c478bd9Sstevel@tonic-gate 				    &server_port, res->nd_alist);
6947c478bd9Sstevel@tonic-gate 				_nderror = ret;
6957c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4switch);
6967c478bd9Sstevel@tonic-gate 				return (ret);
6977c478bd9Sstevel@tonic-gate 			} else {
6987c478bd9Sstevel@tonic-gate 				int ret;
6997c478bd9Sstevel@tonic-gate 				/*
7007c478bd9Sstevel@tonic-gate 				 * Convert h_addr_list into nd_addrlist.
7017c478bd9Sstevel@tonic-gate 				 * malloc's will be done,
7027c478bd9Sstevel@tonic-gate 				 * freed using netdir_free.
7037c478bd9Sstevel@tonic-gate 				 */
7047c478bd9Sstevel@tonic-gate 				ret = hent2ndaddr(AF_INET6, haddrlist,
7056392794bSMichen Chang 				    &server_port, res->nd_alist);
706*d81a47b3SMilan Jurik 				return (inetdir_free(ret, inaddrs, baddrlist));
7077c478bd9Sstevel@tonic-gate 			}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 		default:
7106392794bSMichen Chang 			_nderror = ND_BADARG;
7116392794bSMichen Chang 			return (ND_BADARG); /* should never happen */
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	} else {
7157c478bd9Sstevel@tonic-gate 		/* haddrlist is no longer used, so clean up */
7167c478bd9Sstevel@tonic-gate 		if (inaddrs)
7177c478bd9Sstevel@tonic-gate 			free(inaddrs);
7187c478bd9Sstevel@tonic-gate 		if (baddrlist)
7197c478bd9Sstevel@tonic-gate 			free(baddrlist);
7207c478bd9Sstevel@tonic-gate 	}
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	/*
7237c478bd9Sstevel@tonic-gate 	 * 3. We come this far only if nametoaddr libs are specified for
7247c478bd9Sstevel@tonic-gate 	 *    inet transports and we are called by gethost/servbyname only.
7257c478bd9Sstevel@tonic-gate 	 */
7267c478bd9Sstevel@tonic-gate 	switch (args->op_t) {
7277c478bd9Sstevel@tonic-gate 		struct	nd_hostserv service;
7287c478bd9Sstevel@tonic-gate 		struct	nd_addrlist *addrs;
7297c478bd9Sstevel@tonic-gate 		int ret;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		case NSS_HOST:
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 		service.h_host = (char *)args->arg.nss.host.name;
7347c478bd9Sstevel@tonic-gate 		service.h_serv = NULL;
7357c478bd9Sstevel@tonic-gate 		if ((_nderror = __classic_netdir_getbyname(nconf,
7366392794bSMichen Chang 		    &service, &addrs)) != ND_OK) {
7377c478bd9Sstevel@tonic-gate 			*(res->nss.host.herrno_p) = nd2herrno(_nderror);
7387c478bd9Sstevel@tonic-gate 			return (_nderror);
7397c478bd9Sstevel@tonic-gate 		}
7407c478bd9Sstevel@tonic-gate 		/*
7417c478bd9Sstevel@tonic-gate 		 * convert addresses back into sockaddr for gethostbyname.
7427c478bd9Sstevel@tonic-gate 		 */
7437c478bd9Sstevel@tonic-gate 		ret = ndaddr2hent(AF_INET, service.h_host, addrs,
7447c478bd9Sstevel@tonic-gate 		    res->nss.host.hent, args->arg.nss.host.buf,
7457c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.buflen);
7467c478bd9Sstevel@tonic-gate 		if (ret != ND_OK)
7477c478bd9Sstevel@tonic-gate 			*(res->nss.host.herrno_p) = nd2herrno(ret);
7487c478bd9Sstevel@tonic-gate 		netdir_free((char *)addrs, ND_ADDRLIST);
7497c478bd9Sstevel@tonic-gate 		_nderror = ret;
7507c478bd9Sstevel@tonic-gate 		return (ret);
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 		case NSS_SERV:
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 		if (args->arg.nss.serv.proto == NULL) {
7557c478bd9Sstevel@tonic-gate 			/*
7567c478bd9Sstevel@tonic-gate 			 * A similar HACK showed up in Solaris 2.3.
7577c478bd9Sstevel@tonic-gate 			 * The caller wild-carded proto -- i.e. will
7587c478bd9Sstevel@tonic-gate 			 * accept a match using tcp or udp for the port
7597c478bd9Sstevel@tonic-gate 			 * number. Since we have no hope of getting
7607c478bd9Sstevel@tonic-gate 			 * directly to a name service switch backend
7617c478bd9Sstevel@tonic-gate 			 * from here that understands this semantics,
7627c478bd9Sstevel@tonic-gate 			 * we try calling the netdir interfaces first
7637c478bd9Sstevel@tonic-gate 			 * with "tcp" and then "udp".
7647c478bd9Sstevel@tonic-gate 			 */
7657c478bd9Sstevel@tonic-gate 			args->arg.nss.serv.proto = "tcp";
7667c478bd9Sstevel@tonic-gate 			_nderror = _get_hostserv_inetnetdir_byname(nconf, args,
7677c478bd9Sstevel@tonic-gate 			    res);
7687c478bd9Sstevel@tonic-gate 			if (_nderror != ND_OK) {
7697c478bd9Sstevel@tonic-gate 				args->arg.nss.serv.proto = "udp";
7707c478bd9Sstevel@tonic-gate 				_nderror =
7717c478bd9Sstevel@tonic-gate 				    _get_hostserv_inetnetdir_byname(nconf,
7727c478bd9Sstevel@tonic-gate 				    args, res);
7737c478bd9Sstevel@tonic-gate 			}
7747c478bd9Sstevel@tonic-gate 			return (_nderror);
7757c478bd9Sstevel@tonic-gate 		}
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 		/*
7787c478bd9Sstevel@tonic-gate 		 * Third-parties should optimize their nametoaddr
7797c478bd9Sstevel@tonic-gate 		 * libraries for the HOST_SELF case.
7807c478bd9Sstevel@tonic-gate 		 */
7817c478bd9Sstevel@tonic-gate 		service.h_host = HOST_SELF;
7827c478bd9Sstevel@tonic-gate 		service.h_serv = (char *)args->arg.nss.serv.name;
7837c478bd9Sstevel@tonic-gate 		if ((_nderror = __classic_netdir_getbyname(nconf,
7846392794bSMichen Chang 		    &service, &addrs)) != ND_OK) {
7857c478bd9Sstevel@tonic-gate 			return (_nderror);
7867c478bd9Sstevel@tonic-gate 		}
7877c478bd9Sstevel@tonic-gate 		/*
7887c478bd9Sstevel@tonic-gate 		 * convert addresses back into servent for getservbyname.
7897c478bd9Sstevel@tonic-gate 		 */
7907c478bd9Sstevel@tonic-gate 		_nderror = ndaddr2srent(service.h_serv,
7917c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.proto,
79261961e0fSrobinson 		    /* LINTED pointer cast */
7937c478bd9Sstevel@tonic-gate 		    ((struct sockaddr_in *)addrs->n_addrs->buf)->sin_port,
7947c478bd9Sstevel@tonic-gate 		    res->nss.serv,
7957c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.buf, args->arg.nss.serv.buflen);
7967c478bd9Sstevel@tonic-gate 		netdir_free((char *)addrs, ND_ADDRLIST);
7977c478bd9Sstevel@tonic-gate 		return (_nderror);
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		default:
8007c478bd9Sstevel@tonic-gate 		_nderror = ND_BADARG;
8017c478bd9Sstevel@tonic-gate 		return (ND_BADARG); /* should never happen */
8027c478bd9Sstevel@tonic-gate 	}
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate  * gethostbyaddr/servbyport always call this function; if they call
8077c478bd9Sstevel@tonic-gate  * with nametoaddr libs in nconf, we call netdir_getbyaddr
8087c478bd9Sstevel@tonic-gate  * implementation __classic_netdir_getbyaddr, otherwise nsswitch.
8097c478bd9Sstevel@tonic-gate  *
8107c478bd9Sstevel@tonic-gate  * netdir_getbyaddr calls this only if nametoaddr libs are NOT
8117c478bd9Sstevel@tonic-gate  * specified for inet transports; i.e. it's supposed to follow
8127c478bd9Sstevel@tonic-gate  * the name service switch.
8137c478bd9Sstevel@tonic-gate  */
8147c478bd9Sstevel@tonic-gate int
_get_hostserv_inetnetdir_byaddr(struct netconfig * nconf,struct nss_netdirbyaddr_in * args,union nss_netdirbyaddr_out * res)8157c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byaddr(struct netconfig *nconf,
8167c478bd9Sstevel@tonic-gate     struct nss_netdirbyaddr_in *args, union nss_netdirbyaddr_out *res)
8177c478bd9Sstevel@tonic-gate {
8187c478bd9Sstevel@tonic-gate 	if (nconf == 0) {
8197c478bd9Sstevel@tonic-gate 		_nderror = ND_BADARG;
8207c478bd9Sstevel@tonic-gate 		return (_nderror);
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	/*
8247c478bd9Sstevel@tonic-gate 	 * 1. gethostbyaddr()/netdir_getbyaddr() special cases:
8257c478bd9Sstevel@tonic-gate 	 */
8267c478bd9Sstevel@tonic-gate 	switch (args->op_t) {
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 		case NSS_HOST:
8297c478bd9Sstevel@tonic-gate 		/*
8307c478bd9Sstevel@tonic-gate 		 * Worth the performance gain: assuming a lot of inet apps
8317c478bd9Sstevel@tonic-gate 		 * actively use "127.0.0.1".
8327c478bd9Sstevel@tonic-gate 		 */
83361961e0fSrobinson 		/* LINTED pointer cast */
8347c478bd9Sstevel@tonic-gate 		if (*(uint32_t *)(args->arg.nss.host.addr) ==
8356392794bSMichen Chang 		    htonl(INADDR_LOOPBACK)) {
83661961e0fSrobinson 			(void) mutex_lock(&nd_addr_lock);
8377c478bd9Sstevel@tonic-gate 			IN_SET_LOOPBACK_ADDR(&sa_con);
8387c478bd9Sstevel@tonic-gate 			_nderror = ndaddr2hent(AF_INET, LOCALHOST,
8397c478bd9Sstevel@tonic-gate 			    &nd_conaddrlist, res->nss.host.hent,
8407c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buf,
8417c478bd9Sstevel@tonic-gate 			    args->arg.nss.host.buflen);
84261961e0fSrobinson 			(void) mutex_unlock(&nd_addr_lock);
8437c478bd9Sstevel@tonic-gate 			if (_nderror != ND_OK)
8447c478bd9Sstevel@tonic-gate 				*(res->nss.host.herrno_p) =
8457c478bd9Sstevel@tonic-gate 				    nd2herrno(_nderror);
8467c478bd9Sstevel@tonic-gate 			return (_nderror);
8477c478bd9Sstevel@tonic-gate 		}
8487c478bd9Sstevel@tonic-gate 		break;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		case NETDIR_BY:
8517c478bd9Sstevel@tonic-gate 		case NETDIR_BY_NOSRV:
8527c478bd9Sstevel@tonic-gate 		{
8537c478bd9Sstevel@tonic-gate 			struct sockaddr_in *sin;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 			if (args->arg.nd_nbuf == NULL) {
8567c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
8577c478bd9Sstevel@tonic-gate 				return (_nderror);
8587c478bd9Sstevel@tonic-gate 			}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 			/*
8617c478bd9Sstevel@tonic-gate 			 * Validate the address which was passed
8627c478bd9Sstevel@tonic-gate 			 * as the request.
8637c478bd9Sstevel@tonic-gate 			 */
86461961e0fSrobinson 			/* LINTED pointer cast */
8657c478bd9Sstevel@tonic-gate 			sin = (struct sockaddr_in *)args->arg.nd_nbuf->buf;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 			if ((args->arg.nd_nbuf->len !=
8686392794bSMichen Chang 			    sizeof (struct sockaddr_in)) ||
8697c478bd9Sstevel@tonic-gate 			    (sin->sin_family != AF_INET)) {
8707c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
8717c478bd9Sstevel@tonic-gate 				return (_nderror);
8727c478bd9Sstevel@tonic-gate 			}
8737c478bd9Sstevel@tonic-gate 		}
8747c478bd9Sstevel@tonic-gate 		break;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 		case NETDIR_BY6:
8777c478bd9Sstevel@tonic-gate 		case NETDIR_BY_NOSRV6:
8787c478bd9Sstevel@tonic-gate 		{
8797c478bd9Sstevel@tonic-gate 			struct sockaddr_in6 *sin6;
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 			if (args->arg.nd_nbuf == NULL) {
8827c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
8837c478bd9Sstevel@tonic-gate 				return (_nderror);
8847c478bd9Sstevel@tonic-gate 			}
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 			/*
8877c478bd9Sstevel@tonic-gate 			 * Validate the address which was passed
8887c478bd9Sstevel@tonic-gate 			 * as the request.
8897c478bd9Sstevel@tonic-gate 			 */
89061961e0fSrobinson 			/* LINTED pointer cast */
8917c478bd9Sstevel@tonic-gate 			sin6 = (struct sockaddr_in6 *)args->arg.nd_nbuf->buf;
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 			if ((args->arg.nd_nbuf->len !=
8946392794bSMichen Chang 			    sizeof (struct sockaddr_in6)) ||
8957c478bd9Sstevel@tonic-gate 			    (sin6->sin6_family != AF_INET6)) {
8967c478bd9Sstevel@tonic-gate 				_nderror = ND_BADARG;
8977c478bd9Sstevel@tonic-gate 				return (_nderror);
8987c478bd9Sstevel@tonic-gate 			}
8997c478bd9Sstevel@tonic-gate 		}
9007c478bd9Sstevel@tonic-gate 		break;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	/*
9057c478bd9Sstevel@tonic-gate 	 * 2. Most common scenario. This is the way we ship /etc/netconfig.
9067c478bd9Sstevel@tonic-gate 	 *    Emphasis on improving performance in the "if" part.
9077c478bd9Sstevel@tonic-gate 	 */
9087c478bd9Sstevel@tonic-gate 	if (nconf->nc_nlookups == 0) {
9097c478bd9Sstevel@tonic-gate 		struct hostent	*he = NULL, *tmphe;
9107c478bd9Sstevel@tonic-gate 		struct servent	*se = NULL;
9117c478bd9Sstevel@tonic-gate 		nss_XbyY_buf_t	*ndbuf4host = 0;
9127c478bd9Sstevel@tonic-gate 		nss_XbyY_buf_t	*ndbuf4serv = 0;
9137c478bd9Sstevel@tonic-gate 		char	*proto =
9147c478bd9Sstevel@tonic-gate 		    (strcmp(nconf->nc_proto, NC_TCP) == 0) ? NC_TCP : NC_UDP;
9157c478bd9Sstevel@tonic-gate 		struct	sockaddr_in *sa;
9167c478bd9Sstevel@tonic-gate 		struct sockaddr_in6 *sin6;
9177c478bd9Sstevel@tonic-gate 		struct in_addr *addr4 = 0;
9187c478bd9Sstevel@tonic-gate 		struct in6_addr v4mapbuf;
9197c478bd9Sstevel@tonic-gate 		int	h_errnop;
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	switch (args->op_t) {
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 		case NSS_HOST:
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 		he = DOOR_GETHOSTBYADDR_R(args->arg.nss.host.addr,
9267c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.len, args->arg.nss.host.type,
9277c478bd9Sstevel@tonic-gate 		    res->nss.host.hent, args->arg.nss.host.buf,
9287c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.buflen,
9297c478bd9Sstevel@tonic-gate 		    res->nss.host.herrno_p);
9307c478bd9Sstevel@tonic-gate 		if (he == 0)
9317c478bd9Sstevel@tonic-gate 			_nderror = ND_NOHOST;
9327c478bd9Sstevel@tonic-gate 		else
9337c478bd9Sstevel@tonic-gate 			_nderror = ND_OK;
9347c478bd9Sstevel@tonic-gate 		return (_nderror);
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 		case NSS_HOST6:
9387c478bd9Sstevel@tonic-gate 		he = DOOR_GETIPNODEBYADDR_R(args->arg.nss.host.addr,
9397c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.len, args->arg.nss.host.type,
9407c478bd9Sstevel@tonic-gate 		    res->nss.host.hent, args->arg.nss.host.buf,
9417c478bd9Sstevel@tonic-gate 		    args->arg.nss.host.buflen,
9427c478bd9Sstevel@tonic-gate 		    res->nss.host.herrno_p);
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 		if (he == 0)
9457c478bd9Sstevel@tonic-gate 			return (ND_NOHOST);
9467c478bd9Sstevel@tonic-gate 		return (ND_OK);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 		case NSS_SERV:
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 		se = _switch_getservbyport_r(args->arg.nss.serv.port,
9527c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.proto,
9537c478bd9Sstevel@tonic-gate 		    res->nss.serv, args->arg.nss.serv.buf,
9547c478bd9Sstevel@tonic-gate 		    args->arg.nss.serv.buflen);
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 		if (se == 0)
9577c478bd9Sstevel@tonic-gate 			_nderror = ND_NOSERV;
9587c478bd9Sstevel@tonic-gate 		else
9597c478bd9Sstevel@tonic-gate 			_nderror = ND_OK;
9607c478bd9Sstevel@tonic-gate 		return (_nderror);
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 		case NETDIR_BY:
9637c478bd9Sstevel@tonic-gate 		case NETDIR_BY_NOSRV:
9647c478bd9Sstevel@tonic-gate 
96561961e0fSrobinson 		ndbuf4serv = _nss_XbyY_buf_alloc(sizeof (struct servent),
9666392794bSMichen Chang 		    NSS_BUFLEN_SERVICES);
9677c478bd9Sstevel@tonic-gate 		if (ndbuf4serv == 0) {
9687c478bd9Sstevel@tonic-gate 			_nderror = ND_NOMEM;
9697c478bd9Sstevel@tonic-gate 			return (_nderror);
9707c478bd9Sstevel@tonic-gate 		}
97161961e0fSrobinson 		/* LINTED pointer cast */
9727c478bd9Sstevel@tonic-gate 		sa = (struct sockaddr_in *)(args->arg.nd_nbuf->buf);
9737c478bd9Sstevel@tonic-gate 		addr4 = (struct in_addr *)&(sa->sin_addr);
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		/*
9767c478bd9Sstevel@tonic-gate 		 * if NETDIR_BY_NOSRV or port == 0 skip the service
9777c478bd9Sstevel@tonic-gate 		 * lookup.
9787c478bd9Sstevel@tonic-gate 		 */
9797c478bd9Sstevel@tonic-gate 		if (args->op_t != NETDIR_BY_NOSRV && sa->sin_port != 0) {
9807c478bd9Sstevel@tonic-gate 			se = _switch_getservbyport_r(sa->sin_port, proto,
9817c478bd9Sstevel@tonic-gate 			    ndbuf4serv->result, ndbuf4serv->buffer,
9826392794bSMichen Chang 			    ndbuf4serv->buflen);
9837c478bd9Sstevel@tonic-gate 			if (!se) {
9847c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4serv);
9857c478bd9Sstevel@tonic-gate 				/*
9867c478bd9Sstevel@tonic-gate 				 * We can live with this - i.e. the address
9877c478bd9Sstevel@tonic-gate 				 * does not
9887c478bd9Sstevel@tonic-gate 				 * belong to a well known service. The caller
9897c478bd9Sstevel@tonic-gate 				 * traditionally accepts a stringified port
9907c478bd9Sstevel@tonic-gate 				 * number
9917c478bd9Sstevel@tonic-gate 				 * as the service name. The state of se is used
9927c478bd9Sstevel@tonic-gate 				 * ahead to indicate the same.
9937c478bd9Sstevel@tonic-gate 				 * However, we do not tolerate this nonsense
9947c478bd9Sstevel@tonic-gate 				 * when we cannot get a host name. See below.
9957c478bd9Sstevel@tonic-gate 				 */
9967c478bd9Sstevel@tonic-gate 			}
9977c478bd9Sstevel@tonic-gate 		}
9987c478bd9Sstevel@tonic-gate 
99961961e0fSrobinson 		ndbuf4host = _nss_XbyY_buf_alloc(sizeof (struct hostent),
10006392794bSMichen Chang 		    NSS_BUFLEN_HOSTS);
10017c478bd9Sstevel@tonic-gate 		if (ndbuf4host == 0) {
10027c478bd9Sstevel@tonic-gate 			if (ndbuf4serv)
10037c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4serv);
10047c478bd9Sstevel@tonic-gate 			_nderror = ND_NOMEM;
10057c478bd9Sstevel@tonic-gate 			return (_nderror);
10067c478bd9Sstevel@tonic-gate 		}
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 		/*
10097c478bd9Sstevel@tonic-gate 		 * Since we're going to search the ipnodes (v6) path first,
10107c478bd9Sstevel@tonic-gate 		 * we need to treat the address as a v4mapped address.
10117c478bd9Sstevel@tonic-gate 		 */
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 		IN6_INADDR_TO_V4MAPPED(addr4, &v4mapbuf);
10147c478bd9Sstevel@tonic-gate 		if ((tmphe = DOOR_GETIPNODEBYADDR_R((char *)&v4mapbuf,
10157c478bd9Sstevel@tonic-gate 		    16, AF_INET6, ndbuf4host->result,
10166392794bSMichen Chang 		    ndbuf4host->buffer,
10176392794bSMichen Chang 		    ndbuf4host->buflen, &h_errnop)) != NULL)
10187c478bd9Sstevel@tonic-gate 			he = __mappedtov4(tmphe, &h_errnop);
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 		if (!he) {
10217c478bd9Sstevel@tonic-gate 			/* Failover case, try hosts db for v4 address */
10227c478bd9Sstevel@tonic-gate 			he = DOOR_GETHOSTBYADDR_R((char *)
10236392794bSMichen Chang 			    &(sa->sin_addr.s_addr), 4,
10246392794bSMichen Chang 			    sa->sin_family, ndbuf4host->result,
10256392794bSMichen Chang 			    ndbuf4host->buffer, ndbuf4host->buflen,
10266392794bSMichen Chang 			    &h_errnop);
10277c478bd9Sstevel@tonic-gate 			if (!he) {
10287c478bd9Sstevel@tonic-gate 				NSS_XbyY_FREE(&ndbuf4host);
10297c478bd9Sstevel@tonic-gate 				if (ndbuf4serv)
10307c478bd9Sstevel@tonic-gate 					NSS_XbyY_FREE(&ndbuf4serv);
10317c478bd9Sstevel@tonic-gate 				_nderror = __herrno2netdir(h_errnop);
10327c478bd9Sstevel@tonic-gate 				return (_nderror);
10337c478bd9Sstevel@tonic-gate 			}
10347c478bd9Sstevel@tonic-gate 			/*
10357c478bd9Sstevel@tonic-gate 			 * Convert host names and service names into hostserv
1036