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