/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* netdir.c
*
* This is the library routines that do the name to address
* translation.
*/
#include "mt.h"
#include <stdio.h>
#include <errno.h>
#include <tiuser.h>
#include <netdir.h>
#include <netconfig.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <malloc.h>
#include <syslog.h>
#include <nss_netdir.h>
#include <netdb.h>
/* messaging stuff. */
extern const char __nsl_dom[];
extern char *dgettext(const char *, const char *);
struct translator {
};
/*
* xlate_lock protects xlate_list during updates only. The xlate_list linked
* list is pre-pended when new entries are added, so threads that are already
* using the list will continue correctly to the end of the list.
*/
static struct translator *load_xlate(char *);
/*
* This is the common data (global data) that is exported
* by public interfaces. It has been moved here from nd_comdata.c
* which no longer exists. This fixes the problem for applications
* that do not link directly with -lnsl but dlopen a shared object
* that has a NEEDED dependency on -lnsl and uses the netdir
* interface.
*/
int _nderror;
int *
__nderror(void)
{
int *ret;
if (thr_main())
return (&_nderror);
/* if thr_get_storage fails we return the address of _nderror */
}
/*
* Adds a translator library to the xlate_list, but first check to see if
* it's already on the list. Must be called while holding xlate_lock.
* We have to be careful for the case of the same library being loaded
* with different names (e.g., straddr.so and /usr/lib/straddr.so).
* We check for this case by looking at the gbn and name fields.
* If the gbn address is the same, but the names are different, then we
* have accidentally reloaded the library. We dlclose the new version,
* and then update 'translate' with the old versions of the symbols.
*/
void
{
struct translator *t;
for (t = xlate_list; t; t = t->next) {
return;
}
}
}
/*
* into a bunch of netbufs that should connect you to that particular
* service. RPC uses it to contact the binder service (rpcbind).
*
* this routine calls a common interface _get_hostserv_inetnetdir_byname
* if it's called with a netconfig with "inet" type transports and
* which indicates the use of the switch. For non-inet transports or
* inet transports with nametoaddr libs specified, it simply calls
* the SVr4-classic netdir_getbyname, which loops through the libs.
*
* After all, any problem can be solved by one more layer of abstraction..
*
* This routine when called with a netconfig with "inet6" type of transports
* returns pure IPv6 addresses only and if no IPv6 address is found it
* returns none - Bug Id. 4276329
*/
int
struct nd_addrlist **addrs)
{
if (tp == 0) {
return (_nderror);
}
(tp->nc_nlookups == 0)) {
/*
* In code path of case NETDIR_BY,
* it also calls DOOR_GETIPNODEBYNAME_R.
* So af_family and flags are set to
* get V4 addresses only.
*/
}
(tp->nc_nlookups == 0)) {
/* get both V4 & V6 addresses */
}
}
/*
* triples into a bunch of netbufs that should connect you to that particular
* service. RPC uses it to contact the binder service (rpcbind).
*
* It's either called by the real netdir_getbyname() interface above
* or by gethost/servbyname when nametoaddr libs are specified in
*/
int
struct nd_addrlist **addrs)
{
struct translator *t; /* pointer to translator list */
int i; /* counts the routines */
for (i = 0; i < tp->nc_nlookups; i++) {
for (t = xlate_list; t; t = t->next) {
if (nn) {
return (0);
}
if (_nderror < 0) {
return (_nderror);
}
break;
}
}
/* If we didn't find it try loading it */
if (!t) {
/* add it to the list */
(void) mutex_lock(&xlate_lock);
(void) mutex_unlock(&xlate_lock);
if (nn) {
return (0);
}
if (_nderror < 0) {
return (_nderror);
}
} else {
i--;
continue;
}
}
}
}
return (_nderror); /* No one works */
}
/*
* This routine is similar to the one above except that it tries to resolve
* the name by the address passed.
*/
int
{
if (tp == 0) {
return (_nderror);
}
(tp->nc_nlookups == 0)) {
}
(tp->nc_nlookups == 0)) {
}
}
/*
* This routine is similar to the one above except that it instructs the
* _get_hostserv_inetnetdir_byaddr not to do a service lookup.
*/
int
{
if (tp == 0) {
return (_nderror);
}
(tp->nc_nlookups == 0)) {
}
(tp->nc_nlookups == 0)) {
}
}
/*
* This routine is the svr4_classic routine for resolving a netbuf struct
*
* It's either called by the real netdir_getbyaddr() interface above
* or by gethost/servbyaddr when nametoaddr libs are specified in
*/
int
{
struct translator *t; /* pointer to translator list */
int i; /* counts the routines */
for (i = 0; i < tp->nc_nlookups; i++) {
for (t = xlate_list; t; t = t->next) {
if (hs) {
return (0);
}
if (_nderror < 0)
return (_nderror);
break;
}
}
/* If we didn't find it try loading it */
if (!t) {
/* add it to the list */
(void) mutex_lock(&xlate_lock);
(void) mutex_unlock(&xlate_lock);
if (hs) {
return (0);
}
if (_nderror < 0)
return (_nderror);
} else {
i--;
continue;
}
}
}
}
return (_nderror); /* No one works */
}
/*
* This is the library routine to do transport specific stuff.
* The code is same as the other similar routines except that it does
* not bother to try whole bunch of routines since if the first
* libray cannot resolve the option, then no one can.
*
* If it gets a netconfig structure for inet transports with nametoddr libs,
* it simply calls the inet-specific built in implementation.
*/
int
{
struct translator *t; /* pointer to translator list */
int i; /* counts the routines */
if (tp == 0) {
return (_nderror);
}
(tp->nc_nlookups == 0)) {
}
for (i = 0; i < tp->nc_nlookups; i++) {
for (t = xlate_list; t; t = t->next) {
}
/* If we didn't find it try loading it */
if (!t) {
/* add it to the list */
(void) mutex_lock(&xlate_lock);
(void) mutex_unlock(&xlate_lock);
}
i--;
continue;
}
}
}
return (_nderror); /* No one works */
}
/*
* This is the library routine for translating universal addresses to
* transport specific addresses. Again it uses the same code as above
* to search for the appropriate translation routine. Only it doesn't
* bother trying a whole bunch of routines since either the transport
* can translate it or it can't.
*/
struct netbuf *
{
struct translator *t; /* pointer to translator list */
struct netbuf *x; /* the answer we want */
int i; /* counts the routines */
if (tp == 0) {
return (0);
}
(tp->nc_nlookups == 0)) {
}
for (i = 0; i < tp->nc_nlookups; i++) {
for (t = xlate_list; t; t = t->next) {
if (x)
return (x);
if (_nderror < 0)
return (0);
}
}
/* If we didn't find it try loading it */
if (!t) {
/* add it to the list */
(void) mutex_lock(&xlate_lock);
(void) mutex_unlock(&xlate_lock);
if (x)
return (x);
if (_nderror < 0)
return (0);
} else {
i--;
continue;
}
}
}
}
return (0); /* No one works */
}
/*
* This is the library routine for translating transport specific
* addresses to universal addresses. Again it uses the same code as above
* to search for the appropriate translation routine. Only it doesn't
* bother trying a whole bunch of routines since either the transport
* can translate it or it can't.
*/
char *
{
struct translator *t; /* pointer to translator list */
char *x; /* the answer */
int i; /* counts the routines */
if (tp == 0) {
return (0);
}
(tp->nc_nlookups == 0)) {
}
for (i = 0; i < tp->nc_nlookups; i++) {
for (t = xlate_list; t; t = t->next) {
if (x)
return (x);
if (_nderror < 0)
return (0);
}
}
/* If we didn't find it try loading it */
if (!t) {
/* add it to the list */
(void) mutex_lock(&xlate_lock);
(void) mutex_unlock(&xlate_lock);
if (x)
return (x);
if (_nderror < 0)
return (0);
} else {
i--;
continue;
}
}
}
}
return (0); /* No one works */
}
/*
* This is the routine that frees the objects that these routines allocate.
*/
void
{
int i;
return;
switch (type) {
case ND_ADDR :
break;
case ND_ADDRLIST :
/*
* XXX: We do NOT try to free all individual netbuf->buf
* pointers. Free only the first one since they are allocated
* using one calloc in
* libnsl/nss/netdir_inet.c:order_haddrlist().
* This potentially causes memory leaks if a nametoaddr
* implementation -- from a third party -- has a different
* allocation scheme.
*/
break;
case ND_HOSTSERV :
break;
case ND_HOSTSERVLIST :
}
break;
default :
break;
}
}
/*
* load_xlate is a routine that will attempt to dynamically link in the
* file specified by the network configuration structure.
*/
static struct translator *
{
struct translator *t;
static struct xlate_list {
char *library;
(void) mutex_lock(&xlist_lock);
/*
* We maintain a list of libraries we have loaded. Loading a library
* twice is double-plus ungood!
*/
(void) mutex_unlock(&xlist_lock);
return (0);
}
}
}
t = malloc(sizeof (struct translator));
if (!t) {
(void) mutex_unlock(&xlist_lock);
return (0);
}
if (!t->tr_name) {
free(t);
(void) mutex_unlock(&xlist_lock);
return (NULL);
}
goto error;
}
/* Resolve the getbyname symbol */
"_netdir_getbyname");
if (!(t->gbn)) {
goto error;
}
/* resolve the getbyaddr symbol */
"_netdir_getbyaddr");
if (!(t->gba)) {
goto error;
}
/* resolve the taddr2uaddr symbol */
if (!(t->t2u)) {
goto error;
}
/* resolve the uaddr2taddr symbol */
if (!(t->u2t)) {
goto error;
}
/* resolve the netdir_options symbol */
if (!(t->opt)) {
goto error;
}
/*
* Add this library to the list of loaded libraries.
*/
goto error;
}
goto error;
}
(void) mutex_unlock(&xlist_lock);
return (t);
free(t);
(void) mutex_unlock(&xlist_lock);
return (NULL);
}
/*
* This is a routine that returns a string related to the current
* error in _nderror.
*/
char *
netdir_sperror(void)
{
char *str;
char *dlerrstr;
buf_main :
return (NULL);
switch (_nderror) {
case ND_NOMEM :
break;
case ND_OK :
break;
case ND_NOHOST :
break;
case ND_NOSERV :
break;
case ND_NOSYM :
"n2a: symbol missing in shared object"),
break;
case ND_OPEN :
break;
case ND_ACCESS :
"n2a: access denied for shared object"));
break;
case ND_UKNWN :
"n2a: attempt to free unknown object"));
break;
case ND_BADARG :
"n2a: bad arguments passed to routine"));
break;
case ND_NOCTRL:
break;
case ND_FAILCTRL:
break;
case ND_SYSTEM:
break;
default :
break;
}
return (str);
}
/*
* This is a routine that prints out strings related to the current
* error in _nderror. Like perror() it takes a string to print with a
* colon first.
*/
void
netdir_perror(char *s)
{
char *err;
err = netdir_sperror();
}