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