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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*61961e0fSrobinson 237c478bd9Sstevel@tonic-gate /* 24*61961e0fSrobinson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 297c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 337c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate * netdir.c 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * This is the library routines that do the name to address 427c478bd9Sstevel@tonic-gate * translation. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include "mt.h" 467c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h" /* for MT declarations only */ 477c478bd9Sstevel@tonic-gate #include <stdio.h> 487c478bd9Sstevel@tonic-gate #include <sys/types.h> 497c478bd9Sstevel@tonic-gate #include <errno.h> 507c478bd9Sstevel@tonic-gate #include <tiuser.h> 517c478bd9Sstevel@tonic-gate #include <netdir.h> 527c478bd9Sstevel@tonic-gate #include <netconfig.h> 537c478bd9Sstevel@tonic-gate #include <string.h> 547c478bd9Sstevel@tonic-gate #include <sys/file.h> 557c478bd9Sstevel@tonic-gate #include <dlfcn.h> 56*61961e0fSrobinson #include <stdlib.h> 577c478bd9Sstevel@tonic-gate #include <malloc.h> 587c478bd9Sstevel@tonic-gate #include <syslog.h> 597c478bd9Sstevel@tonic-gate #include <nss_netdir.h> 607c478bd9Sstevel@tonic-gate #include <netinet/in.h> 617c478bd9Sstevel@tonic-gate #include <netdb.h> 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* messaging stuff. */ 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate extern const char __nsl_dom[]; 667c478bd9Sstevel@tonic-gate extern char *dgettext(const char *, const char *); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate struct translator { 697c478bd9Sstevel@tonic-gate struct nd_addrlist *(*gbn)(); /* _netdir_getbyname */ 707c478bd9Sstevel@tonic-gate struct nd_hostservlist *(*gba)(); /* _netdir_getbyaddr */ 717c478bd9Sstevel@tonic-gate int (*opt)(); /* _netdir_options */ 727c478bd9Sstevel@tonic-gate char *(*t2u)(); /* _taddr2uaddr */ 737c478bd9Sstevel@tonic-gate struct netbuf *(*u2t)(); /* _uaddr2taddr */ 747c478bd9Sstevel@tonic-gate void *tr_fd; /* dyn library handle */ 757c478bd9Sstevel@tonic-gate char *tr_name; /* Full path */ 767c478bd9Sstevel@tonic-gate struct translator *next; 777c478bd9Sstevel@tonic-gate }; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * xlate_lock protects xlate_list during updates only. The xlate_list linked 817c478bd9Sstevel@tonic-gate * list is pre-pended when new entries are added, so threads that are already 827c478bd9Sstevel@tonic-gate * using the list will continue correctly to the end of the list. 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate static struct translator *xlate_list = NULL; 857c478bd9Sstevel@tonic-gate static mutex_t xlate_lock = DEFAULTMUTEX; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static struct translator *load_xlate(char *); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * This is the common data (global data) that is exported 917c478bd9Sstevel@tonic-gate * by public interfaces. It has been moved here from nd_comdata.c 927c478bd9Sstevel@tonic-gate * which no longer exists. This fixes the problem for applications 937c478bd9Sstevel@tonic-gate * that do not link directly with -lnsl but dlopen a shared object 947c478bd9Sstevel@tonic-gate * that has a NEEDED dependency on -lnsl and uses the netdir 957c478bd9Sstevel@tonic-gate * interface. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #undef _nderror 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate int _nderror; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate int * 103*61961e0fSrobinson __nderror(void) 1047c478bd9Sstevel@tonic-gate { 1057c478bd9Sstevel@tonic-gate static pthread_key_t nderror_key = 0; 1067c478bd9Sstevel@tonic-gate int *ret; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if (thr_main()) 1097c478bd9Sstevel@tonic-gate return (&_nderror); 1107c478bd9Sstevel@tonic-gate ret = thr_get_storage(&nderror_key, sizeof (int), free); 1117c478bd9Sstevel@tonic-gate /* if thr_get_storage fails we return the address of _nderror */ 1127c478bd9Sstevel@tonic-gate return (ret ? ret : &_nderror); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate #define _nderror (*(__nderror())) 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Adds a translator library to the xlate_list, but first check to see if 1197c478bd9Sstevel@tonic-gate * it's already on the list. Must be called while holding xlate_lock. 1207c478bd9Sstevel@tonic-gate * We have to be careful for the case of the same library being loaded 1217c478bd9Sstevel@tonic-gate * with different names (e.g., straddr.so and /usr/lib/straddr.so). 1227c478bd9Sstevel@tonic-gate * We check for this case by looking at the gbn and name fields. 1237c478bd9Sstevel@tonic-gate * If the gbn address is the same, but the names are different, then we 1247c478bd9Sstevel@tonic-gate * have accidentally reloaded the library. We dlclose the new version, 1257c478bd9Sstevel@tonic-gate * and then update 'translate' with the old versions of the symbols. 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate void 128*61961e0fSrobinson add_to_xlate_list(struct translator *translate) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate struct translator *t; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 1337c478bd9Sstevel@tonic-gate if (strcmp(translate->tr_name, t->tr_name) == 0) { 1347c478bd9Sstevel@tonic-gate return; 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate translate->next = xlate_list; 1387c478bd9Sstevel@tonic-gate xlate_list = translate; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * This routine is the main routine that resolves host/service/xprt triples 1437c478bd9Sstevel@tonic-gate * into a bunch of netbufs that should connect you to that particular 1447c478bd9Sstevel@tonic-gate * service. RPC uses it to contact the binder service (rpcbind). 1457c478bd9Sstevel@tonic-gate * 1467c478bd9Sstevel@tonic-gate * In the interest of consistency with the gethost/servbyYY() routines, 1477c478bd9Sstevel@tonic-gate * this routine calls a common interface _get_hostserv_inetnetdir_byname 1487c478bd9Sstevel@tonic-gate * if it's called with a netconfig with "inet" type transports and 1497c478bd9Sstevel@tonic-gate * an empty list of nametoaddr libs (i.e. a "-" in /etc/netconfig), 1507c478bd9Sstevel@tonic-gate * which indicates the use of the switch. For non-inet transports or 1517c478bd9Sstevel@tonic-gate * inet transports with nametoaddr libs specified, it simply calls 1527c478bd9Sstevel@tonic-gate * the SVr4-classic netdir_getbyname, which loops through the libs. 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * After all, any problem can be solved by one more layer of abstraction.. 1557c478bd9Sstevel@tonic-gate * 1567c478bd9Sstevel@tonic-gate * This routine when called with a netconfig with "inet6" type of transports 1577c478bd9Sstevel@tonic-gate * returns pure IPv6 addresses only and if no IPv6 address is found it 1587c478bd9Sstevel@tonic-gate * returns none - Bug Id. 4276329 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate int 161*61961e0fSrobinson netdir_getbyname(struct netconfig *tp, struct nd_hostserv *serv, 162*61961e0fSrobinson struct nd_addrlist **addrs) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate if (tp == 0) { 1657c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 1667c478bd9Sstevel@tonic-gate return (_nderror); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0) && 1697c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 1707c478bd9Sstevel@tonic-gate struct nss_netdirbyname_in nssin; 1717c478bd9Sstevel@tonic-gate union nss_netdirbyname_out nssout; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY; 1747c478bd9Sstevel@tonic-gate nssin.arg.nd_hs = serv; 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * In code path of case NETDIR_BY, 1777c478bd9Sstevel@tonic-gate * it also calls DOOR_GETIPNODEBYNAME_R. 1787c478bd9Sstevel@tonic-gate * So af_family and flags are set to 1797c478bd9Sstevel@tonic-gate * get V4 addresses only. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate nssin.arg.nss.host6.af_family = AF_INET; 1827c478bd9Sstevel@tonic-gate nssin.arg.nss.host6.flags = 0; 1837c478bd9Sstevel@tonic-gate nssout.nd_alist = addrs; 1847c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byname(tp, &nssin, &nssout)); 185*61961e0fSrobinson } 186*61961e0fSrobinson if ((strcmp(tp->nc_protofmly, NC_INET6) == 0) && 1877c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 1887c478bd9Sstevel@tonic-gate struct nss_netdirbyname_in nssin; 1897c478bd9Sstevel@tonic-gate union nss_netdirbyname_out nssout; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY6; 1927c478bd9Sstevel@tonic-gate nssin.arg.nd_hs = serv; 1937c478bd9Sstevel@tonic-gate /* get both V4 & V6 addresses */ 1947c478bd9Sstevel@tonic-gate nssin.arg.nss.host6.af_family = AF_INET6; 1957c478bd9Sstevel@tonic-gate nssin.arg.nss.host6.flags = (AI_ALL | AI_V4MAPPED); 1967c478bd9Sstevel@tonic-gate nssout.nd_alist = addrs; 1977c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byname(tp, &nssin, &nssout)); 1987c478bd9Sstevel@tonic-gate } 199*61961e0fSrobinson return (__classic_netdir_getbyname(tp, serv, addrs)); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * This routine is the svr4_classic routine for resolving host/service/xprt 2047c478bd9Sstevel@tonic-gate * triples into a bunch of netbufs that should connect you to that particular 2057c478bd9Sstevel@tonic-gate * service. RPC uses it to contact the binder service (rpcbind). 2067c478bd9Sstevel@tonic-gate * 2077c478bd9Sstevel@tonic-gate * It's either called by the real netdir_getbyname() interface above 2087c478bd9Sstevel@tonic-gate * or by gethost/servbyname when nametoaddr libs are specified in 2097c478bd9Sstevel@tonic-gate * /etc/netconfig with an intent of bypassing the name service switch. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate int 212*61961e0fSrobinson __classic_netdir_getbyname(struct netconfig *tp, struct nd_hostserv *serv, 213*61961e0fSrobinson struct nd_addrlist **addrs) 2147c478bd9Sstevel@tonic-gate { 2157c478bd9Sstevel@tonic-gate struct translator *t; /* pointer to translator list */ 2167c478bd9Sstevel@tonic-gate struct nd_addrlist *nn; /* the results */ 2177c478bd9Sstevel@tonic-gate char *lr; /* routines to try */ 2187c478bd9Sstevel@tonic-gate int i; /* counts the routines */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; 2217c478bd9Sstevel@tonic-gate for (i = 0; i < tp->nc_nlookups; i++) { 2227c478bd9Sstevel@tonic-gate lr = *((tp->nc_lookups) + i); 2237c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 2247c478bd9Sstevel@tonic-gate if (strcmp(lr, t->tr_name) == 0) { 2257c478bd9Sstevel@tonic-gate nn = (*(t->gbn))(tp, serv); 2267c478bd9Sstevel@tonic-gate if (nn) { 2277c478bd9Sstevel@tonic-gate *addrs = nn; 2287c478bd9Sstevel@tonic-gate return (0); 229*61961e0fSrobinson } 2307c478bd9Sstevel@tonic-gate if (_nderror < 0) { 2317c478bd9Sstevel@tonic-gate return (_nderror); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate /* If we didn't find it try loading it */ 2377c478bd9Sstevel@tonic-gate if (!t) { 2387c478bd9Sstevel@tonic-gate if ((t = load_xlate(lr)) != NULL) { 2397c478bd9Sstevel@tonic-gate /* add it to the list */ 240*61961e0fSrobinson (void) mutex_lock(&xlate_lock); 2417c478bd9Sstevel@tonic-gate add_to_xlate_list(t); 242*61961e0fSrobinson (void) mutex_unlock(&xlate_lock); 2437c478bd9Sstevel@tonic-gate nn = (*(t->gbn))(tp, serv); 2447c478bd9Sstevel@tonic-gate if (nn) { 2457c478bd9Sstevel@tonic-gate *addrs = nn; 2467c478bd9Sstevel@tonic-gate return (0); 2477c478bd9Sstevel@tonic-gate } 248*61961e0fSrobinson if (_nderror < 0) { 249*61961e0fSrobinson return (_nderror); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate } else { 2527c478bd9Sstevel@tonic-gate if (_nderror == ND_SYSTEM) { /* retry cache */ 2537c478bd9Sstevel@tonic-gate _nderror = ND_OK; 2547c478bd9Sstevel@tonic-gate i--; 2557c478bd9Sstevel@tonic-gate continue; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate return (_nderror); /* No one works */ 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * This routine is similar to the one above except that it tries to resolve 2657c478bd9Sstevel@tonic-gate * the name by the address passed. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate int 268*61961e0fSrobinson netdir_getbyaddr(struct netconfig *tp, struct nd_hostservlist **serv, 269*61961e0fSrobinson struct netbuf *addr) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate if (tp == 0) { 2727c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 2737c478bd9Sstevel@tonic-gate return (_nderror); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0) && 2767c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 2777c478bd9Sstevel@tonic-gate struct nss_netdirbyaddr_in nssin; 2787c478bd9Sstevel@tonic-gate union nss_netdirbyaddr_out nssout; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY; 2817c478bd9Sstevel@tonic-gate nssin.arg.nd_nbuf = addr; 2827c478bd9Sstevel@tonic-gate nssout.nd_hslist = serv; 2837c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byaddr(tp, &nssin, &nssout)); 284*61961e0fSrobinson } 285*61961e0fSrobinson if ((strcmp(tp->nc_protofmly, NC_INET6) == 0) && 2867c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 2877c478bd9Sstevel@tonic-gate struct nss_netdirbyaddr_in nssin; 2887c478bd9Sstevel@tonic-gate union nss_netdirbyaddr_out nssout; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY6; 2917c478bd9Sstevel@tonic-gate nssin.arg.nd_nbuf = addr; 2927c478bd9Sstevel@tonic-gate nssout.nd_hslist = serv; 2937c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byaddr(tp, &nssin, &nssout)); 2947c478bd9Sstevel@tonic-gate } 295*61961e0fSrobinson return (__classic_netdir_getbyaddr(tp, serv, addr)); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * This routine is similar to the one above except that it instructs the 2997c478bd9Sstevel@tonic-gate * _get_hostserv_inetnetdir_byaddr not to do a service lookup. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate int 302*61961e0fSrobinson __netdir_getbyaddr_nosrv(struct netconfig *tp, struct nd_hostservlist **serv, 303*61961e0fSrobinson struct netbuf *addr) 3047c478bd9Sstevel@tonic-gate { 3057c478bd9Sstevel@tonic-gate if (tp == 0) { 3067c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 3077c478bd9Sstevel@tonic-gate return (_nderror); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0) && 3107c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 3117c478bd9Sstevel@tonic-gate struct nss_netdirbyaddr_in nssin; 3127c478bd9Sstevel@tonic-gate union nss_netdirbyaddr_out nssout; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY_NOSRV; 3157c478bd9Sstevel@tonic-gate nssin.arg.nd_nbuf = addr; 3167c478bd9Sstevel@tonic-gate nssout.nd_hslist = serv; 3177c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byaddr(tp, &nssin, &nssout)); 318*61961e0fSrobinson } 319*61961e0fSrobinson if ((strcmp(tp->nc_protofmly, NC_INET6) == 0) && 3207c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 3217c478bd9Sstevel@tonic-gate struct nss_netdirbyaddr_in nssin; 3227c478bd9Sstevel@tonic-gate union nss_netdirbyaddr_out nssout; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate nssin.op_t = NETDIR_BY_NOSRV6; 3257c478bd9Sstevel@tonic-gate nssin.arg.nd_nbuf = addr; 3267c478bd9Sstevel@tonic-gate nssout.nd_hslist = serv; 3277c478bd9Sstevel@tonic-gate return (_get_hostserv_inetnetdir_byaddr(tp, &nssin, &nssout)); 3287c478bd9Sstevel@tonic-gate } 329*61961e0fSrobinson return (__classic_netdir_getbyaddr(tp, serv, addr)); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * This routine is the svr4_classic routine for resolving a netbuf struct 3347c478bd9Sstevel@tonic-gate * into a bunch of host/service name pairs. 3357c478bd9Sstevel@tonic-gate * 3367c478bd9Sstevel@tonic-gate * It's either called by the real netdir_getbyaddr() interface above 3377c478bd9Sstevel@tonic-gate * or by gethost/servbyaddr when nametoaddr libs are specified in 3387c478bd9Sstevel@tonic-gate * /etc/netconfig with an intent of bypassing the name service switch. 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate int 341*61961e0fSrobinson __classic_netdir_getbyaddr(struct netconfig *tp, struct nd_hostservlist **serv, 342*61961e0fSrobinson struct netbuf *addr) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate struct translator *t; /* pointer to translator list */ 3457c478bd9Sstevel@tonic-gate struct nd_hostservlist *hs; /* the results */ 3467c478bd9Sstevel@tonic-gate char *lr; /* routines to try */ 3477c478bd9Sstevel@tonic-gate int i; /* counts the routines */ 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; 3507c478bd9Sstevel@tonic-gate for (i = 0; i < tp->nc_nlookups; i++) { 3517c478bd9Sstevel@tonic-gate lr = *((tp->nc_lookups) + i); 3527c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 3537c478bd9Sstevel@tonic-gate if (strcmp(lr, t->tr_name) == 0) { 3547c478bd9Sstevel@tonic-gate hs = (*(t->gba))(tp, addr); 3557c478bd9Sstevel@tonic-gate if (hs) { 3567c478bd9Sstevel@tonic-gate *serv = hs; 3577c478bd9Sstevel@tonic-gate return (0); 358*61961e0fSrobinson } 359*61961e0fSrobinson if (_nderror < 0) 3607c478bd9Sstevel@tonic-gate return (_nderror); 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate /* If we didn't find it try loading it */ 3657c478bd9Sstevel@tonic-gate if (!t) { 3667c478bd9Sstevel@tonic-gate if ((t = load_xlate(lr)) != NULL) { 3677c478bd9Sstevel@tonic-gate /* add it to the list */ 368*61961e0fSrobinson (void) mutex_lock(&xlate_lock); 3697c478bd9Sstevel@tonic-gate add_to_xlate_list(t); 370*61961e0fSrobinson (void) mutex_unlock(&xlate_lock); 3717c478bd9Sstevel@tonic-gate hs = (*(t->gba))(tp, addr); 3727c478bd9Sstevel@tonic-gate if (hs) { 3737c478bd9Sstevel@tonic-gate *serv = hs; 3747c478bd9Sstevel@tonic-gate return (0); 375*61961e0fSrobinson } 376*61961e0fSrobinson if (_nderror < 0) 3777c478bd9Sstevel@tonic-gate return (_nderror); 3787c478bd9Sstevel@tonic-gate } else { 3797c478bd9Sstevel@tonic-gate if (_nderror == ND_SYSTEM) { /* retry cache */ 3807c478bd9Sstevel@tonic-gate _nderror = ND_OK; 3817c478bd9Sstevel@tonic-gate i--; 3827c478bd9Sstevel@tonic-gate continue; 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate return (_nderror); /* No one works */ 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * This is the library routine to do transport specific stuff. 3927c478bd9Sstevel@tonic-gate * The code is same as the other similar routines except that it does 3937c478bd9Sstevel@tonic-gate * not bother to try whole bunch of routines since if the first 3947c478bd9Sstevel@tonic-gate * libray cannot resolve the option, then no one can. 3957c478bd9Sstevel@tonic-gate * 3967c478bd9Sstevel@tonic-gate * If it gets a netconfig structure for inet transports with nametoddr libs, 3977c478bd9Sstevel@tonic-gate * it simply calls the inet-specific built in implementation. 3987c478bd9Sstevel@tonic-gate */ 3997c478bd9Sstevel@tonic-gate int 400*61961e0fSrobinson netdir_options(struct netconfig *tp, int option, int fd, char *par) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate struct translator *t; /* pointer to translator list */ 4037c478bd9Sstevel@tonic-gate char *lr; /* routines to try */ 4047c478bd9Sstevel@tonic-gate int i; /* counts the routines */ 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (tp == 0) { 4077c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 4087c478bd9Sstevel@tonic-gate return (_nderror); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0 || 4127c478bd9Sstevel@tonic-gate strcmp(tp->nc_protofmly, NC_INET6) == 0) && 4137c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 4147c478bd9Sstevel@tonic-gate return (__inet_netdir_options(tp, option, fd, par)); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate for (i = 0; i < tp->nc_nlookups; i++) { 4197c478bd9Sstevel@tonic-gate lr = *((tp->nc_lookups) + i); 4207c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 421*61961e0fSrobinson if (strcmp(lr, t->tr_name) == 0) 4227c478bd9Sstevel@tonic-gate return ((*(t->opt))(tp, option, fd, par)); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate /* If we didn't find it try loading it */ 4257c478bd9Sstevel@tonic-gate if (!t) { 4267c478bd9Sstevel@tonic-gate if ((t = load_xlate(lr)) != NULL) { 4277c478bd9Sstevel@tonic-gate /* add it to the list */ 428*61961e0fSrobinson (void) mutex_lock(&xlate_lock); 4297c478bd9Sstevel@tonic-gate add_to_xlate_list(t); 430*61961e0fSrobinson (void) mutex_unlock(&xlate_lock); 4317c478bd9Sstevel@tonic-gate return ((*(t->opt))(tp, option, fd, par)); 432*61961e0fSrobinson } 4337c478bd9Sstevel@tonic-gate if (_nderror == ND_SYSTEM) { /* retry cache */ 4347c478bd9Sstevel@tonic-gate _nderror = ND_OK; 4357c478bd9Sstevel@tonic-gate i--; 4367c478bd9Sstevel@tonic-gate continue; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate return (_nderror); /* No one works */ 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * This is the library routine for translating universal addresses to 4457c478bd9Sstevel@tonic-gate * transport specific addresses. Again it uses the same code as above 4467c478bd9Sstevel@tonic-gate * to search for the appropriate translation routine. Only it doesn't 4477c478bd9Sstevel@tonic-gate * bother trying a whole bunch of routines since either the transport 4487c478bd9Sstevel@tonic-gate * can translate it or it can't. 4497c478bd9Sstevel@tonic-gate */ 4507c478bd9Sstevel@tonic-gate struct netbuf * 451*61961e0fSrobinson uaddr2taddr(struct netconfig *tp, char *addr) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate struct translator *t; /* pointer to translator list */ 4547c478bd9Sstevel@tonic-gate struct netbuf *x; /* the answer we want */ 4557c478bd9Sstevel@tonic-gate char *lr; /* routines to try */ 4567c478bd9Sstevel@tonic-gate int i; /* counts the routines */ 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate if (tp == 0) { 4597c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 4607c478bd9Sstevel@tonic-gate return (0); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0 || 4637c478bd9Sstevel@tonic-gate strcmp(tp->nc_protofmly, NC_INET6) == 0) && 4647c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 4657c478bd9Sstevel@tonic-gate return (__inet_uaddr2taddr(tp, addr)); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate for (i = 0; i < tp->nc_nlookups; i++) { 4687c478bd9Sstevel@tonic-gate lr = *((tp->nc_lookups) + i); 4697c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 4707c478bd9Sstevel@tonic-gate if (strcmp(lr, t->tr_name) == 0) { 4717c478bd9Sstevel@tonic-gate x = (*(t->u2t))(tp, addr); 472*61961e0fSrobinson if (x) 4737c478bd9Sstevel@tonic-gate return (x); 474*61961e0fSrobinson if (_nderror < 0) 4757c478bd9Sstevel@tonic-gate return (0); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate /* If we didn't find it try loading it */ 4797c478bd9Sstevel@tonic-gate if (!t) { 4807c478bd9Sstevel@tonic-gate if ((t = load_xlate(lr)) != NULL) { 4817c478bd9Sstevel@tonic-gate /* add it to the list */ 482*61961e0fSrobinson (void) mutex_lock(&xlate_lock); 4837c478bd9Sstevel@tonic-gate add_to_xlate_list(t); 484*61961e0fSrobinson (void) mutex_unlock(&xlate_lock); 4857c478bd9Sstevel@tonic-gate x = (*(t->u2t))(tp, addr); 486*61961e0fSrobinson if (x) 4877c478bd9Sstevel@tonic-gate return (x); 488*61961e0fSrobinson if (_nderror < 0) 4897c478bd9Sstevel@tonic-gate return (0); 4907c478bd9Sstevel@tonic-gate } else { 4917c478bd9Sstevel@tonic-gate if (_nderror == ND_SYSTEM) { /* retry cache */ 4927c478bd9Sstevel@tonic-gate _nderror = ND_OK; 4937c478bd9Sstevel@tonic-gate i--; 4947c478bd9Sstevel@tonic-gate continue; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate return (0); /* No one works */ 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * This is the library routine for translating transport specific 5047c478bd9Sstevel@tonic-gate * addresses to universal addresses. Again it uses the same code as above 5057c478bd9Sstevel@tonic-gate * to search for the appropriate translation routine. Only it doesn't 5067c478bd9Sstevel@tonic-gate * bother trying a whole bunch of routines since either the transport 5077c478bd9Sstevel@tonic-gate * can translate it or it can't. 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gate char * 510*61961e0fSrobinson taddr2uaddr(struct netconfig *tp, struct netbuf *addr) 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate struct translator *t; /* pointer to translator list */ 5137c478bd9Sstevel@tonic-gate char *lr; /* routines to try */ 5147c478bd9Sstevel@tonic-gate char *x; /* the answer */ 5157c478bd9Sstevel@tonic-gate int i; /* counts the routines */ 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate if (tp == 0) { 5187c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 5197c478bd9Sstevel@tonic-gate return (0); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if ((strcmp(tp->nc_protofmly, NC_INET) == 0 || 5227c478bd9Sstevel@tonic-gate strcmp(tp->nc_protofmly, NC_INET6) == 0) && 5237c478bd9Sstevel@tonic-gate (tp->nc_nlookups == 0)) { 5247c478bd9Sstevel@tonic-gate return (__inet_taddr2uaddr(tp, addr)); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate for (i = 0; i < tp->nc_nlookups; i++) { 5277c478bd9Sstevel@tonic-gate lr = *((tp->nc_lookups) + i); 5287c478bd9Sstevel@tonic-gate for (t = xlate_list; t; t = t->next) { 5297c478bd9Sstevel@tonic-gate if (strcmp(lr, t->tr_name) == 0) { 5307c478bd9Sstevel@tonic-gate x = (*(t->t2u))(tp, addr); 531*61961e0fSrobinson if (x) 5327c478bd9Sstevel@tonic-gate return (x); 533*61961e0fSrobinson if (_nderror < 0) 5347c478bd9Sstevel@tonic-gate return (0); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate /* If we didn't find it try loading it */ 5387c478bd9Sstevel@tonic-gate if (!t) { 5397c478bd9Sstevel@tonic-gate if ((t = load_xlate(lr)) != NULL) { 5407c478bd9Sstevel@tonic-gate /* add it to the list */ 541*61961e0fSrobinson (void) mutex_lock(&xlate_lock); 5427c478bd9Sstevel@tonic-gate add_to_xlate_list(t); 543*61961e0fSrobinson (void) mutex_unlock(&xlate_lock); 5447c478bd9Sstevel@tonic-gate x = (*(t->t2u))(tp, addr); 545*61961e0fSrobinson if (x) 5467c478bd9Sstevel@tonic-gate return (x); 547*61961e0fSrobinson if (_nderror < 0) 5487c478bd9Sstevel@tonic-gate return (0); 5497c478bd9Sstevel@tonic-gate } else { 5507c478bd9Sstevel@tonic-gate if (_nderror == ND_SYSTEM) { /* retry cache */ 5517c478bd9Sstevel@tonic-gate _nderror = ND_OK; 5527c478bd9Sstevel@tonic-gate i--; 5537c478bd9Sstevel@tonic-gate continue; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate return (0); /* No one works */ 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * This is the routine that frees the objects that these routines allocate. 5637c478bd9Sstevel@tonic-gate */ 5647c478bd9Sstevel@tonic-gate void 565*61961e0fSrobinson netdir_free(void *ptr, int type) 5667c478bd9Sstevel@tonic-gate { 5677c478bd9Sstevel@tonic-gate struct netbuf *na; 5687c478bd9Sstevel@tonic-gate struct nd_addrlist *nas; 5697c478bd9Sstevel@tonic-gate struct nd_hostserv *hs; 5707c478bd9Sstevel@tonic-gate struct nd_hostservlist *hss; 5717c478bd9Sstevel@tonic-gate int i; 5727c478bd9Sstevel@tonic-gate 573*61961e0fSrobinson if (ptr == NULL) 5747c478bd9Sstevel@tonic-gate return; 5757c478bd9Sstevel@tonic-gate switch (type) { 5767c478bd9Sstevel@tonic-gate case ND_ADDR : 5777c478bd9Sstevel@tonic-gate na = (struct netbuf *)ptr; 5787c478bd9Sstevel@tonic-gate if (na->buf) 5797c478bd9Sstevel@tonic-gate free(na->buf); 580*61961e0fSrobinson free(na); 5817c478bd9Sstevel@tonic-gate break; 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate case ND_ADDRLIST : 5847c478bd9Sstevel@tonic-gate nas = (struct nd_addrlist *)ptr; 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * XXX: We do NOT try to free all individual netbuf->buf 5877c478bd9Sstevel@tonic-gate * pointers. Free only the first one since they are allocated 5887c478bd9Sstevel@tonic-gate * using one calloc in 5897c478bd9Sstevel@tonic-gate * libnsl/nss/netdir_inet.c:order_haddrlist(). 5907c478bd9Sstevel@tonic-gate * This potentially causes memory leaks if a nametoaddr 5917c478bd9Sstevel@tonic-gate * implementation -- from a third party -- has a different 5927c478bd9Sstevel@tonic-gate * allocation scheme. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate if (nas->n_addrs->buf) 5957c478bd9Sstevel@tonic-gate free(nas->n_addrs->buf); 596*61961e0fSrobinson free(nas->n_addrs); 597*61961e0fSrobinson free(nas); 5987c478bd9Sstevel@tonic-gate break; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate case ND_HOSTSERV : 6017c478bd9Sstevel@tonic-gate hs = (struct nd_hostserv *)ptr; 6027c478bd9Sstevel@tonic-gate if (hs->h_host) 6037c478bd9Sstevel@tonic-gate free(hs->h_host); 6047c478bd9Sstevel@tonic-gate if (hs->h_serv) 6057c478bd9Sstevel@tonic-gate free(hs->h_serv); 606*61961e0fSrobinson free(hs); 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate case ND_HOSTSERVLIST : 6107c478bd9Sstevel@tonic-gate hss = (struct nd_hostservlist *)ptr; 6117c478bd9Sstevel@tonic-gate for (hs = hss->h_hostservs, i = 0; i < hss->h_cnt; i++, hs++) { 6127c478bd9Sstevel@tonic-gate if (hs->h_host) 6137c478bd9Sstevel@tonic-gate free(hs->h_host); 6147c478bd9Sstevel@tonic-gate if (hs->h_serv) 6157c478bd9Sstevel@tonic-gate free(hs->h_serv); 6167c478bd9Sstevel@tonic-gate } 617*61961e0fSrobinson free(hss->h_hostservs); 618*61961e0fSrobinson free(hss); 6197c478bd9Sstevel@tonic-gate break; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate default : 6227c478bd9Sstevel@tonic-gate _nderror = ND_UKNWN; 6237c478bd9Sstevel@tonic-gate break; 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * load_xlate is a routine that will attempt to dynamically link in the 6297c478bd9Sstevel@tonic-gate * file specified by the network configuration structure. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate static struct translator * 632*61961e0fSrobinson load_xlate(char *name) 6337c478bd9Sstevel@tonic-gate { 6347c478bd9Sstevel@tonic-gate struct translator *t; 6357c478bd9Sstevel@tonic-gate static struct xlate_list { 6367c478bd9Sstevel@tonic-gate char *library; 6377c478bd9Sstevel@tonic-gate struct xlate_list *next; 6387c478bd9Sstevel@tonic-gate } *xlistp = NULL; 6397c478bd9Sstevel@tonic-gate struct xlate_list *xlp, **xlastp; 6407c478bd9Sstevel@tonic-gate static mutex_t xlist_lock = DEFAULTMUTEX; 6417c478bd9Sstevel@tonic-gate 642*61961e0fSrobinson (void) mutex_lock(&xlist_lock); 6437c478bd9Sstevel@tonic-gate /* 6447c478bd9Sstevel@tonic-gate * We maintain a list of libraries we have loaded. Loading a library 6457c478bd9Sstevel@tonic-gate * twice is double-plus ungood! 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate for (xlp = xlistp, xlastp = &xlistp; xlp != NULL; 6487c478bd9Sstevel@tonic-gate xlastp = &xlp->next, xlp = xlp->next) { 6497c478bd9Sstevel@tonic-gate if (xlp->library != NULL) { 6507c478bd9Sstevel@tonic-gate if (strcmp(xlp->library, name) == 0) { 6517c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; /* seen this lib */ 652*61961e0fSrobinson (void) mutex_unlock(&xlist_lock); 6537c478bd9Sstevel@tonic-gate return (0); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate } 657*61961e0fSrobinson t = malloc(sizeof (struct translator)); 6587c478bd9Sstevel@tonic-gate if (!t) { 6597c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 660*61961e0fSrobinson (void) mutex_unlock(&xlist_lock); 6617c478bd9Sstevel@tonic-gate return (0); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate t->tr_name = strdup(name); 6647c478bd9Sstevel@tonic-gate if (!t->tr_name) { 6657c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 666*61961e0fSrobinson free(t); 667*61961e0fSrobinson (void) mutex_unlock(&xlist_lock); 6687c478bd9Sstevel@tonic-gate return (NULL); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate t->tr_fd = dlopen(name, RTLD_LAZY); 6727c478bd9Sstevel@tonic-gate if (t->tr_fd == NULL) { 6737c478bd9Sstevel@tonic-gate _nderror = ND_OPEN; 6747c478bd9Sstevel@tonic-gate goto error; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* Resolve the getbyname symbol */ 6787c478bd9Sstevel@tonic-gate t->gbn = (struct nd_addrlist *(*)())dlsym(t->tr_fd, 6797c478bd9Sstevel@tonic-gate "_netdir_getbyname"); 6807c478bd9Sstevel@tonic-gate if (!(t->gbn)) { 6817c478bd9Sstevel@tonic-gate _nderror = ND_NOSYM; 6827c478bd9Sstevel@tonic-gate goto error; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* resolve the getbyaddr symbol */ 6867c478bd9Sstevel@tonic-gate t->gba = (struct nd_hostservlist *(*)())dlsym(t->tr_fd, 6877c478bd9Sstevel@tonic-gate "_netdir_getbyaddr"); 6887c478bd9Sstevel@tonic-gate if (!(t->gba)) { 6897c478bd9Sstevel@tonic-gate _nderror = ND_NOSYM; 6907c478bd9Sstevel@tonic-gate goto error; 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* resolve the taddr2uaddr symbol */ 6947c478bd9Sstevel@tonic-gate t->t2u = (char *(*)())dlsym(t->tr_fd, "_taddr2uaddr"); 6957c478bd9Sstevel@tonic-gate if (!(t->t2u)) { 6967c478bd9Sstevel@tonic-gate _nderror = ND_NOSYM; 6977c478bd9Sstevel@tonic-gate goto error; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* resolve the uaddr2taddr symbol */ 7017c478bd9Sstevel@tonic-gate t->u2t = (struct netbuf *(*)())dlsym(t->tr_fd, "_uaddr2taddr"); 7027c478bd9Sstevel@tonic-gate if (!(t->u2t)) { 7037c478bd9Sstevel@tonic-gate _nderror = ND_NOSYM; 7047c478bd9Sstevel@tonic-gate goto error; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate /* resolve the netdir_options symbol */ 7087c478bd9Sstevel@tonic-gate t->opt = (int (*)())dlsym(t->tr_fd, "_netdir_options"); 7097c478bd9Sstevel@tonic-gate if (!(t->opt)) { 7107c478bd9Sstevel@tonic-gate _nderror = ND_NOSYM; 7117c478bd9Sstevel@tonic-gate goto error; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * Add this library to the list of loaded libraries. 7157c478bd9Sstevel@tonic-gate */ 716*61961e0fSrobinson *xlastp = malloc(sizeof (struct xlate_list)); 7177c478bd9Sstevel@tonic-gate if (*xlastp == NULL) { 7187c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 7197c478bd9Sstevel@tonic-gate goto error; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate (*xlastp)->library = strdup(name); 7227c478bd9Sstevel@tonic-gate if ((*xlastp)->library == NULL) { 7237c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 7247c478bd9Sstevel@tonic-gate free(*xlastp); 7257c478bd9Sstevel@tonic-gate goto error; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate (*xlastp)->next = NULL; 728*61961e0fSrobinson (void) mutex_unlock(&xlist_lock); 7297c478bd9Sstevel@tonic-gate return (t); 7307c478bd9Sstevel@tonic-gate error: 7317c478bd9Sstevel@tonic-gate if (t->tr_fd != NULL) 7327c478bd9Sstevel@tonic-gate (void) dlclose(t->tr_fd); 7337c478bd9Sstevel@tonic-gate free(t->tr_name); 734*61961e0fSrobinson free(t); 735*61961e0fSrobinson (void) mutex_unlock(&xlist_lock); 7367c478bd9Sstevel@tonic-gate return (NULL); 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate #define NDERR_BUFSZ 512 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* 7437c478bd9Sstevel@tonic-gate * This is a routine that returns a string related to the current 7447c478bd9Sstevel@tonic-gate * error in _nderror. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate char * 747*61961e0fSrobinson netdir_sperror(void) 7487c478bd9Sstevel@tonic-gate { 7497c478bd9Sstevel@tonic-gate static pthread_key_t nderrbuf_key = 0; 7507c478bd9Sstevel@tonic-gate static char buf_main[NDERR_BUFSZ]; 7517c478bd9Sstevel@tonic-gate char *str; 7527c478bd9Sstevel@tonic-gate char *dlerrstr; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate str = thr_main()? 7557c478bd9Sstevel@tonic-gate buf_main : 7567c478bd9Sstevel@tonic-gate thr_get_storage(&nderrbuf_key, NDERR_BUFSZ, free); 757*61961e0fSrobinson if (str == NULL) 7587c478bd9Sstevel@tonic-gate return (NULL); 7597c478bd9Sstevel@tonic-gate dlerrstr = dlerror(); 7607c478bd9Sstevel@tonic-gate switch (_nderror) { 7617c478bd9Sstevel@tonic-gate case ND_NOMEM : 7627c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7637c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: memory allocation failed")); 7647c478bd9Sstevel@tonic-gate break; 7657c478bd9Sstevel@tonic-gate case ND_OK : 7667c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7677c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: successful completion")); 7687c478bd9Sstevel@tonic-gate break; 7697c478bd9Sstevel@tonic-gate case ND_NOHOST : 7707c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7717c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: hostname not found")); 7727c478bd9Sstevel@tonic-gate break; 7737c478bd9Sstevel@tonic-gate case ND_NOSERV : 7747c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7757c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: service name not found")); 7767c478bd9Sstevel@tonic-gate break; 7777c478bd9Sstevel@tonic-gate case ND_NOSYM : 7787c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, "%s : %s ", 7797c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 7807c478bd9Sstevel@tonic-gate "n2a: symbol missing in shared object"), 7817c478bd9Sstevel@tonic-gate dlerrstr ? dlerrstr : " "); 7827c478bd9Sstevel@tonic-gate break; 7837c478bd9Sstevel@tonic-gate case ND_OPEN : 7847c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, "%s - %s ", 7857c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: couldn't open shared object"), 7867c478bd9Sstevel@tonic-gate dlerrstr ? dlerrstr : " "); 7877c478bd9Sstevel@tonic-gate break; 7887c478bd9Sstevel@tonic-gate case ND_ACCESS : 7897c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7907c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 7917c478bd9Sstevel@tonic-gate "n2a: access denied for shared object")); 7927c478bd9Sstevel@tonic-gate break; 7937c478bd9Sstevel@tonic-gate case ND_UKNWN : 7947c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 7957c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 7967c478bd9Sstevel@tonic-gate "n2a: attempt to free unknown object")); 7977c478bd9Sstevel@tonic-gate break; 7987c478bd9Sstevel@tonic-gate case ND_BADARG : 7997c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 8007c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, 8017c478bd9Sstevel@tonic-gate "n2a: bad arguments passed to routine")); 8027c478bd9Sstevel@tonic-gate break; 8037c478bd9Sstevel@tonic-gate case ND_NOCTRL: 8047c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 8057c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: unknown option passed")); 8067c478bd9Sstevel@tonic-gate break; 8077c478bd9Sstevel@tonic-gate case ND_FAILCTRL: 8087c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, 8097c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: control operation failed")); 8107c478bd9Sstevel@tonic-gate break; 8117c478bd9Sstevel@tonic-gate case ND_SYSTEM: 8127c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, "%s: %s", 8137c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: system error"), 8147c478bd9Sstevel@tonic-gate strerror(errno)); 8157c478bd9Sstevel@tonic-gate break; 8167c478bd9Sstevel@tonic-gate default : 8177c478bd9Sstevel@tonic-gate (void) snprintf(str, NDERR_BUFSZ, "%s#%d", 8187c478bd9Sstevel@tonic-gate dgettext(__nsl_dom, "n2a: unknown error "), _nderror); 8197c478bd9Sstevel@tonic-gate break; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate return (str); 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * This is a routine that prints out strings related to the current 8267c478bd9Sstevel@tonic-gate * error in _nderror. Like perror() it takes a string to print with a 8277c478bd9Sstevel@tonic-gate * colon first. 8287c478bd9Sstevel@tonic-gate */ 8297c478bd9Sstevel@tonic-gate void 830*61961e0fSrobinson netdir_perror(char *s) 8317c478bd9Sstevel@tonic-gate { 8327c478bd9Sstevel@tonic-gate char *err; 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate err = netdir_sperror(); 8357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", s, err ? err : "n2a: error"); 8367c478bd9Sstevel@tonic-gate } 837