Home | History | Annotate | Line # | Download | only in rpc
rpc_generic.c revision 1.2.2.1
      1  1.2.2.1     tv /*	$NetBSD: rpc_generic.c,v 1.2.2.1 2000/11/17 15:38:04 tv Exp $	*/
      2      1.1   fvdl 
      3      1.1   fvdl /*
      4      1.1   fvdl  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
      5      1.1   fvdl  * unrestricted use provided that this legend is included on all tape
      6      1.1   fvdl  * media and as a part of the software program in whole or part.  Users
      7      1.1   fvdl  * may copy or modify Sun RPC without charge, but are not authorized
      8      1.1   fvdl  * to license or distribute it to anyone else except as part of a product or
      9      1.1   fvdl  * program developed by the user.
     10      1.1   fvdl  *
     11      1.1   fvdl  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     12      1.1   fvdl  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     13      1.1   fvdl  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     14      1.1   fvdl  *
     15      1.1   fvdl  * Sun RPC is provided with no support and without any obligation on the
     16      1.1   fvdl  * part of Sun Microsystems, Inc. to assist in its use, correction,
     17      1.1   fvdl  * modification or enhancement.
     18      1.1   fvdl  *
     19      1.1   fvdl  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     20      1.1   fvdl  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     21      1.1   fvdl  * OR ANY PART THEREOF.
     22      1.1   fvdl  *
     23      1.1   fvdl  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     24      1.1   fvdl  * or profits or other special, indirect and consequential damages, even if
     25      1.1   fvdl  * Sun has been advised of the possibility of such damages.
     26      1.1   fvdl  *
     27      1.1   fvdl  * Sun Microsystems, Inc.
     28      1.1   fvdl  * 2550 Garcia Avenue
     29      1.1   fvdl  * Mountain View, California  94043
     30      1.1   fvdl  */
     31      1.1   fvdl /*
     32      1.1   fvdl  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
     33      1.1   fvdl  */
     34      1.1   fvdl 
     35      1.1   fvdl /* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
     36      1.1   fvdl 
     37      1.1   fvdl /*
     38      1.1   fvdl  * rpc_generic.c, Miscl routines for RPC.
     39      1.1   fvdl  *
     40      1.1   fvdl  */
     41      1.1   fvdl 
     42      1.1   fvdl #include <sys/types.h>
     43      1.1   fvdl #include <sys/param.h>
     44      1.1   fvdl #include <sys/socket.h>
     45      1.1   fvdl #include <sys/un.h>
     46      1.1   fvdl #include <sys/resource.h>
     47      1.1   fvdl #include <netinet/in.h>
     48      1.1   fvdl #include <arpa/inet.h>
     49      1.1   fvdl #include <rpc/rpc.h>
     50      1.1   fvdl #include <ctype.h>
     51      1.1   fvdl #include <stdio.h>
     52      1.1   fvdl #include <netdb.h>
     53      1.1   fvdl #include <netconfig.h>
     54      1.1   fvdl #include <malloc.h>
     55      1.1   fvdl #include <string.h>
     56      1.2  assar #include <syslog.h>
     57      1.1   fvdl #include <rpc/nettype.h>
     58      1.1   fvdl #include "rpc_com.h"
     59      1.1   fvdl 
     60      1.1   fvdl struct handle {
     61      1.1   fvdl 	NCONF_HANDLE *nhandle;
     62      1.1   fvdl 	int nflag;		/* Whether NETPATH or NETCONFIG */
     63      1.1   fvdl 	int nettype;
     64      1.1   fvdl };
     65      1.1   fvdl 
     66      1.1   fvdl struct _rpcnettype {
     67      1.1   fvdl 	const char *name;
     68      1.1   fvdl 	const int type;
     69      1.1   fvdl } _rpctypelist[] = {
     70      1.1   fvdl 	{ "netpath", _RPC_NETPATH },
     71      1.1   fvdl 	{ "visible", _RPC_VISIBLE },
     72      1.1   fvdl 	{ "circuit_v", _RPC_CIRCUIT_V },
     73      1.1   fvdl 	{ "datagram_v", _RPC_DATAGRAM_V },
     74      1.1   fvdl 	{ "circuit_n", _RPC_CIRCUIT_N },
     75      1.1   fvdl 	{ "datagram_n", _RPC_DATAGRAM_N },
     76      1.1   fvdl 	{ "tcp", _RPC_TCP },
     77      1.1   fvdl 	{ "udp", _RPC_UDP },
     78      1.1   fvdl 	{ 0, _RPC_NONE }
     79      1.1   fvdl };
     80      1.1   fvdl 
     81      1.1   fvdl struct netid_af {
     82      1.1   fvdl 	const char	*netid;
     83      1.1   fvdl 	int		af;
     84      1.1   fvdl 	int		protocol;
     85      1.1   fvdl };
     86      1.1   fvdl 
     87      1.1   fvdl static struct netid_af na_cvt[] = {
     88      1.1   fvdl 	{ "udp",  AF_INET,  IPPROTO_UDP },
     89      1.1   fvdl 	{ "tcp",  AF_INET,  IPPROTO_TCP },
     90      1.1   fvdl #ifdef INET6
     91      1.1   fvdl 	{ "udp6", AF_INET6, IPPROTO_UDP },
     92      1.1   fvdl 	{ "tcp6", AF_INET6, IPPROTO_TCP },
     93      1.1   fvdl #endif
     94      1.1   fvdl 	{ "local", AF_LOCAL, 0 }
     95      1.1   fvdl };
     96      1.1   fvdl 
     97      1.1   fvdl static char *strlocase __P((char *));
     98      1.1   fvdl static int getnettype __P((char *));
     99      1.1   fvdl 
    100      1.1   fvdl /*
    101      1.1   fvdl  * Cache the result of getrlimit(), so we don't have to do an
    102      1.1   fvdl  * expensive call every time.
    103      1.1   fvdl  */
    104      1.1   fvdl int
    105      1.1   fvdl __rpc_dtbsize()
    106      1.1   fvdl {
    107      1.1   fvdl 	static int tbsize;
    108      1.1   fvdl 	struct rlimit rl;
    109      1.1   fvdl 
    110      1.1   fvdl 	if (tbsize) {
    111      1.1   fvdl 		return (tbsize);
    112      1.1   fvdl 	}
    113      1.1   fvdl 	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
    114      1.1   fvdl 		return (tbsize = rl.rlim_max);
    115      1.1   fvdl 	}
    116      1.1   fvdl 	/*
    117      1.1   fvdl 	 * Something wrong.  I'll try to save face by returning a
    118      1.1   fvdl 	 * pessimistic number.
    119      1.1   fvdl 	 */
    120      1.1   fvdl 	return (32);
    121      1.1   fvdl }
    122      1.1   fvdl 
    123      1.1   fvdl 
    124      1.1   fvdl /*
    125      1.1   fvdl  * Find the appropriate buffer size
    126      1.1   fvdl  */
    127      1.1   fvdl u_int
    128      1.1   fvdl __rpc_get_t_size(af, proto, size)
    129      1.1   fvdl 	int af, proto;
    130      1.1   fvdl 	int size;	/* Size requested */
    131      1.1   fvdl {
    132      1.1   fvdl 	int maxsize;
    133      1.1   fvdl 
    134      1.1   fvdl 	switch (proto) {
    135      1.1   fvdl 	case IPPROTO_TCP:
    136      1.1   fvdl 		maxsize = 65536;	/* XXX */
    137      1.1   fvdl 		break;
    138      1.1   fvdl 	case IPPROTO_UDP:
    139  1.2.2.1     tv 		maxsize = 65508;	/* XXX */
    140      1.1   fvdl 		break;
    141      1.1   fvdl 	default:
    142      1.1   fvdl 		maxsize = RPC_MAXDATASIZE;
    143      1.1   fvdl 		break;
    144      1.1   fvdl 	}
    145      1.1   fvdl 	if (size == 0)
    146      1.1   fvdl 		return maxsize;
    147      1.1   fvdl 
    148      1.1   fvdl 	/* Check whether the value is within the upper max limit */
    149      1.1   fvdl 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
    150      1.1   fvdl }
    151      1.1   fvdl 
    152      1.1   fvdl /*
    153      1.1   fvdl  * Find the appropriate address buffer size
    154      1.1   fvdl  */
    155      1.1   fvdl u_int
    156      1.1   fvdl __rpc_get_a_size(af)
    157      1.1   fvdl 	int af;
    158      1.1   fvdl {
    159      1.1   fvdl 	switch (af) {
    160      1.1   fvdl 	case AF_INET:
    161      1.1   fvdl 		return sizeof (struct sockaddr_in);
    162      1.1   fvdl #ifdef INET6
    163      1.1   fvdl 	case AF_INET6:
    164      1.1   fvdl 		return sizeof (struct sockaddr_in6);
    165      1.1   fvdl #endif
    166      1.1   fvdl 	case AF_LOCAL:
    167      1.1   fvdl 		return sizeof (struct sockaddr_un);
    168      1.1   fvdl 	default:
    169      1.1   fvdl 		break;
    170      1.1   fvdl 	}
    171      1.1   fvdl 	return ((u_int)RPC_MAXADDRSIZE);
    172      1.1   fvdl }
    173      1.1   fvdl 
    174      1.1   fvdl static char *
    175      1.1   fvdl strlocase(p)
    176      1.1   fvdl 	char *p;
    177      1.1   fvdl {
    178      1.1   fvdl 	char *t = p;
    179      1.1   fvdl 
    180      1.1   fvdl 	for (; *p; p++)
    181      1.1   fvdl 		if (isupper(*p))
    182      1.1   fvdl 			*p = tolower(*p);
    183      1.1   fvdl 	return (t);
    184      1.1   fvdl }
    185      1.1   fvdl 
    186      1.1   fvdl /*
    187      1.1   fvdl  * Returns the type of the network as defined in <rpc/nettype.h>
    188      1.1   fvdl  * If nettype is NULL, it defaults to NETPATH.
    189      1.1   fvdl  */
    190      1.1   fvdl static int
    191      1.1   fvdl getnettype(nettype)
    192      1.1   fvdl 	char *nettype;
    193      1.1   fvdl {
    194      1.1   fvdl 	int i;
    195      1.1   fvdl 
    196      1.1   fvdl 	if ((nettype == NULL) || (nettype[0] == NULL)) {
    197      1.1   fvdl 		return (_RPC_NETPATH);	/* Default */
    198      1.1   fvdl 	}
    199      1.1   fvdl 
    200      1.1   fvdl 	nettype = strlocase(nettype);
    201      1.1   fvdl 	for (i = 0; _rpctypelist[i].name; i++)
    202      1.1   fvdl 		if (strcmp(nettype, _rpctypelist[i].name) == 0) {
    203      1.1   fvdl 			return (_rpctypelist[i].type);
    204      1.1   fvdl 		}
    205      1.1   fvdl 	return (_rpctypelist[i].type);
    206      1.1   fvdl }
    207      1.1   fvdl 
    208      1.1   fvdl /*
    209      1.1   fvdl  * For the given nettype (tcp or udp only), return the first structure found.
    210      1.1   fvdl  * This should be freed by calling freenetconfigent()
    211      1.1   fvdl  */
    212      1.1   fvdl struct netconfig *
    213      1.1   fvdl __rpc_getconfip(nettype)
    214      1.1   fvdl 	char *nettype;
    215      1.1   fvdl {
    216      1.1   fvdl 	char *netid;
    217      1.1   fvdl 	char *netid_tcp = (char *) NULL;
    218      1.1   fvdl 	char *netid_udp = (char *) NULL;
    219      1.1   fvdl 	static char *netid_tcp_main;
    220      1.1   fvdl 	static char *netid_udp_main;
    221      1.1   fvdl 	struct netconfig *dummy;
    222      1.1   fvdl #ifdef __REENT
    223      1.1   fvdl 	int main_thread;
    224      1.1   fvdl 	static thread_key_t tcp_key, udp_key;
    225      1.1   fvdl 	extern mutex_t tsd_lock;
    226      1.1   fvdl 
    227      1.1   fvdl 	if ((main_thread = _thr_main())) {
    228      1.1   fvdl 		netid_udp = netid_udp_main;
    229      1.1   fvdl 		netid_tcp = netid_tcp_main;
    230      1.1   fvdl 	} else {
    231      1.1   fvdl 		if (tcp_key == 0) {
    232      1.1   fvdl 			mutex_lock(&tsd_lock);
    233      1.1   fvdl 			if (tcp_key == 0)
    234      1.1   fvdl 				thr_keycreate(&tcp_key, free);
    235      1.1   fvdl 			mutex_unlock(&tsd_lock);
    236      1.1   fvdl 		}
    237      1.1   fvdl 		thr_getspecific(tcp_key, (void **) &netid_tcp);
    238      1.1   fvdl 		if (udp_key == 0) {
    239      1.1   fvdl 			mutex_lock(&tsd_lock);
    240      1.1   fvdl 			if (udp_key == 0)
    241      1.1   fvdl 				thr_keycreate(&udp_key, free);
    242      1.1   fvdl 			mutex_unlock(&tsd_lock);
    243      1.1   fvdl 		}
    244      1.1   fvdl 		thr_getspecific(udp_key, (void **) &netid_udp);
    245      1.1   fvdl 	}
    246      1.1   fvdl #else
    247      1.1   fvdl 	netid_udp = netid_udp_main;
    248      1.1   fvdl 	netid_tcp = netid_tcp_main;
    249      1.1   fvdl #endif
    250      1.1   fvdl 	if (!netid_udp && !netid_tcp) {
    251      1.1   fvdl 		struct netconfig *nconf;
    252      1.1   fvdl 		void *confighandle;
    253      1.1   fvdl 
    254      1.1   fvdl 		if (!(confighandle = setnetconfig())) {
    255      1.2  assar 			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
    256      1.1   fvdl 			return (NULL);
    257      1.1   fvdl 		}
    258      1.1   fvdl 		while ((nconf = getnetconfig(confighandle))) {
    259      1.1   fvdl 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
    260      1.1   fvdl 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
    261      1.1   fvdl 					netid_tcp = strdup(nconf->nc_netid);
    262      1.1   fvdl #ifdef __REENT
    263      1.1   fvdl 					if (main_thread)
    264      1.1   fvdl 						netid_tcp_main = netid_tcp;
    265      1.1   fvdl 					else
    266      1.1   fvdl 						thr_setspecific(tcp_key,
    267      1.1   fvdl 							(void *) netid_tcp);
    268      1.1   fvdl #else
    269      1.1   fvdl 					netid_tcp_main = netid_tcp;
    270      1.1   fvdl #endif
    271      1.1   fvdl 				} else
    272      1.1   fvdl 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
    273      1.1   fvdl 					netid_udp = strdup(nconf->nc_netid);
    274      1.1   fvdl #ifdef __REENT
    275      1.1   fvdl 					if (main_thread)
    276      1.1   fvdl 						netid_udp_main = netid_udp;
    277      1.1   fvdl 					else
    278      1.1   fvdl 						thr_setspecific(udp_key,
    279      1.1   fvdl 							(void *) netid_udp);
    280      1.1   fvdl #else
    281      1.1   fvdl 					netid_udp_main = netid_udp;
    282      1.1   fvdl #endif
    283      1.1   fvdl 				}
    284      1.1   fvdl 			}
    285      1.1   fvdl 		}
    286      1.1   fvdl 		endnetconfig(confighandle);
    287      1.1   fvdl 	}
    288      1.1   fvdl 	if (strcmp(nettype, "udp") == 0)
    289      1.1   fvdl 		netid = netid_udp;
    290      1.1   fvdl 	else if (strcmp(nettype, "tcp") == 0)
    291      1.1   fvdl 		netid = netid_tcp;
    292      1.1   fvdl 	else {
    293      1.1   fvdl 		return ((struct netconfig *)NULL);
    294      1.1   fvdl 	}
    295      1.1   fvdl 	if ((netid == NULL) || (netid[0] == NULL)) {
    296      1.1   fvdl 		return ((struct netconfig *)NULL);
    297      1.1   fvdl 	}
    298      1.1   fvdl 	dummy = getnetconfigent(netid);
    299      1.1   fvdl 	return (dummy);
    300      1.1   fvdl }
    301      1.1   fvdl 
    302      1.1   fvdl /*
    303      1.1   fvdl  * Returns the type of the nettype, which should then be used with
    304      1.1   fvdl  * __rpc_getconf().
    305      1.1   fvdl  */
    306      1.1   fvdl void *
    307      1.1   fvdl __rpc_setconf(nettype)
    308      1.1   fvdl 	char *nettype;
    309      1.1   fvdl {
    310      1.1   fvdl 	struct handle *handle;
    311      1.1   fvdl 
    312      1.1   fvdl 	handle = (struct handle *) malloc(sizeof (struct handle));
    313      1.1   fvdl 	if (handle == NULL) {
    314      1.1   fvdl 		return (NULL);
    315      1.1   fvdl 	}
    316      1.1   fvdl 	switch (handle->nettype = getnettype(nettype)) {
    317      1.1   fvdl 	case _RPC_NETPATH:
    318      1.1   fvdl 	case _RPC_CIRCUIT_N:
    319      1.1   fvdl 	case _RPC_DATAGRAM_N:
    320      1.1   fvdl 		if (!(handle->nhandle = setnetpath())) {
    321      1.1   fvdl 			free(handle);
    322      1.1   fvdl 			return (NULL);
    323      1.1   fvdl 		}
    324      1.1   fvdl 		handle->nflag = TRUE;
    325      1.1   fvdl 		break;
    326      1.1   fvdl 	case _RPC_VISIBLE:
    327      1.1   fvdl 	case _RPC_CIRCUIT_V:
    328      1.1   fvdl 	case _RPC_DATAGRAM_V:
    329      1.1   fvdl 	case _RPC_TCP:
    330      1.1   fvdl 	case _RPC_UDP:
    331      1.1   fvdl 		if (!(handle->nhandle = setnetconfig())) {
    332      1.2  assar 		        syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
    333      1.1   fvdl 			free(handle);
    334      1.1   fvdl 			return (NULL);
    335      1.1   fvdl 		}
    336      1.1   fvdl 		handle->nflag = FALSE;
    337      1.1   fvdl 		break;
    338      1.1   fvdl 	default:
    339      1.1   fvdl 		return (NULL);
    340      1.1   fvdl 	}
    341      1.1   fvdl 
    342      1.1   fvdl 	return (handle);
    343      1.1   fvdl }
    344      1.1   fvdl 
    345      1.1   fvdl /*
    346      1.1   fvdl  * Returns the next netconfig struct for the given "net" type.
    347      1.1   fvdl  * __rpc_setconf() should have been called previously.
    348      1.1   fvdl  */
    349      1.1   fvdl struct netconfig *
    350      1.1   fvdl __rpc_getconf(vhandle)
    351      1.1   fvdl 	void *vhandle;
    352      1.1   fvdl {
    353      1.1   fvdl 	struct handle *handle;
    354      1.1   fvdl 	struct netconfig *nconf;
    355      1.1   fvdl 
    356      1.1   fvdl 	handle = (struct handle *)vhandle;
    357      1.1   fvdl 	if (handle == NULL) {
    358      1.1   fvdl 		return (NULL);
    359      1.1   fvdl 	}
    360      1.1   fvdl 	while (1) {
    361      1.1   fvdl 		if (handle->nflag)
    362      1.1   fvdl 			nconf = getnetpath(handle->nhandle);
    363      1.1   fvdl 		else
    364      1.1   fvdl 			nconf = getnetconfig(handle->nhandle);
    365      1.1   fvdl 		if (nconf == (struct netconfig *)NULL)
    366      1.1   fvdl 			break;
    367      1.1   fvdl 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
    368      1.1   fvdl 			(nconf->nc_semantics != NC_TPI_COTS) &&
    369      1.1   fvdl 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
    370      1.1   fvdl 			continue;
    371      1.1   fvdl 		switch (handle->nettype) {
    372      1.1   fvdl 		case _RPC_VISIBLE:
    373      1.1   fvdl 			if (!(nconf->nc_flag & NC_VISIBLE))
    374      1.1   fvdl 				continue;
    375      1.1   fvdl 			/* FALLTHROUGH */
    376      1.1   fvdl 		case _RPC_NETPATH:	/* Be happy */
    377      1.1   fvdl 			break;
    378      1.1   fvdl 		case _RPC_CIRCUIT_V:
    379      1.1   fvdl 			if (!(nconf->nc_flag & NC_VISIBLE))
    380      1.1   fvdl 				continue;
    381      1.1   fvdl 			/* FALLTHROUGH */
    382      1.1   fvdl 		case _RPC_CIRCUIT_N:
    383      1.1   fvdl 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
    384      1.1   fvdl 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
    385      1.1   fvdl 				continue;
    386      1.1   fvdl 			break;
    387      1.1   fvdl 		case _RPC_DATAGRAM_V:
    388      1.1   fvdl 			if (!(nconf->nc_flag & NC_VISIBLE))
    389      1.1   fvdl 				continue;
    390      1.1   fvdl 			/* FALLTHROUGH */
    391      1.1   fvdl 		case _RPC_DATAGRAM_N:
    392      1.1   fvdl 			if (nconf->nc_semantics != NC_TPI_CLTS)
    393      1.1   fvdl 				continue;
    394      1.1   fvdl 			break;
    395      1.1   fvdl 		case _RPC_TCP:
    396      1.1   fvdl 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
    397      1.1   fvdl 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
    398      1.1   fvdl 				(strcmp(nconf->nc_protofmly, NC_INET)
    399      1.1   fvdl #ifdef INET6
    400      1.1   fvdl 				 && strcmp(nconf->nc_protofmly, NC_INET6))
    401      1.1   fvdl #else
    402      1.1   fvdl 				)
    403      1.1   fvdl #endif
    404      1.1   fvdl 				||
    405      1.1   fvdl 				strcmp(nconf->nc_proto, NC_TCP))
    406      1.1   fvdl 				continue;
    407      1.1   fvdl 			break;
    408      1.1   fvdl 		case _RPC_UDP:
    409      1.1   fvdl 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
    410      1.1   fvdl 				(strcmp(nconf->nc_protofmly, NC_INET)
    411      1.1   fvdl #ifdef INET6
    412      1.1   fvdl 				&& strcmp(nconf->nc_protofmly, NC_INET6))
    413      1.1   fvdl #else
    414      1.1   fvdl 				)
    415      1.1   fvdl #endif
    416      1.1   fvdl 				||
    417      1.1   fvdl 				strcmp(nconf->nc_proto, NC_UDP))
    418      1.1   fvdl 				continue;
    419      1.1   fvdl 			break;
    420      1.1   fvdl 		}
    421      1.1   fvdl 		break;
    422      1.1   fvdl 	}
    423      1.1   fvdl 	return (nconf);
    424      1.1   fvdl }
    425      1.1   fvdl 
    426      1.1   fvdl void
    427      1.1   fvdl __rpc_endconf(vhandle)
    428      1.1   fvdl 	void * vhandle;
    429      1.1   fvdl {
    430      1.1   fvdl 	struct handle *handle;
    431      1.1   fvdl 
    432      1.1   fvdl 	handle = (struct handle *) vhandle;
    433      1.1   fvdl 	if (handle == NULL) {
    434      1.1   fvdl 		return;
    435      1.1   fvdl 	}
    436      1.1   fvdl 	if (handle->nflag) {
    437      1.1   fvdl 		endnetpath(handle->nhandle);
    438      1.1   fvdl 	} else {
    439      1.1   fvdl 		endnetconfig(handle->nhandle);
    440      1.1   fvdl 	}
    441      1.1   fvdl 	free(handle);
    442      1.1   fvdl }
    443      1.1   fvdl 
    444      1.1   fvdl /*
    445      1.1   fvdl  * Used to ping the NULL procedure for clnt handle.
    446      1.1   fvdl  * Returns NULL if fails, else a non-NULL pointer.
    447      1.1   fvdl  */
    448      1.1   fvdl void *
    449      1.1   fvdl rpc_nullproc(clnt)
    450      1.1   fvdl 	CLIENT *clnt;
    451      1.1   fvdl {
    452      1.1   fvdl 	struct timeval TIMEOUT = {25, 0};
    453      1.1   fvdl 
    454      1.1   fvdl 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, (char *)NULL,
    455      1.1   fvdl 		(xdrproc_t) xdr_void, (char *)NULL, TIMEOUT) != RPC_SUCCESS) {
    456      1.1   fvdl 		return ((void *) NULL);
    457      1.1   fvdl 	}
    458      1.1   fvdl 	return ((void *) clnt);
    459      1.1   fvdl }
    460      1.1   fvdl 
    461      1.1   fvdl /*
    462      1.1   fvdl  * Try all possible transports until
    463      1.1   fvdl  * one succeeds in finding the netconf for the given fd.
    464      1.1   fvdl  */
    465      1.1   fvdl struct netconfig *
    466      1.1   fvdl __rpcgettp(fd)
    467      1.1   fvdl 	int fd;
    468      1.1   fvdl {
    469      1.1   fvdl 	const char *netid;
    470      1.1   fvdl 	struct __rpc_sockinfo si;
    471      1.1   fvdl 
    472      1.1   fvdl 	if (!__rpc_fd2sockinfo(fd, &si))
    473      1.1   fvdl 		return NULL;
    474      1.1   fvdl 
    475      1.1   fvdl 	if (!__rpc_sockinfo2netid(&si, &netid))
    476      1.1   fvdl 		return NULL;
    477      1.1   fvdl 
    478      1.1   fvdl 	return getnetconfigent((char *)netid);
    479      1.1   fvdl }
    480      1.1   fvdl 
    481      1.1   fvdl int
    482      1.1   fvdl __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
    483      1.1   fvdl {
    484      1.1   fvdl 	socklen_t len;
    485      1.1   fvdl 	int type, proto;
    486      1.1   fvdl 	struct sockaddr_storage ss;
    487      1.1   fvdl 
    488      1.1   fvdl 	len = sizeof ss;
    489      1.1   fvdl 	if (getsockname(fd, (struct sockaddr *)&ss, &len) < 0)
    490      1.1   fvdl 		return 0;
    491      1.1   fvdl 	sip->si_alen = len;
    492      1.1   fvdl 
    493      1.1   fvdl 	len = sizeof type;
    494      1.1   fvdl 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
    495      1.1   fvdl 		return 0;
    496      1.1   fvdl 
    497      1.1   fvdl 	/* XXX */
    498      1.1   fvdl 	if (ss.ss_family != AF_LOCAL) {
    499      1.1   fvdl 		if (type == SOCK_STREAM)
    500      1.1   fvdl 			proto = IPPROTO_TCP;
    501      1.1   fvdl 		else if (type == SOCK_DGRAM)
    502      1.1   fvdl 			proto = IPPROTO_UDP;
    503      1.1   fvdl 		else
    504      1.1   fvdl 			return 0;
    505      1.1   fvdl 	} else
    506      1.1   fvdl 		proto = 0;
    507      1.1   fvdl 
    508      1.1   fvdl 	sip->si_af = ss.ss_family;
    509      1.1   fvdl 	sip->si_proto = proto;
    510      1.1   fvdl 	sip->si_socktype = type;
    511      1.1   fvdl 
    512      1.1   fvdl 	return 1;
    513      1.1   fvdl }
    514      1.1   fvdl 
    515      1.1   fvdl /*
    516      1.1   fvdl  * Linear search, but the number of entries is small.
    517      1.1   fvdl  */
    518      1.1   fvdl int
    519      1.1   fvdl __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
    520      1.1   fvdl {
    521      1.1   fvdl 	int i;
    522      1.1   fvdl 
    523      1.1   fvdl 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
    524      1.1   fvdl 		if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
    525      1.1   fvdl 			sip->si_af = na_cvt[i].af;
    526      1.1   fvdl 			sip->si_proto = na_cvt[i].protocol;
    527      1.1   fvdl 			sip->si_socktype =
    528      1.1   fvdl 			    __rpc_seman2socktype(nconf->nc_semantics);
    529      1.1   fvdl 			if (sip->si_socktype == -1)
    530      1.1   fvdl 				return 0;
    531      1.1   fvdl 			sip->si_alen = __rpc_get_a_size(sip->si_af);
    532      1.1   fvdl 			return 1;
    533      1.1   fvdl 		}
    534      1.1   fvdl 
    535      1.1   fvdl 	return 0;
    536      1.1   fvdl }
    537      1.1   fvdl 
    538      1.1   fvdl int
    539      1.1   fvdl __rpc_nconf2fd(const struct netconfig *nconf)
    540      1.1   fvdl {
    541      1.1   fvdl 	struct __rpc_sockinfo si;
    542      1.1   fvdl 
    543      1.1   fvdl 	if (!__rpc_nconf2sockinfo(nconf, &si))
    544      1.1   fvdl 		return 0;
    545      1.1   fvdl 
    546      1.1   fvdl 	return socket(si.si_af, si.si_socktype, si.si_proto);
    547      1.1   fvdl }
    548      1.1   fvdl 
    549      1.1   fvdl int
    550      1.1   fvdl __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
    551      1.1   fvdl {
    552      1.1   fvdl 	int i;
    553      1.1   fvdl 
    554      1.1   fvdl 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
    555      1.1   fvdl 		if (na_cvt[i].af == sip->si_af &&
    556      1.1   fvdl 		    na_cvt[i].protocol == sip->si_proto) {
    557      1.1   fvdl 			if (netid)
    558      1.1   fvdl 				*netid = na_cvt[i].netid;
    559      1.1   fvdl 			return 1;
    560      1.1   fvdl 		}
    561      1.1   fvdl 
    562      1.1   fvdl 	return 0;
    563      1.1   fvdl }
    564      1.1   fvdl 
    565      1.1   fvdl char *
    566      1.1   fvdl taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
    567      1.1   fvdl {
    568      1.1   fvdl 	struct __rpc_sockinfo si;
    569      1.1   fvdl 
    570      1.1   fvdl 	if (!__rpc_nconf2sockinfo(nconf, &si))
    571      1.1   fvdl 		return NULL;
    572      1.1   fvdl 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
    573      1.1   fvdl }
    574      1.1   fvdl 
    575      1.1   fvdl struct netbuf *
    576      1.1   fvdl uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
    577      1.1   fvdl {
    578      1.1   fvdl 	struct __rpc_sockinfo si;
    579      1.1   fvdl 
    580      1.1   fvdl 	if (!__rpc_nconf2sockinfo(nconf, &si))
    581      1.1   fvdl 		return NULL;
    582      1.1   fvdl 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
    583      1.1   fvdl }
    584      1.1   fvdl 
    585      1.1   fvdl char *
    586      1.1   fvdl __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
    587      1.1   fvdl {
    588      1.1   fvdl 	char *ret;
    589      1.1   fvdl 	struct sockaddr_in *sin;
    590      1.1   fvdl 	struct sockaddr_un *sun;
    591      1.1   fvdl 	char namebuf[INET_ADDRSTRLEN];
    592      1.1   fvdl #ifdef INET6
    593      1.1   fvdl 	struct sockaddr_in6 *sin6;
    594      1.1   fvdl 	char namebuf6[INET6_ADDRSTRLEN];
    595      1.1   fvdl #endif
    596      1.1   fvdl 	u_int16_t port;
    597      1.1   fvdl 
    598      1.1   fvdl 	switch (af) {
    599      1.1   fvdl 	case AF_INET:
    600      1.1   fvdl 		sin = nbuf->buf;
    601      1.1   fvdl 		if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
    602      1.1   fvdl 		    == NULL)
    603      1.1   fvdl 			return NULL;
    604      1.1   fvdl 		port = ntohs(sin->sin_port);
    605      1.1   fvdl 		if (asprintf(&ret, "%s.%u.%u", namebuf, port >> 8, port & 0xff)
    606      1.1   fvdl 		    < 0)
    607      1.1   fvdl 			return NULL;
    608      1.1   fvdl 		break;
    609      1.1   fvdl #ifdef INET6
    610      1.1   fvdl 	case AF_INET6:
    611      1.1   fvdl 		sin6 = nbuf->buf;
    612      1.1   fvdl 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
    613      1.1   fvdl 		    == NULL)
    614      1.1   fvdl 			return NULL;
    615      1.1   fvdl 		port = ntohs(sin6->sin6_port);
    616      1.1   fvdl 		if (asprintf(&ret, "%s.%u.%u", namebuf6, port >> 8, port & 0xff)
    617      1.1   fvdl 		    < 0)
    618      1.1   fvdl 			return NULL;
    619      1.1   fvdl 		break;
    620      1.1   fvdl #endif
    621      1.1   fvdl 	case AF_LOCAL:
    622      1.1   fvdl 		sun = nbuf->buf;
    623      1.1   fvdl 		sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
    624      1.1   fvdl 		ret = strdup(sun->sun_path);
    625      1.1   fvdl 		break;
    626      1.1   fvdl 	default:
    627      1.1   fvdl 		return NULL;
    628      1.1   fvdl 	}
    629      1.1   fvdl 
    630      1.1   fvdl 	return ret;
    631      1.1   fvdl }
    632      1.1   fvdl 
    633      1.1   fvdl struct netbuf *
    634      1.1   fvdl __rpc_uaddr2taddr_af(int af, const char *uaddr)
    635      1.1   fvdl {
    636      1.1   fvdl 	struct netbuf *ret = NULL;
    637      1.1   fvdl 	char *addrstr, *p;
    638      1.1   fvdl 	unsigned port, portlo, porthi;
    639      1.1   fvdl 	struct sockaddr_in *sin;
    640      1.1   fvdl #ifdef INET6
    641      1.1   fvdl 	struct sockaddr_in6 *sin6;
    642      1.1   fvdl #endif
    643      1.1   fvdl 	struct sockaddr_un *sun;
    644      1.1   fvdl 
    645      1.1   fvdl 	addrstr = strdup(uaddr);
    646      1.1   fvdl 	if (addrstr == NULL)
    647      1.1   fvdl 		return NULL;
    648      1.1   fvdl 
    649      1.1   fvdl 	/*
    650      1.1   fvdl 	 * AF_LOCAL addresses are expected to be absolute
    651      1.1   fvdl 	 * pathnames, anything else will be AF_INET or AF_INET6.
    652      1.1   fvdl 	 */
    653      1.1   fvdl 	if (*addrstr != '/') {
    654      1.1   fvdl 		p = strrchr(addrstr, '.');
    655      1.1   fvdl 		if (p == NULL)
    656      1.1   fvdl 			goto out;
    657      1.1   fvdl 		portlo = (unsigned)atoi(p + 1);
    658      1.1   fvdl 		*p = '\0';
    659      1.1   fvdl 
    660      1.1   fvdl 		p = strrchr(addrstr, '.');
    661      1.1   fvdl 		if (p == NULL)
    662      1.1   fvdl 			goto out;
    663      1.1   fvdl 		porthi = (unsigned)atoi(p + 1);
    664      1.1   fvdl 		*p = '\0';
    665      1.1   fvdl 		port = (porthi << 8) | portlo;
    666      1.1   fvdl 	}
    667      1.1   fvdl 
    668      1.1   fvdl 	ret = (struct netbuf *)malloc(sizeof *ret);
    669      1.1   fvdl 
    670      1.1   fvdl 	switch (af) {
    671      1.1   fvdl 	case AF_INET:
    672      1.1   fvdl 		sin = (struct sockaddr_in *)malloc(sizeof *sin);
    673      1.1   fvdl 		if (sin == NULL)
    674      1.1   fvdl 			goto out;
    675      1.1   fvdl 		memset(sin, 0, sizeof *sin);
    676      1.1   fvdl 		sin->sin_family = AF_INET;
    677      1.1   fvdl 		sin->sin_port = htons(port);
    678      1.1   fvdl 		if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
    679      1.1   fvdl 			free(sin);
    680      1.1   fvdl 			free(ret);
    681      1.1   fvdl 			ret = NULL;
    682      1.1   fvdl 			goto out;
    683      1.1   fvdl 		}
    684      1.1   fvdl 		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
    685      1.1   fvdl 		ret->buf = sin;
    686      1.1   fvdl 		break;
    687      1.1   fvdl #ifdef INET6
    688      1.1   fvdl 	case AF_INET6:
    689      1.1   fvdl 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
    690      1.1   fvdl 		if (sin6 == NULL)
    691      1.1   fvdl 			goto out;
    692      1.1   fvdl 		memset(sin6, 0, sizeof *sin6);
    693      1.1   fvdl 		sin6->sin6_family = AF_INET6;
    694      1.1   fvdl 		sin6->sin6_port = htons(port);
    695      1.1   fvdl 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
    696      1.1   fvdl 			free(sin);
    697      1.1   fvdl 			free(ret);
    698      1.1   fvdl 			ret = NULL;
    699      1.1   fvdl 			goto out;
    700      1.1   fvdl 		}
    701      1.1   fvdl 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
    702      1.1   fvdl 		ret->buf = sin6;
    703      1.1   fvdl 		break;
    704      1.1   fvdl #endif
    705      1.1   fvdl 	case AF_LOCAL:
    706      1.1   fvdl 		sun = (struct sockaddr_un *)malloc(sizeof *sun);
    707      1.1   fvdl 		if (sun == NULL)
    708      1.1   fvdl 			goto out;
    709      1.1   fvdl 		memset(sun, 0, sizeof *sun);
    710      1.1   fvdl 		sun->sun_family = AF_LOCAL;
    711      1.1   fvdl 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
    712      1.1   fvdl 	default:
    713      1.1   fvdl 		break;
    714      1.1   fvdl 	}
    715      1.1   fvdl out:
    716      1.1   fvdl 	free(addrstr);
    717      1.1   fvdl 	return ret;
    718      1.1   fvdl }
    719      1.1   fvdl 
    720      1.1   fvdl int
    721      1.1   fvdl __rpc_seman2socktype(int semantics)
    722      1.1   fvdl {
    723      1.1   fvdl 	switch (semantics) {
    724      1.1   fvdl 	case NC_TPI_CLTS:
    725      1.1   fvdl 		return SOCK_DGRAM;
    726      1.1   fvdl 	case NC_TPI_COTS_ORD:
    727      1.1   fvdl 		return SOCK_STREAM;
    728      1.1   fvdl 	case NC_TPI_RAW:
    729      1.1   fvdl 		return SOCK_RAW;
    730      1.1   fvdl 	default:
    731      1.1   fvdl 		break;
    732      1.1   fvdl 	}
    733      1.1   fvdl 
    734      1.1   fvdl 	return -1;
    735      1.1   fvdl }
    736      1.1   fvdl 
    737      1.1   fvdl int
    738      1.1   fvdl __rpc_socktype2seman(int socktype)
    739      1.1   fvdl {
    740      1.1   fvdl 	switch (socktype) {
    741      1.1   fvdl 	case SOCK_DGRAM:
    742      1.1   fvdl 		return NC_TPI_CLTS;
    743      1.1   fvdl 	case SOCK_STREAM:
    744      1.1   fvdl 		return NC_TPI_COTS_ORD;
    745      1.1   fvdl 	case SOCK_RAW:
    746      1.1   fvdl 		return NC_TPI_RAW;
    747      1.1   fvdl 	default:
    748      1.1   fvdl 		break;
    749      1.1   fvdl 	}
    750      1.1   fvdl 
    751      1.1   fvdl 	return -1;
    752      1.1   fvdl }
    753      1.1   fvdl 
    754      1.1   fvdl /*
    755      1.1   fvdl  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
    756      1.1   fvdl  * Here, we compare the original server address to that of the RPC
    757      1.1   fvdl  * service we just received back from a call to rpcbind on the remote
    758      1.1   fvdl  * machine. If they are both "link local" or "site local", copy
    759      1.1   fvdl  * the scope id of the server address over to the service address.
    760      1.1   fvdl  */
    761      1.1   fvdl int
    762      1.1   fvdl __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
    763      1.1   fvdl {
    764      1.1   fvdl #ifdef INET6
    765      1.1   fvdl 	struct sockaddr *sa_new, *sa_svc;
    766      1.1   fvdl 	struct sockaddr_in6 *sin6_new, *sin6_svc;
    767      1.1   fvdl 
    768      1.1   fvdl 	sa_svc = (struct sockaddr *)svc->buf;
    769      1.1   fvdl 	sa_new = (struct sockaddr *)new->buf;
    770      1.1   fvdl 
    771      1.1   fvdl 	if (sa_new->sa_family == sa_svc->sa_family &&
    772      1.1   fvdl 	    sa_new->sa_family == AF_INET6) {
    773      1.1   fvdl 		sin6_new = (struct sockaddr_in6 *)new->buf;
    774      1.1   fvdl 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
    775      1.1   fvdl 
    776      1.1   fvdl 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
    777      1.1   fvdl 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
    778      1.1   fvdl 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
    779      1.1   fvdl 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
    780      1.1   fvdl 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
    781      1.1   fvdl 		}
    782      1.1   fvdl 	}
    783      1.1   fvdl #endif
    784      1.1   fvdl 	return 1;
    785      1.1   fvdl }
    786      1.1   fvdl 
    787      1.1   fvdl int
    788      1.1   fvdl __rpc_sockisbound(int fd)
    789      1.1   fvdl {
    790      1.1   fvdl 	struct sockaddr_storage ss;
    791      1.1   fvdl 	socklen_t slen;
    792      1.1   fvdl 
    793      1.1   fvdl 	slen = sizeof (struct sockaddr_storage);
    794      1.1   fvdl 	if (getsockname(fd, (struct sockaddr *)&ss, &slen) < 0)
    795      1.1   fvdl 		return 0;
    796      1.1   fvdl 
    797      1.1   fvdl 	switch (ss.ss_family) {
    798      1.1   fvdl 		case AF_INET:
    799      1.1   fvdl 			return (((struct sockaddr_in *)&ss)->sin_port != 0);
    800      1.1   fvdl #ifdef INET6
    801      1.1   fvdl 		case AF_INET6:
    802      1.1   fvdl 			return (((struct sockaddr_in6 *)&ss)->sin6_port != 0);
    803      1.1   fvdl #endif
    804      1.1   fvdl 		case AF_LOCAL:
    805      1.1   fvdl 			/* XXX check this */
    806      1.1   fvdl 			return
    807      1.1   fvdl 			    (((struct sockaddr_un *)&ss)->sun_path[0] != '\0');
    808      1.1   fvdl 		default:
    809      1.1   fvdl 			break;
    810      1.1   fvdl 	}
    811      1.1   fvdl 
    812      1.1   fvdl 	return 0;
    813      1.1   fvdl }
    814