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