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