xref: /minix3/lib/libc/rpc/rpc_generic.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: rpc_generic.c,v 1.29 2013/04/05 03:17:38 dholland Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*
4*84d9c625SLionel Sambuc  * Copyright (c) 2010, Oracle America, Inc.
52fe8fb19SBen Gras  *
6*84d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
7*84d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions are
8*84d9c625SLionel Sambuc  * met:
92fe8fb19SBen Gras  *
10*84d9c625SLionel Sambuc  *     * Redistributions of source code must retain the above copyright
11*84d9c625SLionel Sambuc  *       notice, this list of conditions and the following disclaimer.
12*84d9c625SLionel Sambuc  *     * Redistributions in binary form must reproduce the above
13*84d9c625SLionel Sambuc  *       copyright notice, this list of conditions and the following
14*84d9c625SLionel Sambuc  *       disclaimer in the documentation and/or other materials
15*84d9c625SLionel Sambuc  *       provided with the distribution.
16*84d9c625SLionel Sambuc  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17*84d9c625SLionel Sambuc  *       contributors may be used to endorse or promote products derived
18*84d9c625SLionel Sambuc  *       from this software without specific prior written permission.
192fe8fb19SBen Gras  *
20*84d9c625SLionel Sambuc  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*84d9c625SLionel Sambuc  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*84d9c625SLionel Sambuc  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*84d9c625SLionel Sambuc  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24*84d9c625SLionel Sambuc  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25*84d9c625SLionel Sambuc  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*84d9c625SLionel Sambuc  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27*84d9c625SLionel Sambuc  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*84d9c625SLionel Sambuc  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29*84d9c625SLionel Sambuc  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*84d9c625SLionel Sambuc  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*84d9c625SLionel Sambuc  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322fe8fb19SBen Gras  */
332fe8fb19SBen Gras /*
342fe8fb19SBen Gras  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
352fe8fb19SBen Gras  */
362fe8fb19SBen Gras 
372fe8fb19SBen Gras /* #pragma ident	"@(#)rpc_generic.c	1.17	94/04/24 SMI" */
382fe8fb19SBen Gras 
392fe8fb19SBen Gras /*
402fe8fb19SBen Gras  * rpc_generic.c, Miscl routines for RPC.
412fe8fb19SBen Gras  *
422fe8fb19SBen Gras  */
432fe8fb19SBen Gras 
442fe8fb19SBen Gras #include <sys/cdefs.h>
452fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
46*84d9c625SLionel Sambuc __RCSID("$NetBSD: rpc_generic.c,v 1.29 2013/04/05 03:17:38 dholland Exp $");
472fe8fb19SBen Gras #endif
482fe8fb19SBen Gras 
492fe8fb19SBen Gras #include "namespace.h"
502fe8fb19SBen Gras #include "reentrant.h"
512fe8fb19SBen Gras #include <sys/types.h>
522fe8fb19SBen Gras #include <sys/param.h>
532fe8fb19SBen Gras #include <sys/socket.h>
542fe8fb19SBen Gras #include <sys/un.h>
552fe8fb19SBen Gras #include <sys/resource.h>
562fe8fb19SBen Gras #include <netinet/in.h>
572fe8fb19SBen Gras #include <netinet/tcp.h>
582fe8fb19SBen Gras #include <arpa/inet.h>
592fe8fb19SBen Gras #include <rpc/rpc.h>
602fe8fb19SBen Gras #include <assert.h>
612fe8fb19SBen Gras #include <ctype.h>
622fe8fb19SBen Gras #include <stdio.h>
632fe8fb19SBen Gras #include <netdb.h>
642fe8fb19SBen Gras #include <netconfig.h>
65*84d9c625SLionel Sambuc #include <stdlib.h>
662fe8fb19SBen Gras #include <string.h>
672fe8fb19SBen Gras #include <syslog.h>
682fe8fb19SBen Gras #include <rpc/nettype.h>
69*84d9c625SLionel Sambuc 
70*84d9c625SLionel Sambuc #include "svc_fdset.h"
712fe8fb19SBen Gras #include "rpc_internal.h"
722fe8fb19SBen Gras 
732fe8fb19SBen Gras #ifdef __weak_alias
742fe8fb19SBen Gras __weak_alias(taddr2uaddr,_taddr2uaddr)
752fe8fb19SBen Gras __weak_alias(uaddr2taddr,_uaddr2taddr)
762fe8fb19SBen Gras #endif
772fe8fb19SBen Gras 
782fe8fb19SBen Gras struct handle {
792fe8fb19SBen Gras 	NCONF_HANDLE *nhandle;
802fe8fb19SBen Gras 	int nflag;		/* Whether NETPATH or NETCONFIG */
812fe8fb19SBen Gras 	int nettype;
822fe8fb19SBen Gras };
832fe8fb19SBen Gras 
842fe8fb19SBen Gras static const struct _rpcnettype {
852fe8fb19SBen Gras 	const char *name;
862fe8fb19SBen Gras 	const int type;
872fe8fb19SBen Gras } _rpctypelist[] = {
882fe8fb19SBen Gras 	{ "netpath", _RPC_NETPATH },
892fe8fb19SBen Gras 	{ "visible", _RPC_VISIBLE },
902fe8fb19SBen Gras 	{ "circuit_v", _RPC_CIRCUIT_V },
912fe8fb19SBen Gras 	{ "datagram_v", _RPC_DATAGRAM_V },
922fe8fb19SBen Gras 	{ "circuit_n", _RPC_CIRCUIT_N },
932fe8fb19SBen Gras 	{ "datagram_n", _RPC_DATAGRAM_N },
942fe8fb19SBen Gras 	{ "tcp", _RPC_TCP },
952fe8fb19SBen Gras 	{ "udp", _RPC_UDP },
962fe8fb19SBen Gras 	{ 0, _RPC_NONE }
972fe8fb19SBen Gras };
982fe8fb19SBen Gras 
992fe8fb19SBen Gras struct netid_af {
1002fe8fb19SBen Gras 	const char	*netid;
1012fe8fb19SBen Gras 	int		af;
1022fe8fb19SBen Gras 	int		protocol;
1032fe8fb19SBen Gras };
1042fe8fb19SBen Gras 
1052fe8fb19SBen Gras static const struct netid_af na_cvt[] = {
1062fe8fb19SBen Gras 	{ "udp",  AF_INET,  IPPROTO_UDP },
1072fe8fb19SBen Gras 	{ "tcp",  AF_INET,  IPPROTO_TCP },
1082fe8fb19SBen Gras #ifdef INET6
1092fe8fb19SBen Gras 	{ "udp6", AF_INET6, IPPROTO_UDP },
1102fe8fb19SBen Gras 	{ "tcp6", AF_INET6, IPPROTO_TCP },
1112fe8fb19SBen Gras #endif
1122fe8fb19SBen Gras 	{ "local", AF_LOCAL, 0 }
1132fe8fb19SBen Gras };
1142fe8fb19SBen Gras 
1152fe8fb19SBen Gras #if 0
116f14fb602SLionel Sambuc static char *strlocase(char *);
1172fe8fb19SBen Gras #endif
118f14fb602SLionel Sambuc static int getnettype(const char *);
1192fe8fb19SBen Gras 
1202fe8fb19SBen Gras /*
1212fe8fb19SBen Gras  * Cache the result of getrlimit(), so we don't have to do an
1222fe8fb19SBen Gras  * expensive call every time.
1232fe8fb19SBen Gras  */
1242fe8fb19SBen Gras int
__rpc_dtbsize(void)125f14fb602SLionel Sambuc __rpc_dtbsize(void)
1262fe8fb19SBen Gras {
1272fe8fb19SBen Gras 	static int tbsize;
1282fe8fb19SBen Gras 	struct rlimit rl;
1292fe8fb19SBen Gras 
1302fe8fb19SBen Gras 	if (tbsize) {
1312fe8fb19SBen Gras 		return (tbsize);
1322fe8fb19SBen Gras 	}
1332fe8fb19SBen Gras 	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
1342fe8fb19SBen Gras 		return (tbsize = (int)rl.rlim_max);
1352fe8fb19SBen Gras 	}
1362fe8fb19SBen Gras 	/*
1372fe8fb19SBen Gras 	 * Something wrong.  I'll try to save face by returning a
1382fe8fb19SBen Gras 	 * pessimistic number.
1392fe8fb19SBen Gras 	 */
1402fe8fb19SBen Gras 	return (32);
1412fe8fb19SBen Gras }
1422fe8fb19SBen Gras 
1432fe8fb19SBen Gras 
1442fe8fb19SBen Gras /*
1452fe8fb19SBen Gras  * Find the appropriate buffer size
1462fe8fb19SBen Gras  */
1472fe8fb19SBen Gras u_int
1482fe8fb19SBen Gras /*ARGSUSED*/
__rpc_get_t_size(int af,int proto,int size)149f14fb602SLionel Sambuc __rpc_get_t_size(
150f14fb602SLionel Sambuc 	int af,
151f14fb602SLionel Sambuc 	int proto,
152f14fb602SLionel Sambuc 	int size)	/* Size requested */
1532fe8fb19SBen Gras {
1542fe8fb19SBen Gras 	int maxsize, defsize;
1552fe8fb19SBen Gras 
1562fe8fb19SBen Gras 	maxsize = 256 * 1024;	/* XXX */
1572fe8fb19SBen Gras 	switch (proto) {
1582fe8fb19SBen Gras 	case IPPROTO_TCP:
1592fe8fb19SBen Gras 		defsize = 64 * 1024;	/* XXX */
1602fe8fb19SBen Gras 		break;
1612fe8fb19SBen Gras 	case IPPROTO_UDP:
1622fe8fb19SBen Gras 		defsize = UDPMSGSIZE;
1632fe8fb19SBen Gras 		break;
1642fe8fb19SBen Gras 	default:
1652fe8fb19SBen Gras 		defsize = RPC_MAXDATASIZE;
1662fe8fb19SBen Gras 		break;
1672fe8fb19SBen Gras 	}
1682fe8fb19SBen Gras 	if (size == 0)
1692fe8fb19SBen Gras 		return defsize;
1702fe8fb19SBen Gras 
1712fe8fb19SBen Gras 	/* Check whether the value is within the upper max limit */
1722fe8fb19SBen Gras 	return (size > maxsize ? (u_int)maxsize : (u_int)size);
1732fe8fb19SBen Gras }
1742fe8fb19SBen Gras 
1752fe8fb19SBen Gras /*
1762fe8fb19SBen Gras  * Find the appropriate address buffer size
1772fe8fb19SBen Gras  */
1782fe8fb19SBen Gras u_int
__rpc_get_a_size(int af)179f14fb602SLionel Sambuc __rpc_get_a_size(int af)
1802fe8fb19SBen Gras {
1812fe8fb19SBen Gras 	switch (af) {
1822fe8fb19SBen Gras 	case AF_INET:
1832fe8fb19SBen Gras 		return sizeof (struct sockaddr_in);
1842fe8fb19SBen Gras #ifdef INET6
1852fe8fb19SBen Gras 	case AF_INET6:
1862fe8fb19SBen Gras 		return sizeof (struct sockaddr_in6);
1872fe8fb19SBen Gras #endif
1882fe8fb19SBen Gras 	case AF_LOCAL:
1892fe8fb19SBen Gras 		return sizeof (struct sockaddr_un);
1902fe8fb19SBen Gras 	default:
1912fe8fb19SBen Gras 		break;
1922fe8fb19SBen Gras 	}
1932fe8fb19SBen Gras 	return ((u_int)RPC_MAXADDRSIZE);
1942fe8fb19SBen Gras }
1952fe8fb19SBen Gras 
1962fe8fb19SBen Gras #if 0
1972fe8fb19SBen Gras static char *
198f14fb602SLionel Sambuc strlocase(char *p)
1992fe8fb19SBen Gras {
2002fe8fb19SBen Gras 	char *t = p;
2012fe8fb19SBen Gras 
2022fe8fb19SBen Gras 	_DIAGASSERT(p != NULL);
2032fe8fb19SBen Gras 
2042fe8fb19SBen Gras 	for (; *p; p++)
2052fe8fb19SBen Gras 		if (isupper(*p))
2062fe8fb19SBen Gras 			*p = tolower(*p);
2072fe8fb19SBen Gras 	return (t);
2082fe8fb19SBen Gras }
2092fe8fb19SBen Gras #endif
2102fe8fb19SBen Gras 
2112fe8fb19SBen Gras /*
2122fe8fb19SBen Gras  * Returns the type of the network as defined in <rpc/nettype.h>
2132fe8fb19SBen Gras  * If nettype is NULL, it defaults to NETPATH.
2142fe8fb19SBen Gras  */
2152fe8fb19SBen Gras static int
getnettype(const char * nettype)216f14fb602SLionel Sambuc getnettype(const char *nettype)
2172fe8fb19SBen Gras {
2182fe8fb19SBen Gras 	int i;
2192fe8fb19SBen Gras 
2202fe8fb19SBen Gras 	if ((nettype == NULL) || (nettype[0] == 0)) {
2212fe8fb19SBen Gras 		return (_RPC_NETPATH);	/* Default */
2222fe8fb19SBen Gras 	}
2232fe8fb19SBen Gras 
2242fe8fb19SBen Gras #if 0
2252fe8fb19SBen Gras 	nettype = strlocase(nettype);
2262fe8fb19SBen Gras #endif
2272fe8fb19SBen Gras 	for (i = 0; _rpctypelist[i].name; i++)
2282fe8fb19SBen Gras 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
2292fe8fb19SBen Gras 			return (_rpctypelist[i].type);
2302fe8fb19SBen Gras 		}
2312fe8fb19SBen Gras 	return (_rpctypelist[i].type);
2322fe8fb19SBen Gras }
2332fe8fb19SBen Gras 
2342fe8fb19SBen Gras /*
2352fe8fb19SBen Gras  * For the given nettype (tcp or udp only), return the first structure found.
2362fe8fb19SBen Gras  * This should be freed by calling freenetconfigent()
2372fe8fb19SBen Gras  */
2382fe8fb19SBen Gras 
2392fe8fb19SBen Gras #ifdef _REENTRANT
2402fe8fb19SBen Gras static thread_key_t tcp_key, udp_key;
2412fe8fb19SBen Gras static once_t __rpc_getconfigp_once = ONCE_INITIALIZER;
2422fe8fb19SBen Gras 
2432fe8fb19SBen Gras static void
__rpc_getconfigp_setup(void)2442fe8fb19SBen Gras __rpc_getconfigp_setup(void)
2452fe8fb19SBen Gras {
2462fe8fb19SBen Gras 
2472fe8fb19SBen Gras 	thr_keycreate(&tcp_key, free);
2482fe8fb19SBen Gras 	thr_keycreate(&udp_key, free);
2492fe8fb19SBen Gras }
2502fe8fb19SBen Gras #endif
2512fe8fb19SBen Gras 
2522fe8fb19SBen Gras struct netconfig *
__rpc_getconfip(const char * nettype)253f14fb602SLionel Sambuc __rpc_getconfip(const char *nettype)
2542fe8fb19SBen Gras {
2552fe8fb19SBen Gras 	char *netid;
2562fe8fb19SBen Gras 	char *netid_tcp = NULL;
2572fe8fb19SBen Gras 	char *netid_udp = NULL;
2582fe8fb19SBen Gras 	static char *netid_tcp_main;
2592fe8fb19SBen Gras 	static char *netid_udp_main;
2602fe8fb19SBen Gras 	struct netconfig *dummy;
2612fe8fb19SBen Gras #ifdef _REENTRANT
2622fe8fb19SBen Gras 	if (__isthreaded == 0) {
2632fe8fb19SBen Gras 		netid_udp = netid_udp_main;
2642fe8fb19SBen Gras 		netid_tcp = netid_tcp_main;
2652fe8fb19SBen Gras 	} else {
2662fe8fb19SBen Gras 		thr_once(&__rpc_getconfigp_once, __rpc_getconfigp_setup);
2672fe8fb19SBen Gras 		netid_tcp = thr_getspecific(tcp_key);
2682fe8fb19SBen Gras 		netid_udp = thr_getspecific(udp_key);
2692fe8fb19SBen Gras 	}
2702fe8fb19SBen Gras #else
2712fe8fb19SBen Gras 	netid_udp = netid_udp_main;
2722fe8fb19SBen Gras 	netid_tcp = netid_tcp_main;
2732fe8fb19SBen Gras #endif
2742fe8fb19SBen Gras 
2752fe8fb19SBen Gras 	_DIAGASSERT(nettype != NULL);
2762fe8fb19SBen Gras 
2772fe8fb19SBen Gras 	if (!netid_udp && !netid_tcp) {
2782fe8fb19SBen Gras 		struct netconfig *nconf;
2792fe8fb19SBen Gras 		void *confighandle;
2802fe8fb19SBen Gras 
2812fe8fb19SBen Gras 		if (!(confighandle = setnetconfig())) {
2822fe8fb19SBen Gras 			syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
2832fe8fb19SBen Gras 			return (NULL);
2842fe8fb19SBen Gras 		}
2852fe8fb19SBen Gras 		while ((nconf = getnetconfig(confighandle)) != NULL) {
2862fe8fb19SBen Gras 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
2872fe8fb19SBen Gras 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
2882fe8fb19SBen Gras 					netid_tcp = strdup(nconf->nc_netid);
2892fe8fb19SBen Gras 					if (netid_tcp == NULL)
2902fe8fb19SBen Gras 						return NULL;
2912fe8fb19SBen Gras #ifdef _REENTRANT
2922fe8fb19SBen Gras 					if (__isthreaded == 0)
2932fe8fb19SBen Gras 						netid_tcp_main = netid_tcp;
2942fe8fb19SBen Gras 					else
2952fe8fb19SBen Gras 						thr_setspecific(tcp_key,
2962fe8fb19SBen Gras 							(void *) netid_tcp);
2972fe8fb19SBen Gras #else
2982fe8fb19SBen Gras 					netid_tcp_main = netid_tcp;
2992fe8fb19SBen Gras #endif
3002fe8fb19SBen Gras 				} else
3012fe8fb19SBen Gras 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
3022fe8fb19SBen Gras 					netid_udp = strdup(nconf->nc_netid);
3032fe8fb19SBen Gras 					if (netid_udp == NULL)
3042fe8fb19SBen Gras 						return NULL;
3052fe8fb19SBen Gras #ifdef _REENTRANT
3062fe8fb19SBen Gras 					if (__isthreaded == 0)
3072fe8fb19SBen Gras 						netid_udp_main = netid_udp;
3082fe8fb19SBen Gras 					else
3092fe8fb19SBen Gras 						thr_setspecific(udp_key,
3102fe8fb19SBen Gras 							(void *) netid_udp);
3112fe8fb19SBen Gras #else
3122fe8fb19SBen Gras 					netid_udp_main = netid_udp;
3132fe8fb19SBen Gras #endif
3142fe8fb19SBen Gras 				}
3152fe8fb19SBen Gras 			}
3162fe8fb19SBen Gras 		}
3172fe8fb19SBen Gras 		endnetconfig(confighandle);
3182fe8fb19SBen Gras 	}
3192fe8fb19SBen Gras 	if (strcmp(nettype, "udp") == 0)
3202fe8fb19SBen Gras 		netid = netid_udp;
3212fe8fb19SBen Gras 	else if (strcmp(nettype, "tcp") == 0)
3222fe8fb19SBen Gras 		netid = netid_tcp;
3232fe8fb19SBen Gras 	else {
3242fe8fb19SBen Gras 		return (NULL);
3252fe8fb19SBen Gras 	}
3262fe8fb19SBen Gras 	if ((netid == NULL) || (netid[0] == 0)) {
3272fe8fb19SBen Gras 		return (NULL);
3282fe8fb19SBen Gras 	}
3292fe8fb19SBen Gras 	dummy = getnetconfigent(netid);
3302fe8fb19SBen Gras 	return (dummy);
3312fe8fb19SBen Gras }
3322fe8fb19SBen Gras 
3332fe8fb19SBen Gras /*
3342fe8fb19SBen Gras  * Returns the type of the nettype, which should then be used with
3352fe8fb19SBen Gras  * __rpc_getconf().
3362fe8fb19SBen Gras  */
3372fe8fb19SBen Gras void *
__rpc_setconf(const char * nettype)338f14fb602SLionel Sambuc __rpc_setconf(const char *nettype)
3392fe8fb19SBen Gras {
3402fe8fb19SBen Gras 	struct handle *handle;
3412fe8fb19SBen Gras 
3422fe8fb19SBen Gras 	/* nettype may be NULL; getnettype() supports that */
3432fe8fb19SBen Gras 
3442fe8fb19SBen Gras 	handle = malloc(sizeof(*handle));
3452fe8fb19SBen Gras 	if (handle == NULL) {
3462fe8fb19SBen Gras 		return (NULL);
3472fe8fb19SBen Gras 	}
3482fe8fb19SBen Gras 	switch (handle->nettype = getnettype(nettype)) {
3492fe8fb19SBen Gras 	case _RPC_NETPATH:
3502fe8fb19SBen Gras 	case _RPC_CIRCUIT_N:
3512fe8fb19SBen Gras 	case _RPC_DATAGRAM_N:
3522fe8fb19SBen Gras 		if (!(handle->nhandle = setnetpath())) {
3532fe8fb19SBen Gras 			free(handle);
3542fe8fb19SBen Gras 			return (NULL);
3552fe8fb19SBen Gras 		}
3562fe8fb19SBen Gras 		handle->nflag = TRUE;
3572fe8fb19SBen Gras 		break;
3582fe8fb19SBen Gras 	case _RPC_VISIBLE:
3592fe8fb19SBen Gras 	case _RPC_CIRCUIT_V:
3602fe8fb19SBen Gras 	case _RPC_DATAGRAM_V:
3612fe8fb19SBen Gras 	case _RPC_TCP:
3622fe8fb19SBen Gras 	case _RPC_UDP:
3632fe8fb19SBen Gras 		if (!(handle->nhandle = setnetconfig())) {
3642fe8fb19SBen Gras 		        syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
3652fe8fb19SBen Gras 			free(handle);
3662fe8fb19SBen Gras 			return (NULL);
3672fe8fb19SBen Gras 		}
3682fe8fb19SBen Gras 		handle->nflag = FALSE;
3692fe8fb19SBen Gras 		break;
3702fe8fb19SBen Gras 	default:
3712fe8fb19SBen Gras 		free(handle);
3722fe8fb19SBen Gras 		return (NULL);
3732fe8fb19SBen Gras 	}
3742fe8fb19SBen Gras 
3752fe8fb19SBen Gras 	return (handle);
3762fe8fb19SBen Gras }
3772fe8fb19SBen Gras 
3782fe8fb19SBen Gras /*
3792fe8fb19SBen Gras  * Returns the next netconfig struct for the given "net" type.
3802fe8fb19SBen Gras  * __rpc_setconf() should have been called previously.
3812fe8fb19SBen Gras  */
3822fe8fb19SBen Gras struct netconfig *
__rpc_getconf(void * vhandle)383f14fb602SLionel Sambuc __rpc_getconf(void *vhandle)
3842fe8fb19SBen Gras {
3852fe8fb19SBen Gras 	struct handle *handle;
3862fe8fb19SBen Gras 	struct netconfig *nconf;
3872fe8fb19SBen Gras 
3882fe8fb19SBen Gras 	handle = (struct handle *)vhandle;
3892fe8fb19SBen Gras 	if (handle == NULL) {
3902fe8fb19SBen Gras 		return (NULL);
3912fe8fb19SBen Gras 	}
3922fe8fb19SBen Gras 	for (;;) {
3932fe8fb19SBen Gras 		if (handle->nflag)
3942fe8fb19SBen Gras 			nconf = getnetpath(handle->nhandle);
3952fe8fb19SBen Gras 		else
3962fe8fb19SBen Gras 			nconf = getnetconfig(handle->nhandle);
3972fe8fb19SBen Gras 		if (nconf == NULL)
3982fe8fb19SBen Gras 			break;
3992fe8fb19SBen Gras 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
4002fe8fb19SBen Gras 			(nconf->nc_semantics != NC_TPI_COTS) &&
4012fe8fb19SBen Gras 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
4022fe8fb19SBen Gras 			continue;
4032fe8fb19SBen Gras 		switch (handle->nettype) {
4042fe8fb19SBen Gras 		case _RPC_VISIBLE:
4052fe8fb19SBen Gras 			if (!(nconf->nc_flag & NC_VISIBLE))
4062fe8fb19SBen Gras 				continue;
4072fe8fb19SBen Gras 			/* FALLTHROUGH */
4082fe8fb19SBen Gras 		case _RPC_NETPATH:	/* Be happy */
4092fe8fb19SBen Gras 			break;
4102fe8fb19SBen Gras 		case _RPC_CIRCUIT_V:
4112fe8fb19SBen Gras 			if (!(nconf->nc_flag & NC_VISIBLE))
4122fe8fb19SBen Gras 				continue;
4132fe8fb19SBen Gras 			/* FALLTHROUGH */
4142fe8fb19SBen Gras 		case _RPC_CIRCUIT_N:
4152fe8fb19SBen Gras 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
4162fe8fb19SBen Gras 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
4172fe8fb19SBen Gras 				continue;
4182fe8fb19SBen Gras 			break;
4192fe8fb19SBen Gras 		case _RPC_DATAGRAM_V:
4202fe8fb19SBen Gras 			if (!(nconf->nc_flag & NC_VISIBLE))
4212fe8fb19SBen Gras 				continue;
4222fe8fb19SBen Gras 			/* FALLTHROUGH */
4232fe8fb19SBen Gras 		case _RPC_DATAGRAM_N:
4242fe8fb19SBen Gras 			if (nconf->nc_semantics != NC_TPI_CLTS)
4252fe8fb19SBen Gras 				continue;
4262fe8fb19SBen Gras 			break;
4272fe8fb19SBen Gras 		case _RPC_TCP:
4282fe8fb19SBen Gras 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
4292fe8fb19SBen Gras 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
4302fe8fb19SBen Gras 				(strcmp(nconf->nc_protofmly, NC_INET)
4312fe8fb19SBen Gras #ifdef INET6
4322fe8fb19SBen Gras 				 && strcmp(nconf->nc_protofmly, NC_INET6))
4332fe8fb19SBen Gras #else
4342fe8fb19SBen Gras 				)
4352fe8fb19SBen Gras #endif
4362fe8fb19SBen Gras 				||
4372fe8fb19SBen Gras 				strcmp(nconf->nc_proto, NC_TCP))
4382fe8fb19SBen Gras 				continue;
4392fe8fb19SBen Gras 			break;
4402fe8fb19SBen Gras 		case _RPC_UDP:
4412fe8fb19SBen Gras 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
4422fe8fb19SBen Gras 				(strcmp(nconf->nc_protofmly, NC_INET)
4432fe8fb19SBen Gras #ifdef INET6
4442fe8fb19SBen Gras 				&& strcmp(nconf->nc_protofmly, NC_INET6))
4452fe8fb19SBen Gras #else
4462fe8fb19SBen Gras 				)
4472fe8fb19SBen Gras #endif
4482fe8fb19SBen Gras 				||
4492fe8fb19SBen Gras 				strcmp(nconf->nc_proto, NC_UDP))
4502fe8fb19SBen Gras 				continue;
4512fe8fb19SBen Gras 			break;
4522fe8fb19SBen Gras 		}
4532fe8fb19SBen Gras 		break;
4542fe8fb19SBen Gras 	}
4552fe8fb19SBen Gras 	return (nconf);
4562fe8fb19SBen Gras }
4572fe8fb19SBen Gras 
4582fe8fb19SBen Gras void
__rpc_endconf(void * vhandle)459f14fb602SLionel Sambuc __rpc_endconf(void *vhandle)
4602fe8fb19SBen Gras {
4612fe8fb19SBen Gras 	struct handle *handle;
4622fe8fb19SBen Gras 
4632fe8fb19SBen Gras 	handle = (struct handle *) vhandle;
4642fe8fb19SBen Gras 	if (handle == NULL) {
4652fe8fb19SBen Gras 		return;
4662fe8fb19SBen Gras 	}
4672fe8fb19SBen Gras 	if (handle->nflag) {
4682fe8fb19SBen Gras 		endnetpath(handle->nhandle);
4692fe8fb19SBen Gras 	} else {
4702fe8fb19SBen Gras 		endnetconfig(handle->nhandle);
4712fe8fb19SBen Gras 	}
4722fe8fb19SBen Gras 	free(handle);
4732fe8fb19SBen Gras }
4742fe8fb19SBen Gras 
4752fe8fb19SBen Gras /*
4762fe8fb19SBen Gras  * Used to ping the NULL procedure for clnt handle.
4772fe8fb19SBen Gras  * Returns NULL if fails, else a non-NULL pointer.
4782fe8fb19SBen Gras  */
4792fe8fb19SBen Gras void *
rpc_nullproc(CLIENT * clnt)480f14fb602SLionel Sambuc rpc_nullproc(CLIENT *clnt)
4812fe8fb19SBen Gras {
4822fe8fb19SBen Gras 	struct timeval TIMEOUT = {25, 0};
4832fe8fb19SBen Gras 
4842fe8fb19SBen Gras 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
4852fe8fb19SBen Gras 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
4862fe8fb19SBen Gras 		return (NULL);
4872fe8fb19SBen Gras 	}
4882fe8fb19SBen Gras 	return ((void *) clnt);
4892fe8fb19SBen Gras }
4902fe8fb19SBen Gras 
4912fe8fb19SBen Gras /*
4922fe8fb19SBen Gras  * Try all possible transports until
4932fe8fb19SBen Gras  * one succeeds in finding the netconf for the given fd.
4942fe8fb19SBen Gras  */
4952fe8fb19SBen Gras struct netconfig *
__rpcgettp(int fd)496f14fb602SLionel Sambuc __rpcgettp(int fd)
4972fe8fb19SBen Gras {
4982fe8fb19SBen Gras 	const char *netid;
4992fe8fb19SBen Gras 	struct __rpc_sockinfo si;
5002fe8fb19SBen Gras 
5012fe8fb19SBen Gras 	if (!__rpc_fd2sockinfo(fd, &si))
5022fe8fb19SBen Gras 		return NULL;
5032fe8fb19SBen Gras 
5042fe8fb19SBen Gras 	if (!__rpc_sockinfo2netid(&si, &netid))
5052fe8fb19SBen Gras 		return NULL;
5062fe8fb19SBen Gras 
5072fe8fb19SBen Gras 	return getnetconfigent(__UNCONST(netid));
5082fe8fb19SBen Gras }
5092fe8fb19SBen Gras 
5102fe8fb19SBen Gras int
__rpc_fd2sockinfo(int fd,struct __rpc_sockinfo * sip)5112fe8fb19SBen Gras __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
5122fe8fb19SBen Gras {
5132fe8fb19SBen Gras 	socklen_t len;
5142fe8fb19SBen Gras 	int type, proto;
5152fe8fb19SBen Gras 	struct sockaddr_storage ss;
5162fe8fb19SBen Gras 
5172fe8fb19SBen Gras 	_DIAGASSERT(sip != NULL);
5182fe8fb19SBen Gras 
5192fe8fb19SBen Gras 	len = sizeof ss;
5202fe8fb19SBen Gras 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
5212fe8fb19SBen Gras 		return 0;
5222fe8fb19SBen Gras 	sip->si_alen = len;
5232fe8fb19SBen Gras 
5242fe8fb19SBen Gras 	len = sizeof type;
5252fe8fb19SBen Gras 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
5262fe8fb19SBen Gras 		return 0;
5272fe8fb19SBen Gras 
5282fe8fb19SBen Gras 	/* XXX */
5292fe8fb19SBen Gras 	if (ss.ss_family != AF_LOCAL) {
5302fe8fb19SBen Gras 		if (type == SOCK_STREAM)
5312fe8fb19SBen Gras 			proto = IPPROTO_TCP;
5322fe8fb19SBen Gras 		else if (type == SOCK_DGRAM)
5332fe8fb19SBen Gras 			proto = IPPROTO_UDP;
5342fe8fb19SBen Gras 		else
5352fe8fb19SBen Gras 			return 0;
5362fe8fb19SBen Gras 	} else
5372fe8fb19SBen Gras 		proto = 0;
5382fe8fb19SBen Gras 
5392fe8fb19SBen Gras 	sip->si_af = ss.ss_family;
5402fe8fb19SBen Gras 	sip->si_proto = proto;
5412fe8fb19SBen Gras 	sip->si_socktype = type;
5422fe8fb19SBen Gras 
5432fe8fb19SBen Gras 	return 1;
5442fe8fb19SBen Gras }
5452fe8fb19SBen Gras 
5462fe8fb19SBen Gras /*
5472fe8fb19SBen Gras  * Linear search, but the number of entries is small.
5482fe8fb19SBen Gras  */
5492fe8fb19SBen Gras int
__rpc_nconf2sockinfo(const struct netconfig * nconf,struct __rpc_sockinfo * sip)5502fe8fb19SBen Gras __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
5512fe8fb19SBen Gras {
5522fe8fb19SBen Gras 	size_t i;
5532fe8fb19SBen Gras 
5542fe8fb19SBen Gras 	_DIAGASSERT(nconf != NULL);
5552fe8fb19SBen Gras 	_DIAGASSERT(sip != NULL);
5562fe8fb19SBen Gras 
5572fe8fb19SBen Gras 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
5582fe8fb19SBen Gras 		if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
5592fe8fb19SBen Gras 			sip->si_af = na_cvt[i].af;
5602fe8fb19SBen Gras 			sip->si_proto = na_cvt[i].protocol;
5612fe8fb19SBen Gras 			sip->si_socktype =
5622fe8fb19SBen Gras 			    __rpc_seman2socktype((int)nconf->nc_semantics);
5632fe8fb19SBen Gras 			if (sip->si_socktype == -1)
5642fe8fb19SBen Gras 				return 0;
5652fe8fb19SBen Gras 			sip->si_alen = __rpc_get_a_size(sip->si_af);
5662fe8fb19SBen Gras 			return 1;
5672fe8fb19SBen Gras 		}
5682fe8fb19SBen Gras 
5692fe8fb19SBen Gras 	return 0;
5702fe8fb19SBen Gras }
5712fe8fb19SBen Gras 
5722fe8fb19SBen Gras int
__rpc_nconf2fd(const struct netconfig * nconf)5732fe8fb19SBen Gras __rpc_nconf2fd(const struct netconfig *nconf)
5742fe8fb19SBen Gras {
5752fe8fb19SBen Gras 	struct __rpc_sockinfo si;
5762fe8fb19SBen Gras 
5772fe8fb19SBen Gras 	_DIAGASSERT(nconf != NULL);
5782fe8fb19SBen Gras 
5792fe8fb19SBen Gras 	if (!__rpc_nconf2sockinfo(nconf, &si))
5802fe8fb19SBen Gras 		return 0;
5812fe8fb19SBen Gras 
5822fe8fb19SBen Gras 	return socket(si.si_af, si.si_socktype, si.si_proto);
5832fe8fb19SBen Gras }
5842fe8fb19SBen Gras 
5852fe8fb19SBen Gras int
__rpc_sockinfo2netid(struct __rpc_sockinfo * sip,const char ** netid)5862fe8fb19SBen Gras __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
5872fe8fb19SBen Gras {
5882fe8fb19SBen Gras 	size_t i;
5892fe8fb19SBen Gras 
5902fe8fb19SBen Gras 	_DIAGASSERT(sip != NULL);
5912fe8fb19SBen Gras 	/* netid may be NULL */
5922fe8fb19SBen Gras 
5932fe8fb19SBen Gras 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
5942fe8fb19SBen Gras 		if (na_cvt[i].af == sip->si_af &&
5952fe8fb19SBen Gras 		    na_cvt[i].protocol == sip->si_proto) {
5962fe8fb19SBen Gras 			if (netid)
5972fe8fb19SBen Gras 				*netid = na_cvt[i].netid;
5982fe8fb19SBen Gras 			return 1;
5992fe8fb19SBen Gras 		}
6002fe8fb19SBen Gras 
6012fe8fb19SBen Gras 	return 0;
6022fe8fb19SBen Gras }
6032fe8fb19SBen Gras 
6042fe8fb19SBen Gras char *
taddr2uaddr(const struct netconfig * nconf,const struct netbuf * nbuf)6052fe8fb19SBen Gras taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
6062fe8fb19SBen Gras {
6072fe8fb19SBen Gras 	struct __rpc_sockinfo si;
6082fe8fb19SBen Gras 
6092fe8fb19SBen Gras 	_DIAGASSERT(nconf != NULL);
6102fe8fb19SBen Gras 	_DIAGASSERT(nbuf != NULL);
6112fe8fb19SBen Gras 
6122fe8fb19SBen Gras 	if (!__rpc_nconf2sockinfo(nconf, &si))
6132fe8fb19SBen Gras 		return NULL;
6142fe8fb19SBen Gras 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
6152fe8fb19SBen Gras }
6162fe8fb19SBen Gras 
6172fe8fb19SBen Gras struct netbuf *
uaddr2taddr(const struct netconfig * nconf,const char * uaddr)6182fe8fb19SBen Gras uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
6192fe8fb19SBen Gras {
6202fe8fb19SBen Gras 	struct __rpc_sockinfo si;
6212fe8fb19SBen Gras 
6222fe8fb19SBen Gras 	_DIAGASSERT(nconf != NULL);
6232fe8fb19SBen Gras 	_DIAGASSERT(uaddr != NULL);
6242fe8fb19SBen Gras 
6252fe8fb19SBen Gras 	if (!__rpc_nconf2sockinfo(nconf, &si))
6262fe8fb19SBen Gras 		return NULL;
6272fe8fb19SBen Gras 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
6282fe8fb19SBen Gras }
6292fe8fb19SBen Gras 
6302fe8fb19SBen Gras char *
__rpc_taddr2uaddr_af(int af,const struct netbuf * nbuf)6312fe8fb19SBen Gras __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
6322fe8fb19SBen Gras {
6332fe8fb19SBen Gras 	char *ret;
6342fe8fb19SBen Gras 	struct sockaddr_in *sinp;
6352fe8fb19SBen Gras 	struct sockaddr_un *sun;
6362fe8fb19SBen Gras 	char namebuf[INET_ADDRSTRLEN];
6372fe8fb19SBen Gras #ifdef INET6
6382fe8fb19SBen Gras 	struct sockaddr_in6 *sin6;
6392fe8fb19SBen Gras 	char namebuf6[INET6_ADDRSTRLEN];
6402fe8fb19SBen Gras #endif
6412fe8fb19SBen Gras 	u_int16_t port;
6422fe8fb19SBen Gras 
6432fe8fb19SBen Gras 	_DIAGASSERT(nbuf != NULL);
6442fe8fb19SBen Gras 
6452fe8fb19SBen Gras 	switch (af) {
6462fe8fb19SBen Gras 	case AF_INET:
6472fe8fb19SBen Gras 		sinp = nbuf->buf;
648f14fb602SLionel Sambuc 		if (inet_ntop(af, &sinp->sin_addr, namebuf,
649f14fb602SLionel Sambuc 		    (socklen_t)sizeof namebuf) == NULL)
6502fe8fb19SBen Gras 			return NULL;
6512fe8fb19SBen Gras 		port = ntohs(sinp->sin_port);
6522fe8fb19SBen Gras 		if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
6532fe8fb19SBen Gras 		    port & 0xff) < 0)
6542fe8fb19SBen Gras 			return NULL;
6552fe8fb19SBen Gras 		break;
6562fe8fb19SBen Gras #ifdef INET6
6572fe8fb19SBen Gras 	case AF_INET6:
6582fe8fb19SBen Gras 		sin6 = nbuf->buf;
659f14fb602SLionel Sambuc 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6,
660f14fb602SLionel Sambuc 		    (socklen_t)sizeof namebuf6) == NULL)
6612fe8fb19SBen Gras 			return NULL;
6622fe8fb19SBen Gras 		port = ntohs(sin6->sin6_port);
6632fe8fb19SBen Gras 		if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
6642fe8fb19SBen Gras 		    port & 0xff) < 0)
6652fe8fb19SBen Gras 			return NULL;
6662fe8fb19SBen Gras 		break;
6672fe8fb19SBen Gras #endif
6682fe8fb19SBen Gras 	case AF_LOCAL:
6692fe8fb19SBen Gras 		sun = nbuf->buf;
6702fe8fb19SBen Gras 		sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
6712fe8fb19SBen Gras 		ret = strdup(sun->sun_path);
6722fe8fb19SBen Gras 		break;
6732fe8fb19SBen Gras 	default:
6742fe8fb19SBen Gras 		return NULL;
6752fe8fb19SBen Gras 	}
6762fe8fb19SBen Gras 
6772fe8fb19SBen Gras 	return ret;
6782fe8fb19SBen Gras }
6792fe8fb19SBen Gras 
6802fe8fb19SBen Gras struct netbuf *
__rpc_uaddr2taddr_af(int af,const char * uaddr)6812fe8fb19SBen Gras __rpc_uaddr2taddr_af(int af, const char *uaddr)
6822fe8fb19SBen Gras {
6832fe8fb19SBen Gras 	struct netbuf *ret = NULL;
6842fe8fb19SBen Gras 	char *addrstr, *p;
6852fe8fb19SBen Gras 	unsigned port, portlo, porthi;
686f14fb602SLionel Sambuc 	size_t len;
6872fe8fb19SBen Gras 	struct sockaddr_in *sinp;
6882fe8fb19SBen Gras #ifdef INET6
6892fe8fb19SBen Gras 	struct sockaddr_in6 *sin6;
6902fe8fb19SBen Gras #endif
6912fe8fb19SBen Gras 	struct sockaddr_un *sun;
6922fe8fb19SBen Gras 
6932fe8fb19SBen Gras 	_DIAGASSERT(uaddr != NULL);
6942fe8fb19SBen Gras 
6952fe8fb19SBen Gras 	addrstr = strdup(uaddr);
6962fe8fb19SBen Gras 	if (addrstr == NULL)
6972fe8fb19SBen Gras 		return NULL;
6982fe8fb19SBen Gras 
6992fe8fb19SBen Gras 	/*
7002fe8fb19SBen Gras 	 * AF_LOCAL addresses are expected to be absolute
7012fe8fb19SBen Gras 	 * pathnames, anything else will be AF_INET or AF_INET6.
7022fe8fb19SBen Gras 	 */
7032fe8fb19SBen Gras 	port = 0;
7042fe8fb19SBen Gras 	if (*addrstr != '/') {
7052fe8fb19SBen Gras 		p = strrchr(addrstr, '.');
7062fe8fb19SBen Gras 		if (p == NULL)
7072fe8fb19SBen Gras 			goto out;
7082fe8fb19SBen Gras 		portlo = (unsigned)atoi(p + 1);
7092fe8fb19SBen Gras 		*p = '\0';
7102fe8fb19SBen Gras 
7112fe8fb19SBen Gras 		p = strrchr(addrstr, '.');
7122fe8fb19SBen Gras 		if (p == NULL)
7132fe8fb19SBen Gras 			goto out;
7142fe8fb19SBen Gras 		porthi = (unsigned)atoi(p + 1);
7152fe8fb19SBen Gras 		*p = '\0';
7162fe8fb19SBen Gras 		port = (porthi << 8) | portlo;
7172fe8fb19SBen Gras 	}
7182fe8fb19SBen Gras 
7192fe8fb19SBen Gras 	ret = malloc(sizeof(*ret));
7202fe8fb19SBen Gras 	if (ret == NULL)
7212fe8fb19SBen Gras 		goto out;
7222fe8fb19SBen Gras 
7232fe8fb19SBen Gras 	switch (af) {
7242fe8fb19SBen Gras 	case AF_INET:
7252fe8fb19SBen Gras 		sinp = malloc(sizeof(*sinp));
7262fe8fb19SBen Gras 		if (sinp == NULL)
7272fe8fb19SBen Gras 			goto out;
7282fe8fb19SBen Gras 		memset(sinp, 0, sizeof *sinp);
7292fe8fb19SBen Gras 		sinp->sin_family = AF_INET;
7302fe8fb19SBen Gras 		sinp->sin_port = htons(port);
7312fe8fb19SBen Gras 		if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) {
7322fe8fb19SBen Gras 			free(sinp);
7332fe8fb19SBen Gras 			free(ret);
7342fe8fb19SBen Gras 			ret = NULL;
7352fe8fb19SBen Gras 			goto out;
7362fe8fb19SBen Gras 		}
7372fe8fb19SBen Gras 		sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp;
7382fe8fb19SBen Gras 		ret->buf = sinp;
7392fe8fb19SBen Gras 		break;
7402fe8fb19SBen Gras #ifdef INET6
7412fe8fb19SBen Gras 	case AF_INET6:
7422fe8fb19SBen Gras 		sin6 = malloc(sizeof(*sin6));
7432fe8fb19SBen Gras 		if (sin6 == NULL)
7442fe8fb19SBen Gras 			goto out;
7452fe8fb19SBen Gras 		memset(sin6, 0, sizeof *sin6);
7462fe8fb19SBen Gras 		sin6->sin6_family = AF_INET6;
7472fe8fb19SBen Gras 		sin6->sin6_port = htons(port);
7482fe8fb19SBen Gras 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
7492fe8fb19SBen Gras 			free(sin6);
7502fe8fb19SBen Gras 			free(ret);
7512fe8fb19SBen Gras 			ret = NULL;
7522fe8fb19SBen Gras 			goto out;
7532fe8fb19SBen Gras 		}
7542fe8fb19SBen Gras 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
7552fe8fb19SBen Gras 		ret->buf = sin6;
7562fe8fb19SBen Gras 		break;
7572fe8fb19SBen Gras #endif
7582fe8fb19SBen Gras 	case AF_LOCAL:
7592fe8fb19SBen Gras 		sun = malloc(sizeof(*sun));
7602fe8fb19SBen Gras 		if (sun == NULL)
7612fe8fb19SBen Gras 			goto out;
7622fe8fb19SBen Gras 		memset(sun, 0, sizeof *sun);
7632fe8fb19SBen Gras 		sun->sun_family = AF_LOCAL;
7642fe8fb19SBen Gras 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
765f14fb602SLionel Sambuc 		len = SUN_LEN(sun);
766f14fb602SLionel Sambuc 		_DIAGASSERT(__type_fit(uint8_t, len));
767f14fb602SLionel Sambuc 		ret->len = ret->maxlen = sun->sun_len = (uint8_t)len;
7682fe8fb19SBen Gras 		ret->buf = sun;
7692fe8fb19SBen Gras 		break;
7702fe8fb19SBen Gras 	default:
7712fe8fb19SBen Gras 		break;
7722fe8fb19SBen Gras 	}
7732fe8fb19SBen Gras out:
7742fe8fb19SBen Gras 	free(addrstr);
7752fe8fb19SBen Gras 	return ret;
7762fe8fb19SBen Gras }
7772fe8fb19SBen Gras 
7782fe8fb19SBen Gras int
__rpc_seman2socktype(int semantics)7792fe8fb19SBen Gras __rpc_seman2socktype(int semantics)
7802fe8fb19SBen Gras {
7812fe8fb19SBen Gras 	switch (semantics) {
7822fe8fb19SBen Gras 	case NC_TPI_CLTS:
7832fe8fb19SBen Gras 		return SOCK_DGRAM;
7842fe8fb19SBen Gras 	case NC_TPI_COTS_ORD:
7852fe8fb19SBen Gras 		return SOCK_STREAM;
7862fe8fb19SBen Gras 	case NC_TPI_RAW:
7872fe8fb19SBen Gras 		return SOCK_RAW;
7882fe8fb19SBen Gras 	default:
7892fe8fb19SBen Gras 		break;
7902fe8fb19SBen Gras 	}
7912fe8fb19SBen Gras 
7922fe8fb19SBen Gras 	return -1;
7932fe8fb19SBen Gras }
7942fe8fb19SBen Gras 
7952fe8fb19SBen Gras int
__rpc_socktype2seman(int socktype)7962fe8fb19SBen Gras __rpc_socktype2seman(int socktype)
7972fe8fb19SBen Gras {
7982fe8fb19SBen Gras 	switch (socktype) {
7992fe8fb19SBen Gras 	case SOCK_DGRAM:
8002fe8fb19SBen Gras 		return NC_TPI_CLTS;
8012fe8fb19SBen Gras 	case SOCK_STREAM:
8022fe8fb19SBen Gras 		return NC_TPI_COTS_ORD;
8032fe8fb19SBen Gras 	case SOCK_RAW:
8042fe8fb19SBen Gras 		return NC_TPI_RAW;
8052fe8fb19SBen Gras 	default:
8062fe8fb19SBen Gras 		break;
8072fe8fb19SBen Gras 	}
8082fe8fb19SBen Gras 
8092fe8fb19SBen Gras 	return -1;
8102fe8fb19SBen Gras }
8112fe8fb19SBen Gras 
8122fe8fb19SBen Gras /*
8132fe8fb19SBen Gras  * XXXX - IPv6 scope IDs can't be handled in universal addresses.
8142fe8fb19SBen Gras  * Here, we compare the original server address to that of the RPC
8152fe8fb19SBen Gras  * service we just received back from a call to rpcbind on the remote
8162fe8fb19SBen Gras  * machine. If they are both "link local" or "site local", copy
8172fe8fb19SBen Gras  * the scope id of the server address over to the service address.
8182fe8fb19SBen Gras  */
8192fe8fb19SBen Gras /* ARGSUSED */
8202fe8fb19SBen Gras int
__rpc_fixup_addr(struct netbuf * new,const struct netbuf * svc)8212fe8fb19SBen Gras __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
8222fe8fb19SBen Gras {
8232fe8fb19SBen Gras #ifdef INET6
8242fe8fb19SBen Gras 	struct sockaddr *sa_new, *sa_svc;
8252fe8fb19SBen Gras 	struct sockaddr_in6 *sin6_new, *sin6_svc;
8262fe8fb19SBen Gras 
8272fe8fb19SBen Gras 	_DIAGASSERT(new != NULL);
8282fe8fb19SBen Gras 	_DIAGASSERT(svc != NULL);
8292fe8fb19SBen Gras 
8302fe8fb19SBen Gras 	sa_svc = (struct sockaddr *)svc->buf;
8312fe8fb19SBen Gras 	sa_new = (struct sockaddr *)new->buf;
8322fe8fb19SBen Gras 
8332fe8fb19SBen Gras 	if (sa_new->sa_family == sa_svc->sa_family &&
8342fe8fb19SBen Gras 	    sa_new->sa_family == AF_INET6) {
8352fe8fb19SBen Gras 		sin6_new = (struct sockaddr_in6 *)new->buf;
8362fe8fb19SBen Gras 		sin6_svc = (struct sockaddr_in6 *)svc->buf;
8372fe8fb19SBen Gras 
8382fe8fb19SBen Gras 		if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
8392fe8fb19SBen Gras 		     IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
8402fe8fb19SBen Gras 		    (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
8412fe8fb19SBen Gras 		     IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
8422fe8fb19SBen Gras 			sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
8432fe8fb19SBen Gras 		}
8442fe8fb19SBen Gras 	}
8452fe8fb19SBen Gras #endif
8462fe8fb19SBen Gras 	return 1;
8472fe8fb19SBen Gras }
8482fe8fb19SBen Gras 
8492fe8fb19SBen Gras int
__rpc_sockisbound(int fd)8502fe8fb19SBen Gras __rpc_sockisbound(int fd)
8512fe8fb19SBen Gras {
8522fe8fb19SBen Gras 	struct sockaddr_storage ss;
8532fe8fb19SBen Gras 	socklen_t slen;
8542fe8fb19SBen Gras 
8552fe8fb19SBen Gras 	slen = sizeof (struct sockaddr_storage);
8562fe8fb19SBen Gras 	if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
8572fe8fb19SBen Gras 		return 0;
8582fe8fb19SBen Gras 
8592fe8fb19SBen Gras 	switch (ss.ss_family) {
8602fe8fb19SBen Gras 		case AF_INET:
8612fe8fb19SBen Gras 			return (((struct sockaddr_in *)
8622fe8fb19SBen Gras 			    (void *)&ss)->sin_port != 0);
8632fe8fb19SBen Gras #ifdef INET6
8642fe8fb19SBen Gras 		case AF_INET6:
8652fe8fb19SBen Gras 			return (((struct sockaddr_in6 *)
8662fe8fb19SBen Gras 			    (void *)&ss)->sin6_port != 0);
8672fe8fb19SBen Gras #endif
8682fe8fb19SBen Gras 		case AF_LOCAL:
8692fe8fb19SBen Gras 			/* XXX check this */
8702fe8fb19SBen Gras 			return (((struct sockaddr_un *)
8712fe8fb19SBen Gras 			    (void *)&ss)->sun_path[0] != '\0');
8722fe8fb19SBen Gras 		default:
8732fe8fb19SBen Gras 			break;
8742fe8fb19SBen Gras 	}
8752fe8fb19SBen Gras 
8762fe8fb19SBen Gras 	return 0;
8772fe8fb19SBen Gras }
8782fe8fb19SBen Gras 
8792fe8fb19SBen Gras /*
8802fe8fb19SBen Gras  * For TCP transport, Host Requirements RFCs mandate
8812fe8fb19SBen Gras  * Nagle (RFC-896) processing.  But for RPC, Nagle
8822fe8fb19SBen Gras  * processing adds adds unwanted latency to the last,
8832fe8fb19SBen Gras  * partial TCP segment of each RPC message. See:
8842fe8fb19SBen Gras  *   R. W. Scheifler and J. Gettys, The X Window System,
8852fe8fb19SBen Gras  *   ACM Transactions on Graphics 16:8 (Aug. 1983), pp. 57-69.
8862fe8fb19SBen Gras  * So for TCP transport, disable Nagle via TCP_NODELAY.
8872fe8fb19SBen Gras  * XXX: moral equivalent for non-TCP protocols?
8882fe8fb19SBen Gras  */
8892fe8fb19SBen Gras int
__rpc_setnodelay(int fd,const struct __rpc_sockinfo * si)8902fe8fb19SBen Gras __rpc_setnodelay(int fd, const struct __rpc_sockinfo *si)
8912fe8fb19SBen Gras {
8922fe8fb19SBen Gras 	int one = 1;
8932fe8fb19SBen Gras 	if (si->si_proto != IPPROTO_TCP)
8942fe8fb19SBen Gras 		return 0;
895f14fb602SLionel Sambuc 	return setsockopt(fd, si->si_proto, TCP_NODELAY, &one,
896f14fb602SLionel Sambuc 	    (socklen_t)sizeof(one));
8972fe8fb19SBen Gras }
898