1177633Sdfr/*	$NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $	*/
2177633Sdfr
3261046Smav/*-
4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261046Smav * All rights reserved.
6261046Smav *
7261046Smav * Redistribution and use in source and binary forms, with or without
8261046Smav * modification, are permitted provided that the following conditions are met:
9261046Smav * - Redistributions of source code must retain the above copyright notice,
10261046Smav *   this list of conditions and the following disclaimer.
11261046Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261046Smav *   this list of conditions and the following disclaimer in the documentation
13261046Smav *   and/or other materials provided with the distribution.
14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261046Smav *   contributors may be used to endorse or promote products derived
16261046Smav *   from this software without specific prior written permission.
17177633Sdfr *
18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261046Smav * POSSIBILITY OF SUCH DAMAGE.
29177633Sdfr */
30177633Sdfr
31177633Sdfr#if defined(LIBC_SCCS) && !defined(lint)
32177633Sdfrstatic char *sccsid2 = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
33177633Sdfrstatic char *sccsid = "@(#)svc_tcp.c	2.2 88/08/01 4.0 RPCSRC";
34177633Sdfr#endif
35177633Sdfr#include <sys/cdefs.h>
36177633Sdfr__FBSDID("$FreeBSD: releng/10.3/sys/rpc/svc_vc.c 287338 2015-09-01 01:01:35Z delphij $");
37177633Sdfr
38177633Sdfr/*
39177633Sdfr * svc_vc.c, Server side for Connection Oriented based RPC.
40177633Sdfr *
41177633Sdfr * Actually implements two flavors of transporter -
42177633Sdfr * a tcp rendezvouser (a listner and connection establisher)
43177633Sdfr * and a record/tcp stream.
44177633Sdfr */
45177633Sdfr
46177633Sdfr#include <sys/param.h>
47177633Sdfr#include <sys/lock.h>
48177633Sdfr#include <sys/kernel.h>
49177633Sdfr#include <sys/malloc.h>
50177633Sdfr#include <sys/mbuf.h>
51177633Sdfr#include <sys/mutex.h>
52193509Srwatson#include <sys/proc.h>
53177633Sdfr#include <sys/protosw.h>
54177633Sdfr#include <sys/queue.h>
55177633Sdfr#include <sys/socket.h>
56177633Sdfr#include <sys/socketvar.h>
57184588Sdfr#include <sys/sx.h>
58177633Sdfr#include <sys/systm.h>
59177633Sdfr#include <sys/uio.h>
60196503Szec
61196503Szec#include <net/vnet.h>
62196503Szec
63177633Sdfr#include <netinet/tcp.h>
64177633Sdfr
65177633Sdfr#include <rpc/rpc.h>
66177633Sdfr
67244008Srmacklem#include <rpc/krpc.h>
68177685Sdfr#include <rpc/rpc_com.h>
69177633Sdfr
70193509Srwatson#include <security/mac/mac_framework.h>
71193509Srwatson
72184588Sdfrstatic bool_t svc_vc_rendezvous_recv(SVCXPRT *, struct rpc_msg *,
73184588Sdfr    struct sockaddr **, struct mbuf **);
74177633Sdfrstatic enum xprt_stat svc_vc_rendezvous_stat(SVCXPRT *);
75177633Sdfrstatic void svc_vc_rendezvous_destroy(SVCXPRT *);
76177633Sdfrstatic bool_t svc_vc_null(void);
77177633Sdfrstatic void svc_vc_destroy(SVCXPRT *);
78177633Sdfrstatic enum xprt_stat svc_vc_stat(SVCXPRT *);
79261055Smavstatic bool_t svc_vc_ack(SVCXPRT *, uint32_t *);
80184588Sdfrstatic bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *,
81184588Sdfr    struct sockaddr **, struct mbuf **);
82184588Sdfrstatic bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *,
83261055Smav    struct sockaddr *, struct mbuf *, uint32_t *seq);
84177633Sdfrstatic bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
85177633Sdfrstatic bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
86177633Sdfr    void *in);
87244008Srmacklemstatic void svc_vc_backchannel_destroy(SVCXPRT *);
88244008Srmacklemstatic enum xprt_stat svc_vc_backchannel_stat(SVCXPRT *);
89244008Srmacklemstatic bool_t svc_vc_backchannel_recv(SVCXPRT *, struct rpc_msg *,
90244008Srmacklem    struct sockaddr **, struct mbuf **);
91244008Srmacklemstatic bool_t svc_vc_backchannel_reply(SVCXPRT *, struct rpc_msg *,
92261055Smav    struct sockaddr *, struct mbuf *, uint32_t *);
93244008Srmacklemstatic bool_t svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq,
94244008Srmacklem    void *in);
95177633Sdfrstatic SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so,
96177633Sdfr    struct sockaddr *raddr);
97177633Sdfrstatic int svc_vc_accept(struct socket *head, struct socket **sop);
98193272Sjhbstatic int svc_vc_soupcall(struct socket *so, void *arg, int waitflag);
99177633Sdfr
100177633Sdfrstatic struct xp_ops svc_vc_rendezvous_ops = {
101177633Sdfr	.xp_recv =	svc_vc_rendezvous_recv,
102177633Sdfr	.xp_stat =	svc_vc_rendezvous_stat,
103184588Sdfr	.xp_reply =	(bool_t (*)(SVCXPRT *, struct rpc_msg *,
104261055Smav		struct sockaddr *, struct mbuf *, uint32_t *))svc_vc_null,
105177633Sdfr	.xp_destroy =	svc_vc_rendezvous_destroy,
106177633Sdfr	.xp_control =	svc_vc_rendezvous_control
107177633Sdfr};
108177633Sdfr
109177633Sdfrstatic struct xp_ops svc_vc_ops = {
110177633Sdfr	.xp_recv =	svc_vc_recv,
111177633Sdfr	.xp_stat =	svc_vc_stat,
112261055Smav	.xp_ack =	svc_vc_ack,
113177633Sdfr	.xp_reply =	svc_vc_reply,
114177633Sdfr	.xp_destroy =	svc_vc_destroy,
115177633Sdfr	.xp_control =	svc_vc_control
116177633Sdfr};
117177633Sdfr
118244008Srmacklemstatic struct xp_ops svc_vc_backchannel_ops = {
119244008Srmacklem	.xp_recv =	svc_vc_backchannel_recv,
120244008Srmacklem	.xp_stat =	svc_vc_backchannel_stat,
121244008Srmacklem	.xp_reply =	svc_vc_backchannel_reply,
122244008Srmacklem	.xp_destroy =	svc_vc_backchannel_destroy,
123244008Srmacklem	.xp_control =	svc_vc_backchannel_control
124177633Sdfr};
125177633Sdfr
126177633Sdfr/*
127177633Sdfr * Usage:
128177633Sdfr *	xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
129177633Sdfr *
130177633Sdfr * Creates, registers, and returns a (rpc) tcp based transporter.
131177633Sdfr * Once *xprt is initialized, it is registered as a transporter
132177633Sdfr * see (svc.h, xprt_register).  This routine returns
133177633Sdfr * a NULL if a problem occurred.
134177633Sdfr *
135177633Sdfr * The filedescriptor passed in is expected to refer to a bound, but
136177633Sdfr * not yet connected socket.
137177633Sdfr *
138177633Sdfr * Since streams do buffered io similar to stdio, the caller can specify
139177633Sdfr * how big the send and receive buffers are via the second and third parms;
140177633Sdfr * 0 => use the system default.
141177633Sdfr */
142177633SdfrSVCXPRT *
143177633Sdfrsvc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
144177633Sdfr    size_t recvsize)
145177633Sdfr{
146177633Sdfr	SVCXPRT *xprt;
147177633Sdfr	struct sockaddr* sa;
148177633Sdfr	int error;
149177633Sdfr
150249263Sjhb	SOCK_LOCK(so);
151249263Sjhb	if (so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED)) {
152249263Sjhb		SOCK_UNLOCK(so);
153287338Sdelphij		CURVNET_SET(so->so_vnet);
154180025Sdfr		error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
155287338Sdelphij		CURVNET_RESTORE();
156180025Sdfr		if (error)
157180025Sdfr			return (NULL);
158180025Sdfr		xprt = svc_vc_create_conn(pool, so, sa);
159180025Sdfr		free(sa, M_SONAME);
160180025Sdfr		return (xprt);
161180025Sdfr	}
162249263Sjhb	SOCK_UNLOCK(so);
163180025Sdfr
164184588Sdfr	xprt = svc_xprt_alloc();
165184588Sdfr	sx_init(&xprt->xp_lock, "xprt->xp_lock");
166177633Sdfr	xprt->xp_pool = pool;
167177633Sdfr	xprt->xp_socket = so;
168177633Sdfr	xprt->xp_p1 = NULL;
169177633Sdfr	xprt->xp_p2 = NULL;
170177633Sdfr	xprt->xp_ops = &svc_vc_rendezvous_ops;
171177633Sdfr
172287338Sdelphij	CURVNET_SET(so->so_vnet);
173177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
174287338Sdelphij	CURVNET_RESTORE();
175196503Szec	if (error) {
176177633Sdfr		goto cleanup_svc_vc_create;
177196503Szec	}
178177633Sdfr
179184588Sdfr	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
180177633Sdfr	free(sa, M_SONAME);
181177633Sdfr
182177633Sdfr	xprt_register(xprt);
183177633Sdfr
184281520Smav	solisten(so, -1, curthread);
185177633Sdfr
186177633Sdfr	SOCKBUF_LOCK(&so->so_rcv);
187193436Srmacklem	xprt->xp_upcallset = 1;
188193272Sjhb	soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt);
189177633Sdfr	SOCKBUF_UNLOCK(&so->so_rcv);
190177633Sdfr
191177633Sdfr	return (xprt);
192177633Sdfrcleanup_svc_vc_create:
193261055Smav	if (xprt) {
194261055Smav		sx_destroy(&xprt->xp_lock);
195184588Sdfr		svc_xprt_free(xprt);
196261055Smav	}
197177633Sdfr	return (NULL);
198177633Sdfr}
199177633Sdfr
200177633Sdfr/*
201177633Sdfr * Create a new transport for a socket optained via soaccept().
202177633Sdfr */
203177633SdfrSVCXPRT *
204177633Sdfrsvc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
205177633Sdfr{
206177633Sdfr	SVCXPRT *xprt = NULL;
207177633Sdfr	struct cf_conn *cd = NULL;
208177633Sdfr	struct sockaddr* sa = NULL;
209180025Sdfr	struct sockopt opt;
210180025Sdfr	int one = 1;
211177633Sdfr	int error;
212177633Sdfr
213180025Sdfr	bzero(&opt, sizeof(struct sockopt));
214180025Sdfr	opt.sopt_dir = SOPT_SET;
215180025Sdfr	opt.sopt_level = SOL_SOCKET;
216180025Sdfr	opt.sopt_name = SO_KEEPALIVE;
217180025Sdfr	opt.sopt_val = &one;
218180025Sdfr	opt.sopt_valsize = sizeof(one);
219180025Sdfr	error = sosetopt(so, &opt);
220196503Szec	if (error) {
221180025Sdfr		return (NULL);
222196503Szec	}
223180025Sdfr
224180025Sdfr	if (so->so_proto->pr_protocol == IPPROTO_TCP) {
225180025Sdfr		bzero(&opt, sizeof(struct sockopt));
226180025Sdfr		opt.sopt_dir = SOPT_SET;
227180025Sdfr		opt.sopt_level = IPPROTO_TCP;
228180025Sdfr		opt.sopt_name = TCP_NODELAY;
229180025Sdfr		opt.sopt_val = &one;
230180025Sdfr		opt.sopt_valsize = sizeof(one);
231180025Sdfr		error = sosetopt(so, &opt);
232196503Szec		if (error) {
233180025Sdfr			return (NULL);
234196503Szec		}
235180025Sdfr	}
236180025Sdfr
237177633Sdfr	cd = mem_alloc(sizeof(*cd));
238177633Sdfr	cd->strm_stat = XPRT_IDLE;
239177633Sdfr
240184588Sdfr	xprt = svc_xprt_alloc();
241184588Sdfr	sx_init(&xprt->xp_lock, "xprt->xp_lock");
242177633Sdfr	xprt->xp_pool = pool;
243177633Sdfr	xprt->xp_socket = so;
244177633Sdfr	xprt->xp_p1 = cd;
245177633Sdfr	xprt->xp_p2 = NULL;
246177633Sdfr	xprt->xp_ops = &svc_vc_ops;
247177633Sdfr
248184588Sdfr	/*
249184588Sdfr	 * See http://www.connectathon.org/talks96/nfstcp.pdf - client
250184588Sdfr	 * has a 5 minute timer, server has a 6 minute timer.
251184588Sdfr	 */
252184588Sdfr	xprt->xp_idletimeout = 6 * 60;
253177633Sdfr
254184588Sdfr	memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len);
255184588Sdfr
256287338Sdelphij	CURVNET_SET(so->so_vnet);
257177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
258287338Sdelphij	CURVNET_RESTORE();
259177633Sdfr	if (error)
260177633Sdfr		goto cleanup_svc_vc_create;
261177633Sdfr
262184588Sdfr	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
263177633Sdfr	free(sa, M_SONAME);
264177633Sdfr
265177633Sdfr	xprt_register(xprt);
266177633Sdfr
267177633Sdfr	SOCKBUF_LOCK(&so->so_rcv);
268193436Srmacklem	xprt->xp_upcallset = 1;
269193272Sjhb	soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt);
270177633Sdfr	SOCKBUF_UNLOCK(&so->so_rcv);
271177633Sdfr
272177633Sdfr	/*
273177633Sdfr	 * Throw the transport into the active list in case it already
274177633Sdfr	 * has some data buffered.
275177633Sdfr	 */
276184588Sdfr	sx_xlock(&xprt->xp_lock);
277177633Sdfr	xprt_active(xprt);
278184588Sdfr	sx_xunlock(&xprt->xp_lock);
279177633Sdfr
280177633Sdfr	return (xprt);
281177633Sdfrcleanup_svc_vc_create:
282177633Sdfr	if (xprt) {
283261055Smav		sx_destroy(&xprt->xp_lock);
284261055Smav		svc_xprt_free(xprt);
285177633Sdfr	}
286177633Sdfr	if (cd)
287177633Sdfr		mem_free(cd, sizeof(*cd));
288177633Sdfr	return (NULL);
289177633Sdfr}
290177633Sdfr
291177633Sdfr/*
292244008Srmacklem * Create a new transport for a backchannel on a clnt_vc socket.
293244008Srmacklem */
294244008SrmacklemSVCXPRT *
295244008Srmacklemsvc_vc_create_backchannel(SVCPOOL *pool)
296244008Srmacklem{
297244008Srmacklem	SVCXPRT *xprt = NULL;
298244008Srmacklem	struct cf_conn *cd = NULL;
299244008Srmacklem
300244008Srmacklem	cd = mem_alloc(sizeof(*cd));
301244008Srmacklem	cd->strm_stat = XPRT_IDLE;
302244008Srmacklem
303244008Srmacklem	xprt = svc_xprt_alloc();
304244008Srmacklem	sx_init(&xprt->xp_lock, "xprt->xp_lock");
305244008Srmacklem	xprt->xp_pool = pool;
306244008Srmacklem	xprt->xp_socket = NULL;
307244008Srmacklem	xprt->xp_p1 = cd;
308244008Srmacklem	xprt->xp_p2 = NULL;
309244008Srmacklem	xprt->xp_ops = &svc_vc_backchannel_ops;
310244008Srmacklem	return (xprt);
311244008Srmacklem}
312244008Srmacklem
313244008Srmacklem/*
314177633Sdfr * This does all of the accept except the final call to soaccept. The
315177633Sdfr * caller will call soaccept after dropping its locks (soaccept may
316177633Sdfr * call malloc).
317177633Sdfr */
318177633Sdfrint
319177633Sdfrsvc_vc_accept(struct socket *head, struct socket **sop)
320177633Sdfr{
321177633Sdfr	int error = 0;
322177633Sdfr	struct socket *so;
323177633Sdfr
324177633Sdfr	if ((head->so_options & SO_ACCEPTCONN) == 0) {
325177633Sdfr		error = EINVAL;
326177633Sdfr		goto done;
327177633Sdfr	}
328177633Sdfr#ifdef MAC
329193509Srwatson	error = mac_socket_check_accept(curthread->td_ucred, head);
330177633Sdfr	if (error != 0)
331177633Sdfr		goto done;
332177633Sdfr#endif
333177633Sdfr	ACCEPT_LOCK();
334177633Sdfr	if (TAILQ_EMPTY(&head->so_comp)) {
335177633Sdfr		ACCEPT_UNLOCK();
336177633Sdfr		error = EWOULDBLOCK;
337177633Sdfr		goto done;
338177633Sdfr	}
339177633Sdfr	so = TAILQ_FIRST(&head->so_comp);
340177633Sdfr	KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP"));
341177633Sdfr	KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP"));
342177633Sdfr
343177633Sdfr	/*
344177633Sdfr	 * Before changing the flags on the socket, we have to bump the
345177633Sdfr	 * reference count.  Otherwise, if the protocol calls sofree(),
346177633Sdfr	 * the socket will be released due to a zero refcount.
347177633Sdfr	 * XXX might not need soref() since this is simpler than kern_accept.
348177633Sdfr	 */
349177633Sdfr	SOCK_LOCK(so);			/* soref() and so_state update */
350177633Sdfr	soref(so);			/* file descriptor reference */
351177633Sdfr
352177633Sdfr	TAILQ_REMOVE(&head->so_comp, so, so_list);
353177633Sdfr	head->so_qlen--;
354177633Sdfr	so->so_state |= (head->so_state & SS_NBIO);
355177633Sdfr	so->so_qstate &= ~SQ_COMP;
356177633Sdfr	so->so_head = NULL;
357177633Sdfr
358177633Sdfr	SOCK_UNLOCK(so);
359177633Sdfr	ACCEPT_UNLOCK();
360177633Sdfr
361177633Sdfr	*sop = so;
362177633Sdfr
363177633Sdfr	/* connection has been removed from the listen queue */
364177633Sdfr	KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
365177633Sdfrdone:
366177633Sdfr	return (error);
367177633Sdfr}
368177633Sdfr
369177633Sdfr/*ARGSUSED*/
370177633Sdfrstatic bool_t
371184588Sdfrsvc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg,
372184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
373177633Sdfr{
374177633Sdfr	struct socket *so = NULL;
375177633Sdfr	struct sockaddr *sa = NULL;
376177633Sdfr	int error;
377194407Srmacklem	SVCXPRT *new_xprt;
378177633Sdfr
379177633Sdfr	/*
380177633Sdfr	 * The socket upcall calls xprt_active() which will eventually
381177633Sdfr	 * cause the server to call us here. We attempt to accept a
382177633Sdfr	 * connection from the socket and turn it into a new
383177633Sdfr	 * transport. If the accept fails, we have drained all pending
384177633Sdfr	 * connections so we call xprt_inactive().
385177633Sdfr	 */
386184588Sdfr	sx_xlock(&xprt->xp_lock);
387177633Sdfr
388177633Sdfr	error = svc_vc_accept(xprt->xp_socket, &so);
389177633Sdfr
390177633Sdfr	if (error == EWOULDBLOCK) {
391184588Sdfr		/*
392184588Sdfr		 * We must re-test for new connections after taking
393184588Sdfr		 * the lock to protect us in the case where a new
394184588Sdfr		 * connection arrives after our call to accept fails
395261047Smav		 * with EWOULDBLOCK.
396184588Sdfr		 */
397184588Sdfr		ACCEPT_LOCK();
398184588Sdfr		if (TAILQ_EMPTY(&xprt->xp_socket->so_comp))
399261053Smav			xprt_inactive_self(xprt);
400184588Sdfr		ACCEPT_UNLOCK();
401184588Sdfr		sx_xunlock(&xprt->xp_lock);
402177633Sdfr		return (FALSE);
403177633Sdfr	}
404177633Sdfr
405177633Sdfr	if (error) {
406177633Sdfr		SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
407193436Srmacklem		if (xprt->xp_upcallset) {
408193436Srmacklem			xprt->xp_upcallset = 0;
409193436Srmacklem			soupcall_clear(xprt->xp_socket, SO_RCV);
410193436Srmacklem		}
411177633Sdfr		SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
412261053Smav		xprt_inactive_self(xprt);
413184588Sdfr		sx_xunlock(&xprt->xp_lock);
414177633Sdfr		return (FALSE);
415177633Sdfr	}
416177633Sdfr
417184588Sdfr	sx_xunlock(&xprt->xp_lock);
418177633Sdfr
419177633Sdfr	sa = 0;
420177633Sdfr	error = soaccept(so, &sa);
421177633Sdfr
422177633Sdfr	if (error) {
423177633Sdfr		/*
424177633Sdfr		 * XXX not sure if I need to call sofree or soclose here.
425177633Sdfr		 */
426177633Sdfr		if (sa)
427177633Sdfr			free(sa, M_SONAME);
428177633Sdfr		return (FALSE);
429177633Sdfr	}
430177633Sdfr
431177633Sdfr	/*
432177633Sdfr	 * svc_vc_create_conn will call xprt_register - we don't need
433194407Srmacklem	 * to do anything with the new connection except derefence it.
434177633Sdfr	 */
435194407Srmacklem	new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa);
436194407Srmacklem	if (!new_xprt) {
437180025Sdfr		soclose(so);
438194407Srmacklem	} else {
439194407Srmacklem		SVC_RELEASE(new_xprt);
440194407Srmacklem	}
441180025Sdfr
442177633Sdfr	free(sa, M_SONAME);
443177633Sdfr
444177633Sdfr	return (FALSE); /* there is never an rpc msg to be processed */
445177633Sdfr}
446177633Sdfr
447177633Sdfr/*ARGSUSED*/
448177633Sdfrstatic enum xprt_stat
449177633Sdfrsvc_vc_rendezvous_stat(SVCXPRT *xprt)
450177633Sdfr{
451177633Sdfr
452177633Sdfr	return (XPRT_IDLE);
453177633Sdfr}
454177633Sdfr
455177633Sdfrstatic void
456177633Sdfrsvc_vc_destroy_common(SVCXPRT *xprt)
457177633Sdfr{
458177633Sdfr	SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
459193436Srmacklem	if (xprt->xp_upcallset) {
460193436Srmacklem		xprt->xp_upcallset = 0;
461193436Srmacklem		soupcall_clear(xprt->xp_socket, SO_RCV);
462193436Srmacklem	}
463177633Sdfr	SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
464177633Sdfr
465177633Sdfr	if (xprt->xp_socket)
466177633Sdfr		(void)soclose(xprt->xp_socket);
467177633Sdfr
468184588Sdfr	if (xprt->xp_netid)
469184588Sdfr		(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
470184588Sdfr	svc_xprt_free(xprt);
471177633Sdfr}
472177633Sdfr
473177633Sdfrstatic void
474177633Sdfrsvc_vc_rendezvous_destroy(SVCXPRT *xprt)
475177633Sdfr{
476177633Sdfr
477177633Sdfr	svc_vc_destroy_common(xprt);
478177633Sdfr}
479177633Sdfr
480177633Sdfrstatic void
481177633Sdfrsvc_vc_destroy(SVCXPRT *xprt)
482177633Sdfr{
483177633Sdfr	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
484177633Sdfr
485177633Sdfr	svc_vc_destroy_common(xprt);
486177633Sdfr
487177633Sdfr	if (cd->mreq)
488177633Sdfr		m_freem(cd->mreq);
489177633Sdfr	if (cd->mpending)
490177633Sdfr		m_freem(cd->mpending);
491177633Sdfr	mem_free(cd, sizeof(*cd));
492177633Sdfr}
493177633Sdfr
494244008Srmacklemstatic void
495244008Srmacklemsvc_vc_backchannel_destroy(SVCXPRT *xprt)
496244008Srmacklem{
497244008Srmacklem	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
498244008Srmacklem	struct mbuf *m, *m2;
499244008Srmacklem
500244008Srmacklem	svc_xprt_free(xprt);
501244008Srmacklem	m = cd->mreq;
502244008Srmacklem	while (m != NULL) {
503244008Srmacklem		m2 = m;
504244008Srmacklem		m = m->m_nextpkt;
505244008Srmacklem		m_freem(m2);
506244008Srmacklem	}
507244008Srmacklem	mem_free(cd, sizeof(*cd));
508244008Srmacklem}
509244008Srmacklem
510177633Sdfr/*ARGSUSED*/
511177633Sdfrstatic bool_t
512177633Sdfrsvc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
513177633Sdfr{
514177633Sdfr	return (FALSE);
515177633Sdfr}
516177633Sdfr
517177633Sdfrstatic bool_t
518177633Sdfrsvc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
519177633Sdfr{
520177633Sdfr
521177633Sdfr	return (FALSE);
522177633Sdfr}
523177633Sdfr
524244008Srmacklemstatic bool_t
525244008Srmacklemsvc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, void *in)
526244008Srmacklem{
527244008Srmacklem
528244008Srmacklem	return (FALSE);
529244008Srmacklem}
530244008Srmacklem
531177633Sdfrstatic enum xprt_stat
532177633Sdfrsvc_vc_stat(SVCXPRT *xprt)
533177633Sdfr{
534177633Sdfr	struct cf_conn *cd;
535177633Sdfr
536177633Sdfr	cd = (struct cf_conn *)(xprt->xp_p1);
537177633Sdfr
538177633Sdfr	if (cd->strm_stat == XPRT_DIED)
539177633Sdfr		return (XPRT_DIED);
540177633Sdfr
541261047Smav	if (cd->mreq != NULL && cd->resid == 0 && cd->eor)
542261047Smav		return (XPRT_MOREREQS);
543177633Sdfr
544184588Sdfr	if (soreadable(xprt->xp_socket))
545184588Sdfr		return (XPRT_MOREREQS);
546184588Sdfr
547177633Sdfr	return (XPRT_IDLE);
548177633Sdfr}
549177633Sdfr
550261055Smavstatic bool_t
551261055Smavsvc_vc_ack(SVCXPRT *xprt, uint32_t *ack)
552261055Smav{
553261055Smav
554261055Smav	*ack = atomic_load_acq_32(&xprt->xp_snt_cnt);
555261055Smav	*ack -= xprt->xp_socket->so_snd.sb_cc;
556261055Smav	return (TRUE);
557261055Smav}
558261055Smav
559244008Srmacklemstatic enum xprt_stat
560244008Srmacklemsvc_vc_backchannel_stat(SVCXPRT *xprt)
561244008Srmacklem{
562244008Srmacklem	struct cf_conn *cd;
563244008Srmacklem
564244008Srmacklem	cd = (struct cf_conn *)(xprt->xp_p1);
565244008Srmacklem
566244008Srmacklem	if (cd->mreq != NULL)
567244008Srmacklem		return (XPRT_MOREREQS);
568244008Srmacklem
569244008Srmacklem	return (XPRT_IDLE);
570244008Srmacklem}
571244008Srmacklem
572261047Smav/*
573261047Smav * If we have an mbuf chain in cd->mpending, try to parse a record from it,
574261047Smav * leaving the result in cd->mreq. If we don't have a complete record, leave
575261047Smav * the partial result in cd->mreq and try to read more from the socket.
576261047Smav */
577261050Smavstatic int
578261047Smavsvc_vc_process_pending(SVCXPRT *xprt)
579261047Smav{
580261047Smav	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
581261047Smav	struct socket *so = xprt->xp_socket;
582261047Smav	struct mbuf *m;
583261047Smav
584261047Smav	/*
585261047Smav	 * If cd->resid is non-zero, we have part of the
586261047Smav	 * record already, otherwise we are expecting a record
587261047Smav	 * marker.
588261047Smav	 */
589261047Smav	if (!cd->resid && cd->mpending) {
590261047Smav		/*
591261047Smav		 * See if there is enough data buffered to
592261047Smav		 * make up a record marker. Make sure we can
593261047Smav		 * handle the case where the record marker is
594261047Smav		 * split across more than one mbuf.
595261047Smav		 */
596261047Smav		size_t n = 0;
597261047Smav		uint32_t header;
598261047Smav
599261047Smav		m = cd->mpending;
600261047Smav		while (n < sizeof(uint32_t) && m) {
601261047Smav			n += m->m_len;
602261047Smav			m = m->m_next;
603261047Smav		}
604261047Smav		if (n < sizeof(uint32_t)) {
605261047Smav			so->so_rcv.sb_lowat = sizeof(uint32_t) - n;
606261050Smav			return (FALSE);
607261047Smav		}
608261047Smav		m_copydata(cd->mpending, 0, sizeof(header),
609261047Smav		    (char *)&header);
610261047Smav		header = ntohl(header);
611261047Smav		cd->eor = (header & 0x80000000) != 0;
612261047Smav		cd->resid = header & 0x7fffffff;
613261047Smav		m_adj(cd->mpending, sizeof(uint32_t));
614261047Smav	}
615261047Smav
616261047Smav	/*
617261047Smav	 * Start pulling off mbufs from cd->mpending
618261047Smav	 * until we either have a complete record or
619261047Smav	 * we run out of data. We use m_split to pull
620261047Smav	 * data - it will pull as much as possible and
621261047Smav	 * split the last mbuf if necessary.
622261047Smav	 */
623261047Smav	while (cd->mpending && cd->resid) {
624261047Smav		m = cd->mpending;
625261047Smav		if (cd->mpending->m_next
626261047Smav		    || cd->mpending->m_len > cd->resid)
627261047Smav			cd->mpending = m_split(cd->mpending,
628261047Smav			    cd->resid, M_WAITOK);
629261047Smav		else
630261047Smav			cd->mpending = NULL;
631261047Smav		if (cd->mreq)
632261047Smav			m_last(cd->mreq)->m_next = m;
633261047Smav		else
634261047Smav			cd->mreq = m;
635261047Smav		while (m) {
636261047Smav			cd->resid -= m->m_len;
637261047Smav			m = m->m_next;
638261047Smav		}
639261047Smav	}
640261047Smav
641261052Smav	/*
642261052Smav	 * Block receive upcalls if we have more data pending,
643261052Smav	 * otherwise report our need.
644261052Smav	 */
645261052Smav	if (cd->mpending)
646261052Smav		so->so_rcv.sb_lowat = INT_MAX;
647261052Smav	else
648261052Smav		so->so_rcv.sb_lowat =
649261052Smav		    imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2));
650261050Smav	return (TRUE);
651261047Smav}
652261047Smav
653177633Sdfrstatic bool_t
654184588Sdfrsvc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
655184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
656177633Sdfr{
657177633Sdfr	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
658177633Sdfr	struct uio uio;
659177633Sdfr	struct mbuf *m;
660261047Smav	struct socket* so = xprt->xp_socket;
661184588Sdfr	XDR xdrs;
662177633Sdfr	int error, rcvflag;
663269398Srmacklem	uint32_t xid_plus_direction[2];
664177633Sdfr
665184588Sdfr	/*
666184588Sdfr	 * Serialise access to the socket and our own record parsing
667184588Sdfr	 * state.
668184588Sdfr	 */
669184588Sdfr	sx_xlock(&xprt->xp_lock);
670184588Sdfr
671177633Sdfr	for (;;) {
672261047Smav		/* If we have no request ready, check pending queue. */
673261047Smav		while (cd->mpending &&
674261050Smav		    (cd->mreq == NULL || cd->resid != 0 || !cd->eor)) {
675261050Smav			if (!svc_vc_process_pending(xprt))
676261050Smav				break;
677261050Smav		}
678177633Sdfr
679261047Smav		/* Process and return complete request in cd->mreq. */
680261047Smav		if (cd->mreq != NULL && cd->resid == 0 && cd->eor) {
681177633Sdfr
682269398Srmacklem			/*
683269398Srmacklem			 * Now, check for a backchannel reply.
684269398Srmacklem			 * The XID is in the first uint32_t of the reply
685269398Srmacklem			 * and the message direction is the second one.
686269398Srmacklem			 */
687269398Srmacklem			if ((cd->mreq->m_len >= sizeof(xid_plus_direction) ||
688269398Srmacklem			    m_length(cd->mreq, NULL) >=
689269398Srmacklem			    sizeof(xid_plus_direction)) &&
690269398Srmacklem			    xprt->xp_p2 != NULL) {
691269398Srmacklem				m_copydata(cd->mreq, 0,
692269398Srmacklem				    sizeof(xid_plus_direction),
693269398Srmacklem				    (char *)xid_plus_direction);
694269398Srmacklem				xid_plus_direction[0] =
695269398Srmacklem				    ntohl(xid_plus_direction[0]);
696269398Srmacklem				xid_plus_direction[1] =
697269398Srmacklem				    ntohl(xid_plus_direction[1]);
698269398Srmacklem				/* Check message direction. */
699269398Srmacklem				if (xid_plus_direction[1] == REPLY) {
700269398Srmacklem					clnt_bck_svccall(xprt->xp_p2,
701269398Srmacklem					    cd->mreq,
702269398Srmacklem					    xid_plus_direction[0]);
703269398Srmacklem					cd->mreq = NULL;
704269398Srmacklem					continue;
705269398Srmacklem				}
706269398Srmacklem			}
707269398Srmacklem
708261047Smav			xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
709261047Smav			cd->mreq = NULL;
710261047Smav
711261047Smav			/* Check for next request in a pending queue. */
712261047Smav			svc_vc_process_pending(xprt);
713261047Smav			if (cd->mreq == NULL || cd->resid != 0) {
714261047Smav				SOCKBUF_LOCK(&so->so_rcv);
715261047Smav				if (!soreadable(so))
716261053Smav					xprt_inactive_self(xprt);
717261047Smav				SOCKBUF_UNLOCK(&so->so_rcv);
718177633Sdfr			}
719177633Sdfr
720261047Smav			sx_xunlock(&xprt->xp_lock);
721177633Sdfr
722261047Smav			if (! xdr_callmsg(&xdrs, msg)) {
723261047Smav				XDR_DESTROY(&xdrs);
724261047Smav				return (FALSE);
725261047Smav			}
726184588Sdfr
727261047Smav			*addrp = NULL;
728261047Smav			*mp = xdrmbuf_getall(&xdrs);
729261047Smav			XDR_DESTROY(&xdrs);
730177633Sdfr
731261047Smav			return (TRUE);
732177633Sdfr		}
733177633Sdfr
734177633Sdfr		/*
735177633Sdfr		 * The socket upcall calls xprt_active() which will eventually
736177633Sdfr		 * cause the server to call us here. We attempt to
737177633Sdfr		 * read as much as possible from the socket and put
738177633Sdfr		 * the result in cd->mpending. If the read fails,
739177633Sdfr		 * we have drained both cd->mpending and the socket so
740177633Sdfr		 * we can call xprt_inactive().
741177633Sdfr		 */
742177633Sdfr		uio.uio_resid = 1000000000;
743177633Sdfr		uio.uio_td = curthread;
744177633Sdfr		m = NULL;
745177633Sdfr		rcvflag = MSG_DONTWAIT;
746261047Smav		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
747177633Sdfr
748177633Sdfr		if (error == EWOULDBLOCK) {
749184588Sdfr			/*
750184588Sdfr			 * We must re-test for readability after
751184588Sdfr			 * taking the lock to protect us in the case
752184588Sdfr			 * where a new packet arrives on the socket
753184588Sdfr			 * after our call to soreceive fails with
754261047Smav			 * EWOULDBLOCK.
755184588Sdfr			 */
756261047Smav			SOCKBUF_LOCK(&so->so_rcv);
757261047Smav			if (!soreadable(so))
758261053Smav				xprt_inactive_self(xprt);
759261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
760184588Sdfr			sx_xunlock(&xprt->xp_lock);
761177633Sdfr			return (FALSE);
762177633Sdfr		}
763177633Sdfr
764177633Sdfr		if (error) {
765261047Smav			SOCKBUF_LOCK(&so->so_rcv);
766193436Srmacklem			if (xprt->xp_upcallset) {
767193436Srmacklem				xprt->xp_upcallset = 0;
768261047Smav				soupcall_clear(so, SO_RCV);
769193436Srmacklem			}
770261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
771261053Smav			xprt_inactive_self(xprt);
772177633Sdfr			cd->strm_stat = XPRT_DIED;
773184588Sdfr			sx_xunlock(&xprt->xp_lock);
774177633Sdfr			return (FALSE);
775177633Sdfr		}
776177633Sdfr
777177633Sdfr		if (!m) {
778177633Sdfr			/*
779177633Sdfr			 * EOF - the other end has closed the socket.
780177633Sdfr			 */
781261053Smav			xprt_inactive_self(xprt);
782177633Sdfr			cd->strm_stat = XPRT_DIED;
783184588Sdfr			sx_xunlock(&xprt->xp_lock);
784177633Sdfr			return (FALSE);
785177633Sdfr		}
786177633Sdfr
787177633Sdfr		if (cd->mpending)
788177633Sdfr			m_last(cd->mpending)->m_next = m;
789177633Sdfr		else
790177633Sdfr			cd->mpending = m;
791177633Sdfr	}
792177633Sdfr}
793177633Sdfr
794177633Sdfrstatic bool_t
795244008Srmacklemsvc_vc_backchannel_recv(SVCXPRT *xprt, struct rpc_msg *msg,
796244008Srmacklem    struct sockaddr **addrp, struct mbuf **mp)
797244008Srmacklem{
798244008Srmacklem	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
799244008Srmacklem	struct ct_data *ct;
800244008Srmacklem	struct mbuf *m;
801244008Srmacklem	XDR xdrs;
802244008Srmacklem
803244008Srmacklem	sx_xlock(&xprt->xp_lock);
804244008Srmacklem	ct = (struct ct_data *)xprt->xp_p2;
805244008Srmacklem	if (ct == NULL) {
806244008Srmacklem		sx_xunlock(&xprt->xp_lock);
807244008Srmacklem		return (FALSE);
808244008Srmacklem	}
809244008Srmacklem	mtx_lock(&ct->ct_lock);
810244008Srmacklem	m = cd->mreq;
811244008Srmacklem	if (m == NULL) {
812261053Smav		xprt_inactive_self(xprt);
813244008Srmacklem		mtx_unlock(&ct->ct_lock);
814244008Srmacklem		sx_xunlock(&xprt->xp_lock);
815244008Srmacklem		return (FALSE);
816244008Srmacklem	}
817244008Srmacklem	cd->mreq = m->m_nextpkt;
818244008Srmacklem	mtx_unlock(&ct->ct_lock);
819244008Srmacklem	sx_xunlock(&xprt->xp_lock);
820244008Srmacklem
821244008Srmacklem	xdrmbuf_create(&xdrs, m, XDR_DECODE);
822244008Srmacklem	if (! xdr_callmsg(&xdrs, msg)) {
823244008Srmacklem		XDR_DESTROY(&xdrs);
824244008Srmacklem		return (FALSE);
825244008Srmacklem	}
826244008Srmacklem	*addrp = NULL;
827244008Srmacklem	*mp = xdrmbuf_getall(&xdrs);
828244008Srmacklem	XDR_DESTROY(&xdrs);
829244008Srmacklem	return (TRUE);
830244008Srmacklem}
831244008Srmacklem
832244008Srmacklemstatic bool_t
833184588Sdfrsvc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
834261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
835177633Sdfr{
836177633Sdfr	XDR xdrs;
837177633Sdfr	struct mbuf *mrep;
838184588Sdfr	bool_t stat = TRUE;
839261055Smav	int error, len;
840177633Sdfr
841177633Sdfr	/*
842177633Sdfr	 * Leave space for record mark.
843177633Sdfr	 */
844248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
845177633Sdfr	mrep->m_data += sizeof(uint32_t);
846177633Sdfr
847184588Sdfr	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
848184588Sdfr
849184588Sdfr	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
850184588Sdfr	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
851184588Sdfr		if (!xdr_replymsg(&xdrs, msg))
852184588Sdfr			stat = FALSE;
853184588Sdfr		else
854184588Sdfr			xdrmbuf_append(&xdrs, m);
855184588Sdfr	} else {
856184588Sdfr		stat = xdr_replymsg(&xdrs, msg);
857184588Sdfr	}
858184588Sdfr
859184588Sdfr	if (stat) {
860177633Sdfr		m_fixhdr(mrep);
861177633Sdfr
862177633Sdfr		/*
863177633Sdfr		 * Prepend a record marker containing the reply length.
864177633Sdfr		 */
865243882Sglebius		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
866261055Smav		len = mrep->m_pkthdr.len;
867177633Sdfr		*mtod(mrep, uint32_t *) =
868261055Smav			htonl(0x80000000 | (len - sizeof(uint32_t)));
869261055Smav		atomic_add_acq_32(&xprt->xp_snd_cnt, len);
870177633Sdfr		error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL,
871177633Sdfr		    0, curthread);
872177633Sdfr		if (!error) {
873261055Smav			atomic_add_rel_32(&xprt->xp_snt_cnt, len);
874261055Smav			if (seq)
875261055Smav				*seq = xprt->xp_snd_cnt;
876177633Sdfr			stat = TRUE;
877261055Smav		} else
878261055Smav			atomic_subtract_32(&xprt->xp_snd_cnt, len);
879177633Sdfr	} else {
880177633Sdfr		m_freem(mrep);
881177633Sdfr	}
882177633Sdfr
883184588Sdfr	XDR_DESTROY(&xdrs);
884177633Sdfr
885177633Sdfr	return (stat);
886177633Sdfr}
887177633Sdfr
888177633Sdfrstatic bool_t
889244008Srmacklemsvc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg,
890261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
891244008Srmacklem{
892244008Srmacklem	struct ct_data *ct;
893244008Srmacklem	XDR xdrs;
894244008Srmacklem	struct mbuf *mrep;
895244008Srmacklem	bool_t stat = TRUE;
896244008Srmacklem	int error;
897244008Srmacklem
898244008Srmacklem	/*
899244008Srmacklem	 * Leave space for record mark.
900244008Srmacklem	 */
901248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
902244008Srmacklem	mrep->m_data += sizeof(uint32_t);
903244008Srmacklem
904244008Srmacklem	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
905244008Srmacklem
906244008Srmacklem	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
907244008Srmacklem	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
908244008Srmacklem		if (!xdr_replymsg(&xdrs, msg))
909244008Srmacklem			stat = FALSE;
910244008Srmacklem		else
911244008Srmacklem			xdrmbuf_append(&xdrs, m);
912244008Srmacklem	} else {
913244008Srmacklem		stat = xdr_replymsg(&xdrs, msg);
914244008Srmacklem	}
915244008Srmacklem
916244008Srmacklem	if (stat) {
917244008Srmacklem		m_fixhdr(mrep);
918244008Srmacklem
919244008Srmacklem		/*
920244008Srmacklem		 * Prepend a record marker containing the reply length.
921244008Srmacklem		 */
922244008Srmacklem		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
923244008Srmacklem		*mtod(mrep, uint32_t *) =
924244008Srmacklem			htonl(0x80000000 | (mrep->m_pkthdr.len
925244008Srmacklem				- sizeof(uint32_t)));
926244008Srmacklem		sx_xlock(&xprt->xp_lock);
927244008Srmacklem		ct = (struct ct_data *)xprt->xp_p2;
928244008Srmacklem		if (ct != NULL)
929244008Srmacklem			error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL,
930244008Srmacklem			    0, curthread);
931244008Srmacklem		else
932244008Srmacklem			error = EPIPE;
933244008Srmacklem		sx_xunlock(&xprt->xp_lock);
934244008Srmacklem		if (!error) {
935244008Srmacklem			stat = TRUE;
936244008Srmacklem		}
937244008Srmacklem	} else {
938244008Srmacklem		m_freem(mrep);
939244008Srmacklem	}
940244008Srmacklem
941244008Srmacklem	XDR_DESTROY(&xdrs);
942244008Srmacklem
943244008Srmacklem	return (stat);
944244008Srmacklem}
945244008Srmacklem
946244008Srmacklemstatic bool_t
947177633Sdfrsvc_vc_null()
948177633Sdfr{
949177633Sdfr
950177633Sdfr	return (FALSE);
951177633Sdfr}
952177633Sdfr
953193272Sjhbstatic int
954177633Sdfrsvc_vc_soupcall(struct socket *so, void *arg, int waitflag)
955177633Sdfr{
956177633Sdfr	SVCXPRT *xprt = (SVCXPRT *) arg;
957177633Sdfr
958261047Smav	if (soreadable(xprt->xp_socket))
959261047Smav		xprt_active(xprt);
960193272Sjhb	return (SU_OK);
961177633Sdfr}
962177633Sdfr
963177633Sdfr#if 0
964177633Sdfr/*
965177633Sdfr * Get the effective UID of the sending process. Used by rpcbind, keyserv
966177633Sdfr * and rpc.yppasswdd on AF_LOCAL.
967177633Sdfr */
968177633Sdfrint
969177633Sdfr__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
970177633Sdfr	int sock, ret;
971177633Sdfr	gid_t egid;
972177633Sdfr	uid_t euid;
973177633Sdfr	struct sockaddr *sa;
974177633Sdfr
975177633Sdfr	sock = transp->xp_fd;
976184588Sdfr	sa = (struct sockaddr *)transp->xp_rtaddr;
977177633Sdfr	if (sa->sa_family == AF_LOCAL) {
978177633Sdfr		ret = getpeereid(sock, &euid, &egid);
979177633Sdfr		if (ret == 0)
980177633Sdfr			*uid = euid;
981177633Sdfr		return (ret);
982177633Sdfr	} else
983177633Sdfr		return (-1);
984177633Sdfr}
985177633Sdfr#endif
986