xref: /freebsd/sys/rpc/rpc_generic.c (revision fa1b961259bc5ba90b2ed693d8eb54c7641b6ec7)
1dfdcada3SDoug Rabson /*	$NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $	*/
2dfdcada3SDoug Rabson 
32e322d37SHiroki Sato /*-
451369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
551369649SPedro F. Giffuni  *
62e322d37SHiroki Sato  * Copyright (c) 2009, Sun Microsystems, Inc.
72e322d37SHiroki Sato  * All rights reserved.
8dfdcada3SDoug Rabson  *
92e322d37SHiroki Sato  * Redistribution and use in source and binary forms, with or without
102e322d37SHiroki Sato  * modification, are permitted provided that the following conditions are met:
112e322d37SHiroki Sato  * - Redistributions of source code must retain the above copyright notice,
122e322d37SHiroki Sato  *   this list of conditions and the following disclaimer.
132e322d37SHiroki Sato  * - Redistributions in binary form must reproduce the above copyright notice,
142e322d37SHiroki Sato  *   this list of conditions and the following disclaimer in the documentation
152e322d37SHiroki Sato  *   and/or other materials provided with the distribution.
162e322d37SHiroki Sato  * - Neither the name of Sun Microsystems, Inc. nor the names of its
172e322d37SHiroki Sato  *   contributors may be used to endorse or promote products derived
182e322d37SHiroki Sato  *   from this software without specific prior written permission.
19dfdcada3SDoug Rabson  *
202e322d37SHiroki Sato  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
212e322d37SHiroki Sato  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222e322d37SHiroki Sato  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
232e322d37SHiroki Sato  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
242e322d37SHiroki Sato  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252e322d37SHiroki Sato  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262e322d37SHiroki Sato  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272e322d37SHiroki Sato  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282e322d37SHiroki Sato  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292e322d37SHiroki Sato  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302e322d37SHiroki Sato  * POSSIBILITY OF SUCH DAMAGE.
31dfdcada3SDoug Rabson  */
32dfdcada3SDoug Rabson /*
33dfdcada3SDoug Rabson  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
34dfdcada3SDoug Rabson  */
35dfdcada3SDoug Rabson 
36dfdcada3SDoug Rabson #include <sys/cdefs.h>
37dfdcada3SDoug Rabson /*
38dfdcada3SDoug Rabson  * rpc_generic.c, Miscl routines for RPC.
39dfdcada3SDoug Rabson  *
40dfdcada3SDoug Rabson  */
41dfdcada3SDoug Rabson 
42dfdcada3SDoug Rabson #include "opt_inet6.h"
43dfdcada3SDoug Rabson 
44dfdcada3SDoug Rabson #include <sys/param.h>
45fa9d9930SDoug Rabson #include <sys/kernel.h>
46dfdcada3SDoug Rabson #include <sys/malloc.h>
47a9148abdSDoug Rabson #include <sys/mbuf.h>
48fa9d9930SDoug Rabson #include <sys/module.h>
49dfdcada3SDoug Rabson #include <sys/proc.h>
50dfdcada3SDoug Rabson #include <sys/protosw.h>
51dfdcada3SDoug Rabson #include <sys/sbuf.h>
52dfdcada3SDoug Rabson #include <sys/systm.h>
53dfdcada3SDoug Rabson #include <sys/socket.h>
54dfdcada3SDoug Rabson #include <sys/socketvar.h>
55dfdcada3SDoug Rabson #include <sys/syslog.h>
56dfdcada3SDoug Rabson 
570348c661SMarko Zec #include <net/vnet.h>
580348c661SMarko Zec 
59dfdcada3SDoug Rabson #include <rpc/rpc.h>
60dfdcada3SDoug Rabson #include <rpc/nettype.h>
617e7fd7d1SRick Macklem #include <rpc/rpcsec_gss.h>
62ab0c29afSRick Macklem #include <rpc/rpcsec_tls.h>
63dfdcada3SDoug Rabson 
64ee31b83aSDoug Rabson #include <rpc/rpc_com.h>
65ab0c29afSRick Macklem #include <rpc/krpc.h>
66ab0c29afSRick Macklem 
67ab0c29afSRick Macklem #include <vm/vm.h>
68ab0c29afSRick Macklem #include <vm/pmap.h>
69ab0c29afSRick Macklem #include <vm/vm_param.h>
70ee31b83aSDoug Rabson 
71cec077bcSRick Macklem extern	u_long sb_max_adj;	/* not defined in socketvar.h */
72cec077bcSRick Macklem 
737e7fd7d1SRick Macklem /* Provide an entry point hook for the rpcsec_gss module. */
747e7fd7d1SRick Macklem struct rpc_gss_entries	rpc_gss_entries;
757e7fd7d1SRick Macklem 
76dfdcada3SDoug Rabson struct handle {
77dfdcada3SDoug Rabson 	NCONF_HANDLE *nhandle;
78dfdcada3SDoug Rabson 	int nflag;		/* Whether NETPATH or NETCONFIG */
79dfdcada3SDoug Rabson 	int nettype;
80dfdcada3SDoug Rabson };
81dfdcada3SDoug Rabson 
82dfdcada3SDoug Rabson static const struct _rpcnettype {
83dfdcada3SDoug Rabson 	const char *name;
84dfdcada3SDoug Rabson 	const int type;
85dfdcada3SDoug Rabson } _rpctypelist[] = {
86dfdcada3SDoug Rabson 	{ "netpath", _RPC_NETPATH },
87dfdcada3SDoug Rabson 	{ "visible", _RPC_VISIBLE },
88dfdcada3SDoug Rabson 	{ "circuit_v", _RPC_CIRCUIT_V },
89dfdcada3SDoug Rabson 	{ "datagram_v", _RPC_DATAGRAM_V },
90dfdcada3SDoug Rabson 	{ "circuit_n", _RPC_CIRCUIT_N },
91dfdcada3SDoug Rabson 	{ "datagram_n", _RPC_DATAGRAM_N },
92dfdcada3SDoug Rabson 	{ "tcp", _RPC_TCP },
93dfdcada3SDoug Rabson 	{ "udp", _RPC_UDP },
94dfdcada3SDoug Rabson 	{ 0, _RPC_NONE }
95dfdcada3SDoug Rabson };
96dfdcada3SDoug Rabson 
97dfdcada3SDoug Rabson struct netid_af {
98dfdcada3SDoug Rabson 	const char	*netid;
99dfdcada3SDoug Rabson 	int		af;
100dfdcada3SDoug Rabson 	int		protocol;
101dfdcada3SDoug Rabson };
102dfdcada3SDoug Rabson 
103dfdcada3SDoug Rabson static const struct netid_af na_cvt[] = {
104dfdcada3SDoug Rabson 	{ "udp",  AF_INET,  IPPROTO_UDP },
105dfdcada3SDoug Rabson 	{ "tcp",  AF_INET,  IPPROTO_TCP },
106dfdcada3SDoug Rabson #ifdef INET6
107dfdcada3SDoug Rabson 	{ "udp6", AF_INET6, IPPROTO_UDP },
108dfdcada3SDoug Rabson 	{ "tcp6", AF_INET6, IPPROTO_TCP },
109dfdcada3SDoug Rabson #endif
110dfdcada3SDoug Rabson 	{ "local", AF_LOCAL, 0 }
111dfdcada3SDoug Rabson };
112dfdcada3SDoug Rabson 
113dfdcada3SDoug Rabson struct rpc_createerr rpc_createerr;
114dfdcada3SDoug Rabson 
115dfdcada3SDoug Rabson /*
116dfdcada3SDoug Rabson  * Find the appropriate buffer size
117dfdcada3SDoug Rabson  */
118dfdcada3SDoug Rabson u_int
119dfdcada3SDoug Rabson /*ARGSUSED*/
__rpc_get_t_size(int af,int proto,int size)120dfdcada3SDoug Rabson __rpc_get_t_size(int af, int proto, int size)
121dfdcada3SDoug Rabson {
122cec077bcSRick Macklem 	int defsize;
123dfdcada3SDoug Rabson 
124dfdcada3SDoug Rabson 	switch (proto) {
125dfdcada3SDoug Rabson 	case IPPROTO_TCP:
126dfdcada3SDoug Rabson 		defsize = 64 * 1024;	/* XXX */
127dfdcada3SDoug Rabson 		break;
128dfdcada3SDoug Rabson 	case IPPROTO_UDP:
129dfdcada3SDoug Rabson 		defsize = UDPMSGSIZE;
130dfdcada3SDoug Rabson 		break;
131dfdcada3SDoug Rabson 	default:
132dfdcada3SDoug Rabson 		defsize = RPC_MAXDATASIZE;
133dfdcada3SDoug Rabson 		break;
134dfdcada3SDoug Rabson 	}
135dfdcada3SDoug Rabson 	if (size == 0)
136dfdcada3SDoug Rabson 		return defsize;
137dfdcada3SDoug Rabson 
138dfdcada3SDoug Rabson 	/* Check whether the value is within the upper max limit */
139cec077bcSRick Macklem 	return (size > sb_max_adj ? (u_int)sb_max_adj : (u_int)size);
140dfdcada3SDoug Rabson }
141dfdcada3SDoug Rabson 
142dfdcada3SDoug Rabson /*
143dfdcada3SDoug Rabson  * Find the appropriate address buffer size
144dfdcada3SDoug Rabson  */
145dfdcada3SDoug Rabson u_int
__rpc_get_a_size(int af)14671948c15SMateusz Guzik __rpc_get_a_size(int af)
147dfdcada3SDoug Rabson {
148dfdcada3SDoug Rabson 	switch (af) {
149dfdcada3SDoug Rabson 	case AF_INET:
150dfdcada3SDoug Rabson 		return sizeof (struct sockaddr_in);
151dfdcada3SDoug Rabson #ifdef INET6
152dfdcada3SDoug Rabson 	case AF_INET6:
153dfdcada3SDoug Rabson 		return sizeof (struct sockaddr_in6);
154dfdcada3SDoug Rabson #endif
155dfdcada3SDoug Rabson 	case AF_LOCAL:
156dfdcada3SDoug Rabson 		return sizeof (struct sockaddr_un);
157dfdcada3SDoug Rabson 	default:
158dfdcada3SDoug Rabson 		break;
159dfdcada3SDoug Rabson 	}
160dfdcada3SDoug Rabson 	return ((u_int)RPC_MAXADDRSIZE);
161dfdcada3SDoug Rabson }
162dfdcada3SDoug Rabson 
163dfdcada3SDoug Rabson #if 0
164dfdcada3SDoug Rabson 
165dfdcada3SDoug Rabson /*
166dfdcada3SDoug Rabson  * Used to ping the NULL procedure for clnt handle.
167dfdcada3SDoug Rabson  * Returns NULL if fails, else a non-NULL pointer.
168dfdcada3SDoug Rabson  */
169dfdcada3SDoug Rabson void *
170dfdcada3SDoug Rabson rpc_nullproc(clnt)
171dfdcada3SDoug Rabson 	CLIENT *clnt;
172dfdcada3SDoug Rabson {
173dfdcada3SDoug Rabson 	struct timeval TIMEOUT = {25, 0};
174dfdcada3SDoug Rabson 
175dfdcada3SDoug Rabson 	if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
176dfdcada3SDoug Rabson 		(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
177dfdcada3SDoug Rabson 		return (NULL);
178dfdcada3SDoug Rabson 	}
179dfdcada3SDoug Rabson 	return ((void *) clnt);
180dfdcada3SDoug Rabson }
181dfdcada3SDoug Rabson 
182dfdcada3SDoug Rabson #endif
183dfdcada3SDoug Rabson 
184dfdcada3SDoug Rabson int
__rpc_socket2sockinfo(struct socket * so,struct __rpc_sockinfo * sip)185dfdcada3SDoug Rabson __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip)
186dfdcada3SDoug Rabson {
187dfdcada3SDoug Rabson 	int type, proto;
1880fac350cSGleb Smirnoff 	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
189dfdcada3SDoug Rabson 	sa_family_t family;
190dfdcada3SDoug Rabson 	struct sockopt opt;
191dfdcada3SDoug Rabson 	int error;
192dfdcada3SDoug Rabson 
1930fac350cSGleb Smirnoff 	error = sosockaddr(so, (struct sockaddr *)&ss);
194dfdcada3SDoug Rabson 	if (error)
195dfdcada3SDoug Rabson 		return 0;
196dfdcada3SDoug Rabson 
1970fac350cSGleb Smirnoff 	sip->si_alen = ss.ss_len;
1980fac350cSGleb Smirnoff 	family = ss.ss_family;
199dfdcada3SDoug Rabson 
200dfdcada3SDoug Rabson 	opt.sopt_dir = SOPT_GET;
201dfdcada3SDoug Rabson 	opt.sopt_level = SOL_SOCKET;
202dfdcada3SDoug Rabson 	opt.sopt_name = SO_TYPE;
203dfdcada3SDoug Rabson 	opt.sopt_val = &type;
204dfdcada3SDoug Rabson 	opt.sopt_valsize = sizeof type;
205dfdcada3SDoug Rabson 	opt.sopt_td = NULL;
206dfdcada3SDoug Rabson 	error = sogetopt(so, &opt);
207dfdcada3SDoug Rabson 	if (error)
208dfdcada3SDoug Rabson 		return 0;
209dfdcada3SDoug Rabson 
210dfdcada3SDoug Rabson 	/* XXX */
211dfdcada3SDoug Rabson 	if (family != AF_LOCAL) {
212dfdcada3SDoug Rabson 		if (type == SOCK_STREAM)
213dfdcada3SDoug Rabson 			proto = IPPROTO_TCP;
214dfdcada3SDoug Rabson 		else if (type == SOCK_DGRAM)
215dfdcada3SDoug Rabson 			proto = IPPROTO_UDP;
216dfdcada3SDoug Rabson 		else
217dfdcada3SDoug Rabson 			return 0;
218dfdcada3SDoug Rabson 	} else
219dfdcada3SDoug Rabson 		proto = 0;
220dfdcada3SDoug Rabson 
221dfdcada3SDoug Rabson 	sip->si_af = family;
222dfdcada3SDoug Rabson 	sip->si_proto = proto;
223dfdcada3SDoug Rabson 	sip->si_socktype = type;
224dfdcada3SDoug Rabson 
225dfdcada3SDoug Rabson 	return 1;
226dfdcada3SDoug Rabson }
227dfdcada3SDoug Rabson 
228dfdcada3SDoug Rabson /*
229dfdcada3SDoug Rabson  * Linear search, but the number of entries is small.
230dfdcada3SDoug Rabson  */
231dfdcada3SDoug Rabson int
__rpc_nconf2sockinfo(const struct netconfig * nconf,struct __rpc_sockinfo * sip)232dfdcada3SDoug Rabson __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
233dfdcada3SDoug Rabson {
234dfdcada3SDoug Rabson 	int i;
235dfdcada3SDoug Rabson 
236dfdcada3SDoug Rabson 	for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
237dfdcada3SDoug Rabson 		if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
238dfdcada3SDoug Rabson 		    strcmp(nconf->nc_netid, "unix") == 0 &&
239dfdcada3SDoug Rabson 		    strcmp(na_cvt[i].netid, "local") == 0)) {
240dfdcada3SDoug Rabson 			sip->si_af = na_cvt[i].af;
241dfdcada3SDoug Rabson 			sip->si_proto = na_cvt[i].protocol;
242dfdcada3SDoug Rabson 			sip->si_socktype =
243dfdcada3SDoug Rabson 			    __rpc_seman2socktype((int)nconf->nc_semantics);
244dfdcada3SDoug Rabson 			if (sip->si_socktype == -1)
245dfdcada3SDoug Rabson 				return 0;
246dfdcada3SDoug Rabson 			sip->si_alen = __rpc_get_a_size(sip->si_af);
247dfdcada3SDoug Rabson 			return 1;
248dfdcada3SDoug Rabson 		}
249dfdcada3SDoug Rabson 
250dfdcada3SDoug Rabson 	return 0;
251dfdcada3SDoug Rabson }
252dfdcada3SDoug Rabson 
253dfdcada3SDoug Rabson struct socket *
__rpc_nconf2socket(const struct netconfig * nconf)254dfdcada3SDoug Rabson __rpc_nconf2socket(const struct netconfig *nconf)
255dfdcada3SDoug Rabson {
256dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
257dfdcada3SDoug Rabson 	struct socket *so;
258dfdcada3SDoug Rabson 	int error;
259dfdcada3SDoug Rabson 
260dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si))
261dfdcada3SDoug Rabson 		return 0;
262dfdcada3SDoug Rabson 
263dfdcada3SDoug Rabson 	so = NULL;
264dfdcada3SDoug Rabson 	error =  socreate(si.si_af, &so, si.si_socktype, si.si_proto,
265dfdcada3SDoug Rabson 	    curthread->td_ucred, curthread);
266dfdcada3SDoug Rabson 
267dfdcada3SDoug Rabson 	if (error)
268dfdcada3SDoug Rabson 		return NULL;
269dfdcada3SDoug Rabson 	else
270dfdcada3SDoug Rabson 		return so;
271dfdcada3SDoug Rabson }
272dfdcada3SDoug Rabson 
273dfdcada3SDoug Rabson char *
taddr2uaddr(const struct netconfig * nconf,const struct netbuf * nbuf)274dfdcada3SDoug Rabson taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
275dfdcada3SDoug Rabson {
276dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
277dfdcada3SDoug Rabson 
278dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si))
279dfdcada3SDoug Rabson 		return NULL;
280dfdcada3SDoug Rabson 	return __rpc_taddr2uaddr_af(si.si_af, nbuf);
281dfdcada3SDoug Rabson }
282dfdcada3SDoug Rabson 
283dfdcada3SDoug Rabson struct netbuf *
uaddr2taddr(const struct netconfig * nconf,const char * uaddr)284dfdcada3SDoug Rabson uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
285dfdcada3SDoug Rabson {
286dfdcada3SDoug Rabson 	struct __rpc_sockinfo si;
287dfdcada3SDoug Rabson 
288dfdcada3SDoug Rabson 	if (!__rpc_nconf2sockinfo(nconf, &si))
289dfdcada3SDoug Rabson 		return NULL;
290dfdcada3SDoug Rabson 	return __rpc_uaddr2taddr_af(si.si_af, uaddr);
291dfdcada3SDoug Rabson }
292dfdcada3SDoug Rabson 
293dfdcada3SDoug Rabson char *
__rpc_taddr2uaddr_af(int af,const struct netbuf * nbuf)294dfdcada3SDoug Rabson __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
295dfdcada3SDoug Rabson {
296dfdcada3SDoug Rabson 	char *ret;
297dfdcada3SDoug Rabson 	struct sbuf sb;
298dfdcada3SDoug Rabson 	struct sockaddr_in *sin;
299dfdcada3SDoug Rabson 	struct sockaddr_un *sun;
300dfdcada3SDoug Rabson 	char namebuf[INET_ADDRSTRLEN];
301dfdcada3SDoug Rabson #ifdef INET6
302dfdcada3SDoug Rabson 	struct sockaddr_in6 *sin6;
303dfdcada3SDoug Rabson 	char namebuf6[INET6_ADDRSTRLEN];
304dfdcada3SDoug Rabson #endif
305bcd0e31dSJohn Baldwin 	uint16_t port;
306dfdcada3SDoug Rabson 
307dfdcada3SDoug Rabson 	sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND);
308dfdcada3SDoug Rabson 
309dfdcada3SDoug Rabson 	switch (af) {
310dfdcada3SDoug Rabson 	case AF_INET:
3116448ec89SXin LI 		if (nbuf->len < sizeof(*sin))
3126448ec89SXin LI 			return NULL;
313dfdcada3SDoug Rabson 		sin = nbuf->buf;
314109c1de8SAttilio Rao 		if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
315dfdcada3SDoug Rabson 		    == NULL)
316dfdcada3SDoug Rabson 			return NULL;
317dfdcada3SDoug Rabson 		port = ntohs(sin->sin_port);
318dfdcada3SDoug Rabson 		if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
319dfdcada3SDoug Rabson 			((uint32_t)port) >> 8,
320dfdcada3SDoug Rabson 			port & 0xff) < 0)
321dfdcada3SDoug Rabson 			return NULL;
322dfdcada3SDoug Rabson 		break;
323dfdcada3SDoug Rabson #ifdef INET6
324dfdcada3SDoug Rabson 	case AF_INET6:
3256448ec89SXin LI 		if (nbuf->len < sizeof(*sin6))
3266448ec89SXin LI 			return NULL;
327dfdcada3SDoug Rabson 		sin6 = nbuf->buf;
328109c1de8SAttilio Rao 		if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
329dfdcada3SDoug Rabson 		    == NULL)
330dfdcada3SDoug Rabson 			return NULL;
331dfdcada3SDoug Rabson 		port = ntohs(sin6->sin6_port);
332dfdcada3SDoug Rabson 		if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
333dfdcada3SDoug Rabson 			((uint32_t)port) >> 8,
334dfdcada3SDoug Rabson 			port & 0xff) < 0)
335dfdcada3SDoug Rabson 			return NULL;
336dfdcada3SDoug Rabson 		break;
337dfdcada3SDoug Rabson #endif
338dfdcada3SDoug Rabson 	case AF_LOCAL:
339dfdcada3SDoug Rabson 		sun = nbuf->buf;
340dfdcada3SDoug Rabson 		if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
341dfdcada3SDoug Rabson 			    offsetof(struct sockaddr_un, sun_path)),
342dfdcada3SDoug Rabson 			sun->sun_path) < 0)
343dfdcada3SDoug Rabson 			return (NULL);
344dfdcada3SDoug Rabson 		break;
345dfdcada3SDoug Rabson 	default:
346dfdcada3SDoug Rabson 		return NULL;
347dfdcada3SDoug Rabson 	}
348dfdcada3SDoug Rabson 
349dfdcada3SDoug Rabson 	sbuf_finish(&sb);
350dfdcada3SDoug Rabson 	ret = strdup(sbuf_data(&sb), M_RPC);
351dfdcada3SDoug Rabson 	sbuf_delete(&sb);
352dfdcada3SDoug Rabson 
353dfdcada3SDoug Rabson 	return ret;
354dfdcada3SDoug Rabson }
355dfdcada3SDoug Rabson 
356dfdcada3SDoug Rabson struct netbuf *
__rpc_uaddr2taddr_af(int af,const char * uaddr)357dfdcada3SDoug Rabson __rpc_uaddr2taddr_af(int af, const char *uaddr)
358dfdcada3SDoug Rabson {
359dfdcada3SDoug Rabson 	struct netbuf *ret = NULL;
360dfdcada3SDoug Rabson 	char *addrstr, *p;
361dfdcada3SDoug Rabson 	unsigned port, portlo, porthi;
362dfdcada3SDoug Rabson 	struct sockaddr_in *sin;
363dfdcada3SDoug Rabson #ifdef INET6
364dfdcada3SDoug Rabson 	struct sockaddr_in6 *sin6;
365dfdcada3SDoug Rabson #endif
366dfdcada3SDoug Rabson 	struct sockaddr_un *sun;
367dfdcada3SDoug Rabson 
368dfdcada3SDoug Rabson 	port = 0;
369dfdcada3SDoug Rabson 	sin = NULL;
3706448ec89SXin LI 
3716448ec89SXin LI 	if (uaddr == NULL)
3726448ec89SXin LI 		return NULL;
3736448ec89SXin LI 
374dfdcada3SDoug Rabson 	addrstr = strdup(uaddr, M_RPC);
375dfdcada3SDoug Rabson 	if (addrstr == NULL)
376dfdcada3SDoug Rabson 		return NULL;
377dfdcada3SDoug Rabson 
378dfdcada3SDoug Rabson 	/*
379dfdcada3SDoug Rabson 	 * AF_LOCAL addresses are expected to be absolute
380dfdcada3SDoug Rabson 	 * pathnames, anything else will be AF_INET or AF_INET6.
381dfdcada3SDoug Rabson 	 */
382dfdcada3SDoug Rabson 	if (*addrstr != '/') {
383dfdcada3SDoug Rabson 		p = strrchr(addrstr, '.');
384dfdcada3SDoug Rabson 		if (p == NULL)
385dfdcada3SDoug Rabson 			goto out;
386dfdcada3SDoug Rabson 		portlo = (unsigned)strtol(p + 1, NULL, 10);
387dfdcada3SDoug Rabson 		*p = '\0';
388dfdcada3SDoug Rabson 
389dfdcada3SDoug Rabson 		p = strrchr(addrstr, '.');
390dfdcada3SDoug Rabson 		if (p == NULL)
391dfdcada3SDoug Rabson 			goto out;
392dfdcada3SDoug Rabson 		porthi = (unsigned)strtol(p + 1, NULL, 10);
393dfdcada3SDoug Rabson 		*p = '\0';
394dfdcada3SDoug Rabson 		port = (porthi << 8) | portlo;
395dfdcada3SDoug Rabson 	}
396dfdcada3SDoug Rabson 
397dfdcada3SDoug Rabson 	ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
398dfdcada3SDoug Rabson 
399dfdcada3SDoug Rabson 	switch (af) {
400dfdcada3SDoug Rabson 	case AF_INET:
401dfdcada3SDoug Rabson 		sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
402dfdcada3SDoug Rabson 		    M_WAITOK);
403dfdcada3SDoug Rabson 		memset(sin, 0, sizeof *sin);
404dfdcada3SDoug Rabson 		sin->sin_family = AF_INET;
405dfdcada3SDoug Rabson 		sin->sin_port = htons(port);
406109c1de8SAttilio Rao 		if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
407dfdcada3SDoug Rabson 			free(sin, M_RPC);
408dfdcada3SDoug Rabson 			free(ret, M_RPC);
409dfdcada3SDoug Rabson 			ret = NULL;
410dfdcada3SDoug Rabson 			goto out;
411dfdcada3SDoug Rabson 		}
412dfdcada3SDoug Rabson 		sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
413dfdcada3SDoug Rabson 		ret->buf = sin;
414dfdcada3SDoug Rabson 		break;
415dfdcada3SDoug Rabson #ifdef INET6
416dfdcada3SDoug Rabson 	case AF_INET6:
417dfdcada3SDoug Rabson 		sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
418dfdcada3SDoug Rabson 		    M_WAITOK);
419dfdcada3SDoug Rabson 		memset(sin6, 0, sizeof *sin6);
420dfdcada3SDoug Rabson 		sin6->sin6_family = AF_INET6;
421dfdcada3SDoug Rabson 		sin6->sin6_port = htons(port);
422109c1de8SAttilio Rao 		if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
423dfdcada3SDoug Rabson 			free(sin6, M_RPC);
424dfdcada3SDoug Rabson 			free(ret, M_RPC);
425dfdcada3SDoug Rabson 			ret = NULL;
426dfdcada3SDoug Rabson 			goto out;
427dfdcada3SDoug Rabson 		}
428dfdcada3SDoug Rabson 		sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
429dfdcada3SDoug Rabson 		ret->buf = sin6;
430dfdcada3SDoug Rabson 		break;
431dfdcada3SDoug Rabson #endif
432dfdcada3SDoug Rabson 	case AF_LOCAL:
433dfdcada3SDoug Rabson 		sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
434dfdcada3SDoug Rabson 		    M_WAITOK);
435dfdcada3SDoug Rabson 		memset(sun, 0, sizeof *sun);
436dfdcada3SDoug Rabson 		sun->sun_family = AF_LOCAL;
437dfdcada3SDoug Rabson 		strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
438dfdcada3SDoug Rabson 		ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
439dfdcada3SDoug Rabson 		ret->buf = sun;
440dfdcada3SDoug Rabson 		break;
441dfdcada3SDoug Rabson 	default:
442dfdcada3SDoug Rabson 		break;
443dfdcada3SDoug Rabson 	}
444dfdcada3SDoug Rabson out:
445dfdcada3SDoug Rabson 	free(addrstr, M_RPC);
446dfdcada3SDoug Rabson 	return ret;
447dfdcada3SDoug Rabson }
448dfdcada3SDoug Rabson 
449dfdcada3SDoug Rabson int
__rpc_seman2socktype(int semantics)450dfdcada3SDoug Rabson __rpc_seman2socktype(int semantics)
451dfdcada3SDoug Rabson {
452dfdcada3SDoug Rabson 	switch (semantics) {
453dfdcada3SDoug Rabson 	case NC_TPI_CLTS:
454dfdcada3SDoug Rabson 		return SOCK_DGRAM;
455dfdcada3SDoug Rabson 	case NC_TPI_COTS_ORD:
456dfdcada3SDoug Rabson 		return SOCK_STREAM;
457dfdcada3SDoug Rabson 	case NC_TPI_RAW:
458dfdcada3SDoug Rabson 		return SOCK_RAW;
459dfdcada3SDoug Rabson 	default:
460dfdcada3SDoug Rabson 		break;
461dfdcada3SDoug Rabson 	}
462dfdcada3SDoug Rabson 
463dfdcada3SDoug Rabson 	return -1;
464dfdcada3SDoug Rabson }
465dfdcada3SDoug Rabson 
466dfdcada3SDoug Rabson int
__rpc_socktype2seman(int socktype)467dfdcada3SDoug Rabson __rpc_socktype2seman(int socktype)
468dfdcada3SDoug Rabson {
469dfdcada3SDoug Rabson 	switch (socktype) {
470dfdcada3SDoug Rabson 	case SOCK_DGRAM:
471dfdcada3SDoug Rabson 		return NC_TPI_CLTS;
472dfdcada3SDoug Rabson 	case SOCK_STREAM:
473dfdcada3SDoug Rabson 		return NC_TPI_COTS_ORD;
474dfdcada3SDoug Rabson 	case SOCK_RAW:
475dfdcada3SDoug Rabson 		return NC_TPI_RAW;
476dfdcada3SDoug Rabson 	default:
477dfdcada3SDoug Rabson 		break;
478dfdcada3SDoug Rabson 	}
479dfdcada3SDoug Rabson 
480dfdcada3SDoug Rabson 	return -1;
481dfdcada3SDoug Rabson }
482dfdcada3SDoug Rabson 
483dfdcada3SDoug Rabson /*
484dfdcada3SDoug Rabson  * Returns the type of the network as defined in <rpc/nettype.h>
485dfdcada3SDoug Rabson  * If nettype is NULL, it defaults to NETPATH.
486dfdcada3SDoug Rabson  */
487dfdcada3SDoug Rabson static int
getnettype(const char * nettype)488dfdcada3SDoug Rabson getnettype(const char *nettype)
489dfdcada3SDoug Rabson {
490dfdcada3SDoug Rabson 	int i;
491dfdcada3SDoug Rabson 
492dfdcada3SDoug Rabson 	if ((nettype == NULL) || (nettype[0] == 0)) {
493dfdcada3SDoug Rabson 		return (_RPC_NETPATH);	/* Default */
494dfdcada3SDoug Rabson 	}
495dfdcada3SDoug Rabson 
496dfdcada3SDoug Rabson #if 0
497dfdcada3SDoug Rabson 	nettype = strlocase(nettype);
498dfdcada3SDoug Rabson #endif
499dfdcada3SDoug Rabson 	for (i = 0; _rpctypelist[i].name; i++)
500dfdcada3SDoug Rabson 		if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
501dfdcada3SDoug Rabson 			return (_rpctypelist[i].type);
502dfdcada3SDoug Rabson 		}
503dfdcada3SDoug Rabson 	return (_rpctypelist[i].type);
504dfdcada3SDoug Rabson }
505dfdcada3SDoug Rabson 
506dfdcada3SDoug Rabson /*
507dfdcada3SDoug Rabson  * For the given nettype (tcp or udp only), return the first structure found.
508dfdcada3SDoug Rabson  * This should be freed by calling freenetconfigent()
509dfdcada3SDoug Rabson  */
510dfdcada3SDoug Rabson struct netconfig *
__rpc_getconfip(const char * nettype)511dfdcada3SDoug Rabson __rpc_getconfip(const char *nettype)
512dfdcada3SDoug Rabson {
513dfdcada3SDoug Rabson 	char *netid;
514dfdcada3SDoug Rabson 	static char *netid_tcp = (char *) NULL;
515dfdcada3SDoug Rabson 	static char *netid_udp = (char *) NULL;
516dfdcada3SDoug Rabson 	struct netconfig *dummy;
517dfdcada3SDoug Rabson 
518dfdcada3SDoug Rabson 	if (!netid_udp && !netid_tcp) {
519dfdcada3SDoug Rabson 		struct netconfig *nconf;
520dfdcada3SDoug Rabson 		void *confighandle;
521dfdcada3SDoug Rabson 
522dfdcada3SDoug Rabson 		if (!(confighandle = setnetconfig())) {
523dfdcada3SDoug Rabson 			log(LOG_ERR, "rpc: failed to open " NETCONFIG);
524dfdcada3SDoug Rabson 			return (NULL);
525dfdcada3SDoug Rabson 		}
526dfdcada3SDoug Rabson 		while ((nconf = getnetconfig(confighandle)) != NULL) {
527dfdcada3SDoug Rabson 			if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
528dfdcada3SDoug Rabson 				if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
529dfdcada3SDoug Rabson 					netid_tcp = strdup(nconf->nc_netid,
530dfdcada3SDoug Rabson 					    M_RPC);
531dfdcada3SDoug Rabson 				} else
532dfdcada3SDoug Rabson 				if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
533dfdcada3SDoug Rabson 					netid_udp = strdup(nconf->nc_netid,
534dfdcada3SDoug Rabson 					    M_RPC);
535dfdcada3SDoug Rabson 				}
536dfdcada3SDoug Rabson 			}
537dfdcada3SDoug Rabson 		}
538dfdcada3SDoug Rabson 		endnetconfig(confighandle);
539dfdcada3SDoug Rabson 	}
540dfdcada3SDoug Rabson 	if (strcmp(nettype, "udp") == 0)
541dfdcada3SDoug Rabson 		netid = netid_udp;
542dfdcada3SDoug Rabson 	else if (strcmp(nettype, "tcp") == 0)
543dfdcada3SDoug Rabson 		netid = netid_tcp;
544dfdcada3SDoug Rabson 	else {
545dfdcada3SDoug Rabson 		return (NULL);
546dfdcada3SDoug Rabson 	}
547dfdcada3SDoug Rabson 	if ((netid == NULL) || (netid[0] == 0)) {
548dfdcada3SDoug Rabson 		return (NULL);
549dfdcada3SDoug Rabson 	}
550dfdcada3SDoug Rabson 	dummy = getnetconfigent(netid);
551dfdcada3SDoug Rabson 	return (dummy);
552dfdcada3SDoug Rabson }
553dfdcada3SDoug Rabson 
554dfdcada3SDoug Rabson /*
555dfdcada3SDoug Rabson  * Returns the type of the nettype, which should then be used with
556dfdcada3SDoug Rabson  * __rpc_getconf().
557dfdcada3SDoug Rabson  *
558dfdcada3SDoug Rabson  * For simplicity in the kernel, we don't support the NETPATH
559dfdcada3SDoug Rabson  * environment variable. We behave as userland would then NETPATH is
560dfdcada3SDoug Rabson  * unset, i.e. iterate over all visible entries in netconfig.
561dfdcada3SDoug Rabson  */
562dfdcada3SDoug Rabson void *
__rpc_setconf(const char * nettype)56371948c15SMateusz Guzik __rpc_setconf(const char *nettype)
564dfdcada3SDoug Rabson {
565dfdcada3SDoug Rabson 	struct handle *handle;
566dfdcada3SDoug Rabson 
567dfdcada3SDoug Rabson 	handle = (struct handle *) malloc(sizeof (struct handle),
568dfdcada3SDoug Rabson 	    M_RPC, M_WAITOK);
569dfdcada3SDoug Rabson 	switch (handle->nettype = getnettype(nettype)) {
570dfdcada3SDoug Rabson 	case _RPC_NETPATH:
571dfdcada3SDoug Rabson 	case _RPC_CIRCUIT_N:
572dfdcada3SDoug Rabson 	case _RPC_DATAGRAM_N:
573dfdcada3SDoug Rabson 		if (!(handle->nhandle = setnetconfig()))
574dfdcada3SDoug Rabson 			goto failed;
575dfdcada3SDoug Rabson 		handle->nflag = TRUE;
576dfdcada3SDoug Rabson 		break;
577dfdcada3SDoug Rabson 	case _RPC_VISIBLE:
578dfdcada3SDoug Rabson 	case _RPC_CIRCUIT_V:
579dfdcada3SDoug Rabson 	case _RPC_DATAGRAM_V:
580dfdcada3SDoug Rabson 	case _RPC_TCP:
581dfdcada3SDoug Rabson 	case _RPC_UDP:
582dfdcada3SDoug Rabson 		if (!(handle->nhandle = setnetconfig())) {
583dfdcada3SDoug Rabson 		        log(LOG_ERR, "rpc: failed to open " NETCONFIG);
584dfdcada3SDoug Rabson 			goto failed;
585dfdcada3SDoug Rabson 		}
586dfdcada3SDoug Rabson 		handle->nflag = FALSE;
587dfdcada3SDoug Rabson 		break;
588dfdcada3SDoug Rabson 	default:
589dfdcada3SDoug Rabson 		goto failed;
590dfdcada3SDoug Rabson 	}
591dfdcada3SDoug Rabson 
592dfdcada3SDoug Rabson 	return (handle);
593dfdcada3SDoug Rabson 
594dfdcada3SDoug Rabson failed:
595dfdcada3SDoug Rabson 	free(handle, M_RPC);
596dfdcada3SDoug Rabson 	return (NULL);
597dfdcada3SDoug Rabson }
598dfdcada3SDoug Rabson 
599dfdcada3SDoug Rabson /*
600dfdcada3SDoug Rabson  * Returns the next netconfig struct for the given "net" type.
601dfdcada3SDoug Rabson  * __rpc_setconf() should have been called previously.
602dfdcada3SDoug Rabson  */
603dfdcada3SDoug Rabson struct netconfig *
__rpc_getconf(void * vhandle)604dfdcada3SDoug Rabson __rpc_getconf(void *vhandle)
605dfdcada3SDoug Rabson {
606dfdcada3SDoug Rabson 	struct handle *handle;
607dfdcada3SDoug Rabson 	struct netconfig *nconf;
608dfdcada3SDoug Rabson 
609dfdcada3SDoug Rabson 	handle = (struct handle *)vhandle;
610dfdcada3SDoug Rabson 	if (handle == NULL) {
611dfdcada3SDoug Rabson 		return (NULL);
612dfdcada3SDoug Rabson 	}
613dfdcada3SDoug Rabson 	for (;;) {
614dfdcada3SDoug Rabson 		if (handle->nflag) {
615dfdcada3SDoug Rabson 			nconf = getnetconfig(handle->nhandle);
616dfdcada3SDoug Rabson 			if (nconf && !(nconf->nc_flag & NC_VISIBLE))
617dfdcada3SDoug Rabson 				continue;
618dfdcada3SDoug Rabson 		} else {
619dfdcada3SDoug Rabson 			nconf = getnetconfig(handle->nhandle);
620dfdcada3SDoug Rabson 		}
621dfdcada3SDoug Rabson 		if (nconf == NULL)
622dfdcada3SDoug Rabson 			break;
623dfdcada3SDoug Rabson 		if ((nconf->nc_semantics != NC_TPI_CLTS) &&
624dfdcada3SDoug Rabson 			(nconf->nc_semantics != NC_TPI_COTS) &&
625dfdcada3SDoug Rabson 			(nconf->nc_semantics != NC_TPI_COTS_ORD))
626dfdcada3SDoug Rabson 			continue;
627dfdcada3SDoug Rabson 		switch (handle->nettype) {
628dfdcada3SDoug Rabson 		case _RPC_VISIBLE:
629dfdcada3SDoug Rabson 			if (!(nconf->nc_flag & NC_VISIBLE))
630dfdcada3SDoug Rabson 				continue;
631dfdcada3SDoug Rabson 			/* FALLTHROUGH */
632dfdcada3SDoug Rabson 		case _RPC_NETPATH:	/* Be happy */
633dfdcada3SDoug Rabson 			break;
634dfdcada3SDoug Rabson 		case _RPC_CIRCUIT_V:
635dfdcada3SDoug Rabson 			if (!(nconf->nc_flag & NC_VISIBLE))
636dfdcada3SDoug Rabson 				continue;
637dfdcada3SDoug Rabson 			/* FALLTHROUGH */
638dfdcada3SDoug Rabson 		case _RPC_CIRCUIT_N:
639dfdcada3SDoug Rabson 			if ((nconf->nc_semantics != NC_TPI_COTS) &&
640dfdcada3SDoug Rabson 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
641dfdcada3SDoug Rabson 				continue;
642dfdcada3SDoug Rabson 			break;
643dfdcada3SDoug Rabson 		case _RPC_DATAGRAM_V:
644dfdcada3SDoug Rabson 			if (!(nconf->nc_flag & NC_VISIBLE))
645dfdcada3SDoug Rabson 				continue;
646dfdcada3SDoug Rabson 			/* FALLTHROUGH */
647dfdcada3SDoug Rabson 		case _RPC_DATAGRAM_N:
648dfdcada3SDoug Rabson 			if (nconf->nc_semantics != NC_TPI_CLTS)
649dfdcada3SDoug Rabson 				continue;
650dfdcada3SDoug Rabson 			break;
651dfdcada3SDoug Rabson 		case _RPC_TCP:
652dfdcada3SDoug Rabson 			if (((nconf->nc_semantics != NC_TPI_COTS) &&
653dfdcada3SDoug Rabson 				(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
654dfdcada3SDoug Rabson 				(strcmp(nconf->nc_protofmly, NC_INET)
655dfdcada3SDoug Rabson #ifdef INET6
656dfdcada3SDoug Rabson 				 && strcmp(nconf->nc_protofmly, NC_INET6))
657dfdcada3SDoug Rabson #else
658dfdcada3SDoug Rabson 				)
659dfdcada3SDoug Rabson #endif
660dfdcada3SDoug Rabson 				||
661dfdcada3SDoug Rabson 				strcmp(nconf->nc_proto, NC_TCP))
662dfdcada3SDoug Rabson 				continue;
663dfdcada3SDoug Rabson 			break;
664dfdcada3SDoug Rabson 		case _RPC_UDP:
665dfdcada3SDoug Rabson 			if ((nconf->nc_semantics != NC_TPI_CLTS) ||
666dfdcada3SDoug Rabson 				(strcmp(nconf->nc_protofmly, NC_INET)
667dfdcada3SDoug Rabson #ifdef INET6
668dfdcada3SDoug Rabson 				&& strcmp(nconf->nc_protofmly, NC_INET6))
669dfdcada3SDoug Rabson #else
670dfdcada3SDoug Rabson 				)
671dfdcada3SDoug Rabson #endif
672dfdcada3SDoug Rabson 				||
673dfdcada3SDoug Rabson 				strcmp(nconf->nc_proto, NC_UDP))
674dfdcada3SDoug Rabson 				continue;
675dfdcada3SDoug Rabson 			break;
676dfdcada3SDoug Rabson 		}
677dfdcada3SDoug Rabson 		break;
678dfdcada3SDoug Rabson 	}
679dfdcada3SDoug Rabson 	return (nconf);
680dfdcada3SDoug Rabson }
681dfdcada3SDoug Rabson 
682dfdcada3SDoug Rabson void
__rpc_endconf(void * vhandle)68371948c15SMateusz Guzik __rpc_endconf(void *vhandle)
684dfdcada3SDoug Rabson {
685dfdcada3SDoug Rabson 	struct handle *handle;
686dfdcada3SDoug Rabson 
687dfdcada3SDoug Rabson 	handle = (struct handle *) vhandle;
688dfdcada3SDoug Rabson 	if (handle == NULL) {
689dfdcada3SDoug Rabson 		return;
690dfdcada3SDoug Rabson 	}
691dfdcada3SDoug Rabson 	endnetconfig(handle->nhandle);
692dfdcada3SDoug Rabson 	free(handle, M_RPC);
693dfdcada3SDoug Rabson }
694dfdcada3SDoug Rabson 
695dfdcada3SDoug Rabson int
__rpc_sockisbound(struct socket * so)696dfdcada3SDoug Rabson __rpc_sockisbound(struct socket *so)
697dfdcada3SDoug Rabson {
6980fac350cSGleb Smirnoff 	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
699dfdcada3SDoug Rabson 	int error, bound;
700dfdcada3SDoug Rabson 
7010fac350cSGleb Smirnoff 	error = sosockaddr(so, (struct sockaddr *)&ss);
702dfdcada3SDoug Rabson 	if (error)
703dfdcada3SDoug Rabson 		return (0);
704dfdcada3SDoug Rabson 
7050fac350cSGleb Smirnoff 	switch (ss.ss_family) {
706dfdcada3SDoug Rabson 		case AF_INET:
7070fac350cSGleb Smirnoff 			bound = (((struct sockaddr_in *)&ss)->sin_port != 0);
708dfdcada3SDoug Rabson 			break;
709dfdcada3SDoug Rabson #ifdef INET6
710dfdcada3SDoug Rabson 		case AF_INET6:
7110fac350cSGleb Smirnoff 			bound = (((struct sockaddr_in6 *)&ss)->sin6_port != 0);
712dfdcada3SDoug Rabson 			break;
713dfdcada3SDoug Rabson #endif
714dfdcada3SDoug Rabson 		case AF_LOCAL:
715dfdcada3SDoug Rabson 			/* XXX check this */
7160fac350cSGleb Smirnoff 			bound = (((struct sockaddr_un *)&ss)->sun_path[0] != '\0');
717dfdcada3SDoug Rabson 			break;
718dfdcada3SDoug Rabson 		default:
719dfdcada3SDoug Rabson 			bound = FALSE;
720dfdcada3SDoug Rabson 			break;
721dfdcada3SDoug Rabson 	}
722dfdcada3SDoug Rabson 
723dfdcada3SDoug Rabson 	return bound;
724dfdcada3SDoug Rabson }
725fa9d9930SDoug Rabson 
726fa9d9930SDoug Rabson /*
727a9148abdSDoug Rabson  * Implement XDR-style API for RPC call.
728a9148abdSDoug Rabson  */
729a9148abdSDoug Rabson enum clnt_stat
clnt_call_private(CLIENT * cl,struct rpc_callextra * ext,rpcproc_t proc,xdrproc_t xargs,void * argsp,xdrproc_t xresults,void * resultsp,struct timeval utimeout)730a9148abdSDoug Rabson clnt_call_private(
731a9148abdSDoug Rabson 	CLIENT		*cl,		/* client handle */
732a9148abdSDoug Rabson 	struct rpc_callextra *ext,	/* call metadata */
733a9148abdSDoug Rabson 	rpcproc_t	proc,		/* procedure number */
734a9148abdSDoug Rabson 	xdrproc_t	xargs,		/* xdr routine for args */
735a9148abdSDoug Rabson 	void		*argsp,		/* pointer to args */
736a9148abdSDoug Rabson 	xdrproc_t	xresults,	/* xdr routine for results */
737a9148abdSDoug Rabson 	void		*resultsp,	/* pointer to results */
738a9148abdSDoug Rabson 	struct timeval	utimeout)	/* seconds to wait before giving up */
739a9148abdSDoug Rabson {
740a9148abdSDoug Rabson 	XDR xdrs;
741a9148abdSDoug Rabson 	struct mbuf *mreq;
742a9148abdSDoug Rabson 	struct mbuf *mrep;
743a9148abdSDoug Rabson 	enum clnt_stat stat;
744a9148abdSDoug Rabson 
745bd54830bSGleb Smirnoff 	mreq = m_getcl(M_WAITOK, MT_DATA, 0);
746a9148abdSDoug Rabson 
747a9148abdSDoug Rabson 	xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
748a9148abdSDoug Rabson 	if (!xargs(&xdrs, argsp)) {
749a9148abdSDoug Rabson 		m_freem(mreq);
750a9148abdSDoug Rabson 		return (RPC_CANTENCODEARGS);
751a9148abdSDoug Rabson 	}
752a9148abdSDoug Rabson 	XDR_DESTROY(&xdrs);
753a9148abdSDoug Rabson 
754a9148abdSDoug Rabson 	stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout);
755a9148abdSDoug Rabson 	m_freem(mreq);
756a9148abdSDoug Rabson 
757a9148abdSDoug Rabson 	if (stat == RPC_SUCCESS) {
758a9148abdSDoug Rabson 		xdrmbuf_create(&xdrs, mrep, XDR_DECODE);
759a9148abdSDoug Rabson 		if (!xresults(&xdrs, resultsp)) {
760a9148abdSDoug Rabson 			XDR_DESTROY(&xdrs);
761a9148abdSDoug Rabson 			return (RPC_CANTDECODERES);
762a9148abdSDoug Rabson 		}
763a9148abdSDoug Rabson 		XDR_DESTROY(&xdrs);
764a9148abdSDoug Rabson 	}
765a9148abdSDoug Rabson 
766a9148abdSDoug Rabson 	return (stat);
767a9148abdSDoug Rabson }
768a9148abdSDoug Rabson 
769a9148abdSDoug Rabson /*
770a9148abdSDoug Rabson  * Bind a socket to a privileged IP port
771a9148abdSDoug Rabson  */
772a9148abdSDoug Rabson int
bindresvport(struct socket * so,struct sockaddr * sa)773a9148abdSDoug Rabson bindresvport(struct socket *so, struct sockaddr *sa)
774a9148abdSDoug Rabson {
7750fac350cSGleb Smirnoff 	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
776a9148abdSDoug Rabson 	int old, error, af;
777a9148abdSDoug Rabson 	struct sockaddr_in *sin;
778a9148abdSDoug Rabson #ifdef INET6
779a9148abdSDoug Rabson 	struct sockaddr_in6 *sin6;
780a9148abdSDoug Rabson #endif
781a9148abdSDoug Rabson 	struct sockopt opt;
782a9148abdSDoug Rabson 	int proto, portrange, portlow;
783bcd0e31dSJohn Baldwin 	uint16_t *portp;
784a9148abdSDoug Rabson 	socklen_t salen;
785a9148abdSDoug Rabson 
786a9148abdSDoug Rabson 	if (sa == NULL) {
7870fac350cSGleb Smirnoff 		sa = (struct sockaddr *)&ss;
7880fac350cSGleb Smirnoff 		error = sosockaddr(so, sa);
789a9148abdSDoug Rabson 		if (error)
790a9148abdSDoug Rabson 			return (error);
791a9148abdSDoug Rabson 		af = sa->sa_family;
792a9148abdSDoug Rabson 		salen = sa->sa_len;
793a9148abdSDoug Rabson 		memset(sa, 0, sa->sa_len);
794a9148abdSDoug Rabson 	} else {
795a9148abdSDoug Rabson 		af = sa->sa_family;
796a9148abdSDoug Rabson 		salen = sa->sa_len;
797a9148abdSDoug Rabson 	}
798a9148abdSDoug Rabson 
799a9148abdSDoug Rabson 	switch (af) {
800a9148abdSDoug Rabson 	case AF_INET:
801a9148abdSDoug Rabson 		proto = IPPROTO_IP;
802a9148abdSDoug Rabson 		portrange = IP_PORTRANGE;
803a9148abdSDoug Rabson 		portlow = IP_PORTRANGE_LOW;
804a9148abdSDoug Rabson 		sin = (struct sockaddr_in *)sa;
805a9148abdSDoug Rabson 		portp = &sin->sin_port;
806a9148abdSDoug Rabson 		break;
807a9148abdSDoug Rabson #ifdef INET6
808a9148abdSDoug Rabson 	case AF_INET6:
809a9148abdSDoug Rabson 		proto = IPPROTO_IPV6;
810a9148abdSDoug Rabson 		portrange = IPV6_PORTRANGE;
811a9148abdSDoug Rabson 		portlow = IPV6_PORTRANGE_LOW;
812a9148abdSDoug Rabson 		sin6 = (struct sockaddr_in6 *)sa;
813a9148abdSDoug Rabson 		portp = &sin6->sin6_port;
814a9148abdSDoug Rabson 		break;
815a9148abdSDoug Rabson #endif
816a9148abdSDoug Rabson 	default:
817a9148abdSDoug Rabson 		return (EPFNOSUPPORT);
818a9148abdSDoug Rabson 	}
819a9148abdSDoug Rabson 
820a9148abdSDoug Rabson 	sa->sa_family = af;
821a9148abdSDoug Rabson 	sa->sa_len = salen;
822a9148abdSDoug Rabson 
823a9148abdSDoug Rabson 	if (*portp == 0) {
824a9148abdSDoug Rabson 		bzero(&opt, sizeof(opt));
825a9148abdSDoug Rabson 		opt.sopt_dir = SOPT_GET;
826a9148abdSDoug Rabson 		opt.sopt_level = proto;
827a9148abdSDoug Rabson 		opt.sopt_name = portrange;
828a9148abdSDoug Rabson 		opt.sopt_val = &old;
829a9148abdSDoug Rabson 		opt.sopt_valsize = sizeof(old);
830a9148abdSDoug Rabson 		error = sogetopt(so, &opt);
8310fac350cSGleb Smirnoff 		if (error)
8320fac350cSGleb Smirnoff 			return (error);
833a9148abdSDoug Rabson 
834a9148abdSDoug Rabson 		opt.sopt_dir = SOPT_SET;
835a9148abdSDoug Rabson 		opt.sopt_val = &portlow;
836a9148abdSDoug Rabson 		error = sosetopt(so, &opt);
837a9148abdSDoug Rabson 		if (error)
8380fac350cSGleb Smirnoff 			return (error);
839a9148abdSDoug Rabson 	}
840a9148abdSDoug Rabson 
841a9148abdSDoug Rabson 	error = sobind(so, sa, curthread);
842a9148abdSDoug Rabson 
843a9148abdSDoug Rabson 	if (*portp == 0) {
844a9148abdSDoug Rabson 		if (error) {
845a9148abdSDoug Rabson 			opt.sopt_dir = SOPT_SET;
846a9148abdSDoug Rabson 			opt.sopt_val = &old;
847a9148abdSDoug Rabson 			sosetopt(so, &opt);
848a9148abdSDoug Rabson 		}
849a9148abdSDoug Rabson 	}
850a9148abdSDoug Rabson 
851a9148abdSDoug Rabson 	return (error);
852a9148abdSDoug Rabson }
853a9148abdSDoug Rabson 
854a9148abdSDoug Rabson /*
855ab0c29afSRick Macklem  * Make sure an mbuf list is made up entirely of ext_pgs mbufs.
856ab0c29afSRick Macklem  * This is needed for sosend() when KERN_TLS is being used.
857ab0c29afSRick Macklem  * (There might also be a performance improvement for certain
858ab0c29afSRick Macklem  *  network interfaces that handle ext_pgs mbufs efficiently.)
859ab0c29afSRick Macklem  * It expects at least one non-ext_pgs mbuf followed by zero
860ab0c29afSRick Macklem  * or more ext_pgs mbufs.  It does not handle the case where
861ab0c29afSRick Macklem  * non-ext_pgs mbuf(s) follow ext_pgs ones.
862ab0c29afSRick Macklem  * It also performs sanity checks on the resultant list.
863ab0c29afSRick Macklem  * The "mp" argument list is consumed.
864ab0c29afSRick Macklem  * The "maxextsiz" argument is the upper bound on the data
865ab0c29afSRick Macklem  * size for each mbuf (usually 16K for KERN_TLS).
866ab0c29afSRick Macklem  */
867ab0c29afSRick Macklem struct mbuf *
_rpc_copym_into_ext_pgs(struct mbuf * mp,int maxextsiz)868ab0c29afSRick Macklem _rpc_copym_into_ext_pgs(struct mbuf *mp, int maxextsiz)
869ab0c29afSRick Macklem {
870ab0c29afSRick Macklem 	struct mbuf *m, *m2, *m3, *mhead;
871ab0c29afSRick Macklem 	int tlen;
872ab0c29afSRick Macklem 
873ab0c29afSRick Macklem 	KASSERT((mp->m_flags & (M_EXT | M_EXTPG)) !=
874ab0c29afSRick Macklem 	    (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
875ab0c29afSRick Macklem 	    " first mbuf is an ext_pgs"));
876ab0c29afSRick Macklem 	/*
877ab0c29afSRick Macklem 	 * Find the last non-ext_pgs mbuf and the total
878ab0c29afSRick Macklem 	 * length of the non-ext_pgs mbuf(s).
879ab0c29afSRick Macklem 	 * The first mbuf must always be a non-ext_pgs
880ab0c29afSRick Macklem 	 * mbuf.
881ab0c29afSRick Macklem 	 */
882ab0c29afSRick Macklem 	tlen = mp->m_len;
883ab0c29afSRick Macklem 	m2 = mp;
884ab0c29afSRick Macklem 	for (m = mp->m_next; m != NULL; m = m->m_next) {
885ab0c29afSRick Macklem 		if ((m->m_flags & M_EXTPG) != 0)
886ab0c29afSRick Macklem 			break;
887ab0c29afSRick Macklem 		tlen += m->m_len;
888ab0c29afSRick Macklem 		m2 = m;
889ab0c29afSRick Macklem 	}
890ab0c29afSRick Macklem 
891ab0c29afSRick Macklem 	/*
892ab0c29afSRick Macklem 	 * Copy the non-ext_pgs mbuf(s) into an ext_pgs
893ab0c29afSRick Macklem 	 * mbuf list.
894ab0c29afSRick Macklem 	 */
895ab0c29afSRick Macklem 	m2->m_next = NULL;
896ab0c29afSRick Macklem 	mhead = mb_mapped_to_unmapped(mp, tlen, maxextsiz,
897ab0c29afSRick Macklem 	    M_WAITOK, &m2);
898ab0c29afSRick Macklem 
899ab0c29afSRick Macklem 	/*
900ab0c29afSRick Macklem 	 * Link the ext_pgs list onto the newly copied
901ab0c29afSRick Macklem 	 * list and free up the non-ext_pgs mbuf(s).
902ab0c29afSRick Macklem 	 */
903ab0c29afSRick Macklem 	m2->m_next = m;
904ab0c29afSRick Macklem 	m_freem(mp);
905ab0c29afSRick Macklem 
906ab0c29afSRick Macklem 	/*
907ab0c29afSRick Macklem 	 * Sanity check the resultant mbuf list.  Check for and
908ab0c29afSRick Macklem 	 * remove any 0 length mbufs in the list, since the
909ab0c29afSRick Macklem 	 * KERN_TLS code does not expect any 0 length mbuf(s)
910ab0c29afSRick Macklem 	 * in the list.
911ab0c29afSRick Macklem 	 */
912ab0c29afSRick Macklem 	m3 = NULL;
913ab0c29afSRick Macklem 	m2 = mhead;
914ab0c29afSRick Macklem 	tlen = 0;
915ab0c29afSRick Macklem 	while (m2 != NULL) {
916ab0c29afSRick Macklem 		KASSERT(m2->m_len >= 0, ("_rpc_copym_into_ext_pgs:"
917ab0c29afSRick Macklem 		    " negative m_len"));
918ab0c29afSRick Macklem 		KASSERT((m2->m_flags & (M_EXT | M_EXTPG)) ==
919ab0c29afSRick Macklem 		    (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
920ab0c29afSRick Macklem 			    " non-nomap mbuf in list"));
921ab0c29afSRick Macklem 		if (m2->m_len == 0) {
922ab0c29afSRick Macklem 			if (m3 != NULL)
923ab0c29afSRick Macklem 				m3->m_next = m2->m_next;
924ab0c29afSRick Macklem 			else
925ab0c29afSRick Macklem 				m = m2->m_next;
926ab0c29afSRick Macklem 			m2->m_next = NULL;
927ab0c29afSRick Macklem 			m_free(m2);
928ab0c29afSRick Macklem 			if (m3 != NULL)
929ab0c29afSRick Macklem 				m2 = m3->m_next;
930ab0c29afSRick Macklem 			else
931ab0c29afSRick Macklem 				m2 = m;
932ab0c29afSRick Macklem 		} else {
933ab0c29afSRick Macklem 			MBUF_EXT_PGS_ASSERT_SANITY(m2);
934ab0c29afSRick Macklem 			m3 = m2;
935ab0c29afSRick Macklem 			tlen += m2->m_len;
936ab0c29afSRick Macklem 			m2 = m2->m_next;
937ab0c29afSRick Macklem 		}
938ab0c29afSRick Macklem 	}
939ab0c29afSRick Macklem 	return (mhead);
940ab0c29afSRick Macklem }
941ab0c29afSRick Macklem 
942ab0c29afSRick Macklem /*
943fa9d9930SDoug Rabson  * Kernel module glue
944fa9d9930SDoug Rabson  */
945fa9d9930SDoug Rabson static int
krpc_modevent(module_t mod,int type,void * data)946fa9d9930SDoug Rabson krpc_modevent(module_t mod, int type, void *data)
947fa9d9930SDoug Rabson {
948ab0c29afSRick Macklem 	int error = 0;
949fa9d9930SDoug Rabson 
950ab0c29afSRick Macklem 	switch (type) {
951ab0c29afSRick Macklem 	case MOD_LOAD:
952*fa1b9612SGleb Smirnoff 		rpcnl_init();
953ab0c29afSRick Macklem 		error = rpctls_init();
954ab0c29afSRick Macklem 		break;
955ab0c29afSRick Macklem 	case MOD_UNLOAD:
956ab0c29afSRick Macklem 		/*
957ab0c29afSRick Macklem 		 * Cannot be unloaded, since the rpctlssd or rpctlscd daemons
958ab0c29afSRick Macklem 		 * might be performing a rpctls syscall.
959ab0c29afSRick Macklem 		 */
960ab0c29afSRick Macklem 		/* FALLTHROUGH */
961ab0c29afSRick Macklem 	default:
962ab0c29afSRick Macklem 		error = EOPNOTSUPP;
963ab0c29afSRick Macklem 	}
964ab0c29afSRick Macklem 	return (error);
965fa9d9930SDoug Rabson }
966fa9d9930SDoug Rabson static moduledata_t krpc_mod = {
967fa9d9930SDoug Rabson 	"krpc",
968fa9d9930SDoug Rabson 	krpc_modevent,
969fa9d9930SDoug Rabson 	NULL,
970fa9d9930SDoug Rabson };
971*fa1b9612SGleb Smirnoff DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_FIRST);
972fa9d9930SDoug Rabson 
973fa9d9930SDoug Rabson /* So that loader and kldload(2) can find us, wherever we are.. */
974fa9d9930SDoug Rabson MODULE_VERSION(krpc, 1);
975732a02b4SGleb Smirnoff MODULE_DEPEND(krpc, xdr, 1, 1, 1);
976