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: stable/10/sys/rpc/svc_vc.c 309503 2016-12-03 19:03:25Z ngie $");
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);
192301801Sngie
193177633Sdfrcleanup_svc_vc_create:
194301801Sngie	sx_destroy(&xprt->xp_lock);
195301801Sngie	svc_xprt_free(xprt);
196301801Sngie
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{
206301801Sngie	SVCXPRT *xprt;
207301801Sngie	struct cf_conn *cd;
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:
282301801Sngie	sx_destroy(&xprt->xp_lock);
283301801Sngie	svc_xprt_free(xprt);
284301801Sngie	mem_free(cd, sizeof(*cd));
285301801Sngie
286177633Sdfr	return (NULL);
287177633Sdfr}
288177633Sdfr
289177633Sdfr/*
290244008Srmacklem * Create a new transport for a backchannel on a clnt_vc socket.
291244008Srmacklem */
292244008SrmacklemSVCXPRT *
293244008Srmacklemsvc_vc_create_backchannel(SVCPOOL *pool)
294244008Srmacklem{
295244008Srmacklem	SVCXPRT *xprt = NULL;
296244008Srmacklem	struct cf_conn *cd = NULL;
297244008Srmacklem
298244008Srmacklem	cd = mem_alloc(sizeof(*cd));
299244008Srmacklem	cd->strm_stat = XPRT_IDLE;
300244008Srmacklem
301244008Srmacklem	xprt = svc_xprt_alloc();
302244008Srmacklem	sx_init(&xprt->xp_lock, "xprt->xp_lock");
303244008Srmacklem	xprt->xp_pool = pool;
304244008Srmacklem	xprt->xp_socket = NULL;
305244008Srmacklem	xprt->xp_p1 = cd;
306244008Srmacklem	xprt->xp_p2 = NULL;
307244008Srmacklem	xprt->xp_ops = &svc_vc_backchannel_ops;
308244008Srmacklem	return (xprt);
309244008Srmacklem}
310244008Srmacklem
311244008Srmacklem/*
312177633Sdfr * This does all of the accept except the final call to soaccept. The
313177633Sdfr * caller will call soaccept after dropping its locks (soaccept may
314177633Sdfr * call malloc).
315177633Sdfr */
316177633Sdfrint
317177633Sdfrsvc_vc_accept(struct socket *head, struct socket **sop)
318177633Sdfr{
319177633Sdfr	int error = 0;
320177633Sdfr	struct socket *so;
321177633Sdfr
322177633Sdfr	if ((head->so_options & SO_ACCEPTCONN) == 0) {
323177633Sdfr		error = EINVAL;
324177633Sdfr		goto done;
325177633Sdfr	}
326177633Sdfr#ifdef MAC
327193509Srwatson	error = mac_socket_check_accept(curthread->td_ucred, head);
328177633Sdfr	if (error != 0)
329177633Sdfr		goto done;
330177633Sdfr#endif
331177633Sdfr	ACCEPT_LOCK();
332177633Sdfr	if (TAILQ_EMPTY(&head->so_comp)) {
333177633Sdfr		ACCEPT_UNLOCK();
334177633Sdfr		error = EWOULDBLOCK;
335177633Sdfr		goto done;
336177633Sdfr	}
337177633Sdfr	so = TAILQ_FIRST(&head->so_comp);
338177633Sdfr	KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP"));
339177633Sdfr	KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP"));
340177633Sdfr
341177633Sdfr	/*
342177633Sdfr	 * Before changing the flags on the socket, we have to bump the
343177633Sdfr	 * reference count.  Otherwise, if the protocol calls sofree(),
344177633Sdfr	 * the socket will be released due to a zero refcount.
345177633Sdfr	 * XXX might not need soref() since this is simpler than kern_accept.
346177633Sdfr	 */
347177633Sdfr	SOCK_LOCK(so);			/* soref() and so_state update */
348177633Sdfr	soref(so);			/* file descriptor reference */
349177633Sdfr
350177633Sdfr	TAILQ_REMOVE(&head->so_comp, so, so_list);
351177633Sdfr	head->so_qlen--;
352177633Sdfr	so->so_state |= (head->so_state & SS_NBIO);
353177633Sdfr	so->so_qstate &= ~SQ_COMP;
354177633Sdfr	so->so_head = NULL;
355177633Sdfr
356177633Sdfr	SOCK_UNLOCK(so);
357177633Sdfr	ACCEPT_UNLOCK();
358177633Sdfr
359177633Sdfr	*sop = so;
360177633Sdfr
361177633Sdfr	/* connection has been removed from the listen queue */
362177633Sdfr	KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
363177633Sdfrdone:
364177633Sdfr	return (error);
365177633Sdfr}
366177633Sdfr
367177633Sdfr/*ARGSUSED*/
368177633Sdfrstatic bool_t
369184588Sdfrsvc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg,
370184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
371177633Sdfr{
372177633Sdfr	struct socket *so = NULL;
373177633Sdfr	struct sockaddr *sa = NULL;
374177633Sdfr	int error;
375194407Srmacklem	SVCXPRT *new_xprt;
376177633Sdfr
377177633Sdfr	/*
378177633Sdfr	 * The socket upcall calls xprt_active() which will eventually
379177633Sdfr	 * cause the server to call us here. We attempt to accept a
380177633Sdfr	 * connection from the socket and turn it into a new
381177633Sdfr	 * transport. If the accept fails, we have drained all pending
382177633Sdfr	 * connections so we call xprt_inactive().
383177633Sdfr	 */
384184588Sdfr	sx_xlock(&xprt->xp_lock);
385177633Sdfr
386177633Sdfr	error = svc_vc_accept(xprt->xp_socket, &so);
387177633Sdfr
388177633Sdfr	if (error == EWOULDBLOCK) {
389184588Sdfr		/*
390184588Sdfr		 * We must re-test for new connections after taking
391184588Sdfr		 * the lock to protect us in the case where a new
392184588Sdfr		 * connection arrives after our call to accept fails
393261047Smav		 * with EWOULDBLOCK.
394184588Sdfr		 */
395184588Sdfr		ACCEPT_LOCK();
396184588Sdfr		if (TAILQ_EMPTY(&xprt->xp_socket->so_comp))
397261053Smav			xprt_inactive_self(xprt);
398184588Sdfr		ACCEPT_UNLOCK();
399184588Sdfr		sx_xunlock(&xprt->xp_lock);
400177633Sdfr		return (FALSE);
401177633Sdfr	}
402177633Sdfr
403177633Sdfr	if (error) {
404177633Sdfr		SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
405193436Srmacklem		if (xprt->xp_upcallset) {
406193436Srmacklem			xprt->xp_upcallset = 0;
407193436Srmacklem			soupcall_clear(xprt->xp_socket, SO_RCV);
408193436Srmacklem		}
409177633Sdfr		SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
410261053Smav		xprt_inactive_self(xprt);
411184588Sdfr		sx_xunlock(&xprt->xp_lock);
412177633Sdfr		return (FALSE);
413177633Sdfr	}
414177633Sdfr
415184588Sdfr	sx_xunlock(&xprt->xp_lock);
416177633Sdfr
417309503Sngie	sa = NULL;
418177633Sdfr	error = soaccept(so, &sa);
419177633Sdfr
420177633Sdfr	if (error) {
421177633Sdfr		/*
422177633Sdfr		 * XXX not sure if I need to call sofree or soclose here.
423177633Sdfr		 */
424177633Sdfr		if (sa)
425177633Sdfr			free(sa, M_SONAME);
426177633Sdfr		return (FALSE);
427177633Sdfr	}
428177633Sdfr
429177633Sdfr	/*
430177633Sdfr	 * svc_vc_create_conn will call xprt_register - we don't need
431194407Srmacklem	 * to do anything with the new connection except derefence it.
432177633Sdfr	 */
433194407Srmacklem	new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa);
434194407Srmacklem	if (!new_xprt) {
435180025Sdfr		soclose(so);
436194407Srmacklem	} else {
437194407Srmacklem		SVC_RELEASE(new_xprt);
438194407Srmacklem	}
439180025Sdfr
440177633Sdfr	free(sa, M_SONAME);
441177633Sdfr
442177633Sdfr	return (FALSE); /* there is never an rpc msg to be processed */
443177633Sdfr}
444177633Sdfr
445177633Sdfr/*ARGSUSED*/
446177633Sdfrstatic enum xprt_stat
447177633Sdfrsvc_vc_rendezvous_stat(SVCXPRT *xprt)
448177633Sdfr{
449177633Sdfr
450177633Sdfr	return (XPRT_IDLE);
451177633Sdfr}
452177633Sdfr
453177633Sdfrstatic void
454177633Sdfrsvc_vc_destroy_common(SVCXPRT *xprt)
455177633Sdfr{
456177633Sdfr	SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
457193436Srmacklem	if (xprt->xp_upcallset) {
458193436Srmacklem		xprt->xp_upcallset = 0;
459193436Srmacklem		soupcall_clear(xprt->xp_socket, SO_RCV);
460193436Srmacklem	}
461177633Sdfr	SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
462177633Sdfr
463177633Sdfr	if (xprt->xp_socket)
464177633Sdfr		(void)soclose(xprt->xp_socket);
465177633Sdfr
466184588Sdfr	if (xprt->xp_netid)
467184588Sdfr		(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
468184588Sdfr	svc_xprt_free(xprt);
469177633Sdfr}
470177633Sdfr
471177633Sdfrstatic void
472177633Sdfrsvc_vc_rendezvous_destroy(SVCXPRT *xprt)
473177633Sdfr{
474177633Sdfr
475177633Sdfr	svc_vc_destroy_common(xprt);
476177633Sdfr}
477177633Sdfr
478177633Sdfrstatic void
479177633Sdfrsvc_vc_destroy(SVCXPRT *xprt)
480177633Sdfr{
481177633Sdfr	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
482177633Sdfr
483177633Sdfr	svc_vc_destroy_common(xprt);
484177633Sdfr
485177633Sdfr	if (cd->mreq)
486177633Sdfr		m_freem(cd->mreq);
487177633Sdfr	if (cd->mpending)
488177633Sdfr		m_freem(cd->mpending);
489177633Sdfr	mem_free(cd, sizeof(*cd));
490177633Sdfr}
491177633Sdfr
492244008Srmacklemstatic void
493244008Srmacklemsvc_vc_backchannel_destroy(SVCXPRT *xprt)
494244008Srmacklem{
495244008Srmacklem	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
496244008Srmacklem	struct mbuf *m, *m2;
497244008Srmacklem
498244008Srmacklem	svc_xprt_free(xprt);
499244008Srmacklem	m = cd->mreq;
500244008Srmacklem	while (m != NULL) {
501244008Srmacklem		m2 = m;
502244008Srmacklem		m = m->m_nextpkt;
503244008Srmacklem		m_freem(m2);
504244008Srmacklem	}
505244008Srmacklem	mem_free(cd, sizeof(*cd));
506244008Srmacklem}
507244008Srmacklem
508177633Sdfr/*ARGSUSED*/
509177633Sdfrstatic bool_t
510177633Sdfrsvc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
511177633Sdfr{
512177633Sdfr	return (FALSE);
513177633Sdfr}
514177633Sdfr
515177633Sdfrstatic bool_t
516177633Sdfrsvc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
517177633Sdfr{
518177633Sdfr
519177633Sdfr	return (FALSE);
520177633Sdfr}
521177633Sdfr
522244008Srmacklemstatic bool_t
523244008Srmacklemsvc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, void *in)
524244008Srmacklem{
525244008Srmacklem
526244008Srmacklem	return (FALSE);
527244008Srmacklem}
528244008Srmacklem
529177633Sdfrstatic enum xprt_stat
530177633Sdfrsvc_vc_stat(SVCXPRT *xprt)
531177633Sdfr{
532177633Sdfr	struct cf_conn *cd;
533177633Sdfr
534177633Sdfr	cd = (struct cf_conn *)(xprt->xp_p1);
535177633Sdfr
536177633Sdfr	if (cd->strm_stat == XPRT_DIED)
537177633Sdfr		return (XPRT_DIED);
538177633Sdfr
539261047Smav	if (cd->mreq != NULL && cd->resid == 0 && cd->eor)
540261047Smav		return (XPRT_MOREREQS);
541177633Sdfr
542184588Sdfr	if (soreadable(xprt->xp_socket))
543184588Sdfr		return (XPRT_MOREREQS);
544184588Sdfr
545177633Sdfr	return (XPRT_IDLE);
546177633Sdfr}
547177633Sdfr
548261055Smavstatic bool_t
549261055Smavsvc_vc_ack(SVCXPRT *xprt, uint32_t *ack)
550261055Smav{
551261055Smav
552261055Smav	*ack = atomic_load_acq_32(&xprt->xp_snt_cnt);
553261055Smav	*ack -= xprt->xp_socket->so_snd.sb_cc;
554261055Smav	return (TRUE);
555261055Smav}
556261055Smav
557244008Srmacklemstatic enum xprt_stat
558244008Srmacklemsvc_vc_backchannel_stat(SVCXPRT *xprt)
559244008Srmacklem{
560244008Srmacklem	struct cf_conn *cd;
561244008Srmacklem
562244008Srmacklem	cd = (struct cf_conn *)(xprt->xp_p1);
563244008Srmacklem
564244008Srmacklem	if (cd->mreq != NULL)
565244008Srmacklem		return (XPRT_MOREREQS);
566244008Srmacklem
567244008Srmacklem	return (XPRT_IDLE);
568244008Srmacklem}
569244008Srmacklem
570261047Smav/*
571261047Smav * If we have an mbuf chain in cd->mpending, try to parse a record from it,
572261047Smav * leaving the result in cd->mreq. If we don't have a complete record, leave
573261047Smav * the partial result in cd->mreq and try to read more from the socket.
574261047Smav */
575261050Smavstatic int
576261047Smavsvc_vc_process_pending(SVCXPRT *xprt)
577261047Smav{
578261047Smav	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
579261047Smav	struct socket *so = xprt->xp_socket;
580261047Smav	struct mbuf *m;
581261047Smav
582261047Smav	/*
583261047Smav	 * If cd->resid is non-zero, we have part of the
584261047Smav	 * record already, otherwise we are expecting a record
585261047Smav	 * marker.
586261047Smav	 */
587261047Smav	if (!cd->resid && cd->mpending) {
588261047Smav		/*
589261047Smav		 * See if there is enough data buffered to
590261047Smav		 * make up a record marker. Make sure we can
591261047Smav		 * handle the case where the record marker is
592261047Smav		 * split across more than one mbuf.
593261047Smav		 */
594261047Smav		size_t n = 0;
595261047Smav		uint32_t header;
596261047Smav
597261047Smav		m = cd->mpending;
598261047Smav		while (n < sizeof(uint32_t) && m) {
599261047Smav			n += m->m_len;
600261047Smav			m = m->m_next;
601261047Smav		}
602261047Smav		if (n < sizeof(uint32_t)) {
603261047Smav			so->so_rcv.sb_lowat = sizeof(uint32_t) - n;
604261050Smav			return (FALSE);
605261047Smav		}
606261047Smav		m_copydata(cd->mpending, 0, sizeof(header),
607261047Smav		    (char *)&header);
608261047Smav		header = ntohl(header);
609261047Smav		cd->eor = (header & 0x80000000) != 0;
610261047Smav		cd->resid = header & 0x7fffffff;
611261047Smav		m_adj(cd->mpending, sizeof(uint32_t));
612261047Smav	}
613261047Smav
614261047Smav	/*
615261047Smav	 * Start pulling off mbufs from cd->mpending
616261047Smav	 * until we either have a complete record or
617261047Smav	 * we run out of data. We use m_split to pull
618261047Smav	 * data - it will pull as much as possible and
619261047Smav	 * split the last mbuf if necessary.
620261047Smav	 */
621261047Smav	while (cd->mpending && cd->resid) {
622261047Smav		m = cd->mpending;
623261047Smav		if (cd->mpending->m_next
624261047Smav		    || cd->mpending->m_len > cd->resid)
625261047Smav			cd->mpending = m_split(cd->mpending,
626261047Smav			    cd->resid, M_WAITOK);
627261047Smav		else
628261047Smav			cd->mpending = NULL;
629261047Smav		if (cd->mreq)
630261047Smav			m_last(cd->mreq)->m_next = m;
631261047Smav		else
632261047Smav			cd->mreq = m;
633261047Smav		while (m) {
634261047Smav			cd->resid -= m->m_len;
635261047Smav			m = m->m_next;
636261047Smav		}
637261047Smav	}
638261047Smav
639261052Smav	/*
640261052Smav	 * Block receive upcalls if we have more data pending,
641261052Smav	 * otherwise report our need.
642261052Smav	 */
643261052Smav	if (cd->mpending)
644261052Smav		so->so_rcv.sb_lowat = INT_MAX;
645261052Smav	else
646261052Smav		so->so_rcv.sb_lowat =
647261052Smav		    imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2));
648261050Smav	return (TRUE);
649261047Smav}
650261047Smav
651177633Sdfrstatic bool_t
652184588Sdfrsvc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
653184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
654177633Sdfr{
655177633Sdfr	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
656177633Sdfr	struct uio uio;
657177633Sdfr	struct mbuf *m;
658261047Smav	struct socket* so = xprt->xp_socket;
659184588Sdfr	XDR xdrs;
660177633Sdfr	int error, rcvflag;
661269398Srmacklem	uint32_t xid_plus_direction[2];
662177633Sdfr
663184588Sdfr	/*
664184588Sdfr	 * Serialise access to the socket and our own record parsing
665184588Sdfr	 * state.
666184588Sdfr	 */
667184588Sdfr	sx_xlock(&xprt->xp_lock);
668184588Sdfr
669177633Sdfr	for (;;) {
670261047Smav		/* If we have no request ready, check pending queue. */
671261047Smav		while (cd->mpending &&
672261050Smav		    (cd->mreq == NULL || cd->resid != 0 || !cd->eor)) {
673261050Smav			if (!svc_vc_process_pending(xprt))
674261050Smav				break;
675261050Smav		}
676177633Sdfr
677261047Smav		/* Process and return complete request in cd->mreq. */
678261047Smav		if (cd->mreq != NULL && cd->resid == 0 && cd->eor) {
679177633Sdfr
680269398Srmacklem			/*
681269398Srmacklem			 * Now, check for a backchannel reply.
682269398Srmacklem			 * The XID is in the first uint32_t of the reply
683269398Srmacklem			 * and the message direction is the second one.
684269398Srmacklem			 */
685269398Srmacklem			if ((cd->mreq->m_len >= sizeof(xid_plus_direction) ||
686269398Srmacklem			    m_length(cd->mreq, NULL) >=
687269398Srmacklem			    sizeof(xid_plus_direction)) &&
688269398Srmacklem			    xprt->xp_p2 != NULL) {
689269398Srmacklem				m_copydata(cd->mreq, 0,
690269398Srmacklem				    sizeof(xid_plus_direction),
691269398Srmacklem				    (char *)xid_plus_direction);
692269398Srmacklem				xid_plus_direction[0] =
693269398Srmacklem				    ntohl(xid_plus_direction[0]);
694269398Srmacklem				xid_plus_direction[1] =
695269398Srmacklem				    ntohl(xid_plus_direction[1]);
696269398Srmacklem				/* Check message direction. */
697269398Srmacklem				if (xid_plus_direction[1] == REPLY) {
698269398Srmacklem					clnt_bck_svccall(xprt->xp_p2,
699269398Srmacklem					    cd->mreq,
700269398Srmacklem					    xid_plus_direction[0]);
701269398Srmacklem					cd->mreq = NULL;
702269398Srmacklem					continue;
703269398Srmacklem				}
704269398Srmacklem			}
705269398Srmacklem
706261047Smav			xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
707261047Smav			cd->mreq = NULL;
708261047Smav
709261047Smav			/* Check for next request in a pending queue. */
710261047Smav			svc_vc_process_pending(xprt);
711261047Smav			if (cd->mreq == NULL || cd->resid != 0) {
712261047Smav				SOCKBUF_LOCK(&so->so_rcv);
713261047Smav				if (!soreadable(so))
714261053Smav					xprt_inactive_self(xprt);
715261047Smav				SOCKBUF_UNLOCK(&so->so_rcv);
716177633Sdfr			}
717177633Sdfr
718261047Smav			sx_xunlock(&xprt->xp_lock);
719177633Sdfr
720261047Smav			if (! xdr_callmsg(&xdrs, msg)) {
721261047Smav				XDR_DESTROY(&xdrs);
722261047Smav				return (FALSE);
723261047Smav			}
724184588Sdfr
725261047Smav			*addrp = NULL;
726261047Smav			*mp = xdrmbuf_getall(&xdrs);
727261047Smav			XDR_DESTROY(&xdrs);
728177633Sdfr
729261047Smav			return (TRUE);
730177633Sdfr		}
731177633Sdfr
732177633Sdfr		/*
733177633Sdfr		 * The socket upcall calls xprt_active() which will eventually
734177633Sdfr		 * cause the server to call us here. We attempt to
735177633Sdfr		 * read as much as possible from the socket and put
736177633Sdfr		 * the result in cd->mpending. If the read fails,
737177633Sdfr		 * we have drained both cd->mpending and the socket so
738177633Sdfr		 * we can call xprt_inactive().
739177633Sdfr		 */
740177633Sdfr		uio.uio_resid = 1000000000;
741177633Sdfr		uio.uio_td = curthread;
742177633Sdfr		m = NULL;
743177633Sdfr		rcvflag = MSG_DONTWAIT;
744261047Smav		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
745177633Sdfr
746177633Sdfr		if (error == EWOULDBLOCK) {
747184588Sdfr			/*
748184588Sdfr			 * We must re-test for readability after
749184588Sdfr			 * taking the lock to protect us in the case
750184588Sdfr			 * where a new packet arrives on the socket
751184588Sdfr			 * after our call to soreceive fails with
752261047Smav			 * EWOULDBLOCK.
753184588Sdfr			 */
754261047Smav			SOCKBUF_LOCK(&so->so_rcv);
755261047Smav			if (!soreadable(so))
756261053Smav				xprt_inactive_self(xprt);
757261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
758184588Sdfr			sx_xunlock(&xprt->xp_lock);
759177633Sdfr			return (FALSE);
760177633Sdfr		}
761177633Sdfr
762177633Sdfr		if (error) {
763261047Smav			SOCKBUF_LOCK(&so->so_rcv);
764193436Srmacklem			if (xprt->xp_upcallset) {
765193436Srmacklem				xprt->xp_upcallset = 0;
766261047Smav				soupcall_clear(so, SO_RCV);
767193436Srmacklem			}
768261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
769261053Smav			xprt_inactive_self(xprt);
770177633Sdfr			cd->strm_stat = XPRT_DIED;
771184588Sdfr			sx_xunlock(&xprt->xp_lock);
772177633Sdfr			return (FALSE);
773177633Sdfr		}
774177633Sdfr
775177633Sdfr		if (!m) {
776177633Sdfr			/*
777177633Sdfr			 * EOF - the other end has closed the socket.
778177633Sdfr			 */
779261053Smav			xprt_inactive_self(xprt);
780177633Sdfr			cd->strm_stat = XPRT_DIED;
781184588Sdfr			sx_xunlock(&xprt->xp_lock);
782177633Sdfr			return (FALSE);
783177633Sdfr		}
784177633Sdfr
785177633Sdfr		if (cd->mpending)
786177633Sdfr			m_last(cd->mpending)->m_next = m;
787177633Sdfr		else
788177633Sdfr			cd->mpending = m;
789177633Sdfr	}
790177633Sdfr}
791177633Sdfr
792177633Sdfrstatic bool_t
793244008Srmacklemsvc_vc_backchannel_recv(SVCXPRT *xprt, struct rpc_msg *msg,
794244008Srmacklem    struct sockaddr **addrp, struct mbuf **mp)
795244008Srmacklem{
796244008Srmacklem	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
797244008Srmacklem	struct ct_data *ct;
798244008Srmacklem	struct mbuf *m;
799244008Srmacklem	XDR xdrs;
800244008Srmacklem
801244008Srmacklem	sx_xlock(&xprt->xp_lock);
802244008Srmacklem	ct = (struct ct_data *)xprt->xp_p2;
803244008Srmacklem	if (ct == NULL) {
804244008Srmacklem		sx_xunlock(&xprt->xp_lock);
805244008Srmacklem		return (FALSE);
806244008Srmacklem	}
807244008Srmacklem	mtx_lock(&ct->ct_lock);
808244008Srmacklem	m = cd->mreq;
809244008Srmacklem	if (m == NULL) {
810261053Smav		xprt_inactive_self(xprt);
811244008Srmacklem		mtx_unlock(&ct->ct_lock);
812244008Srmacklem		sx_xunlock(&xprt->xp_lock);
813244008Srmacklem		return (FALSE);
814244008Srmacklem	}
815244008Srmacklem	cd->mreq = m->m_nextpkt;
816244008Srmacklem	mtx_unlock(&ct->ct_lock);
817244008Srmacklem	sx_xunlock(&xprt->xp_lock);
818244008Srmacklem
819244008Srmacklem	xdrmbuf_create(&xdrs, m, XDR_DECODE);
820244008Srmacklem	if (! xdr_callmsg(&xdrs, msg)) {
821244008Srmacklem		XDR_DESTROY(&xdrs);
822244008Srmacklem		return (FALSE);
823244008Srmacklem	}
824244008Srmacklem	*addrp = NULL;
825244008Srmacklem	*mp = xdrmbuf_getall(&xdrs);
826244008Srmacklem	XDR_DESTROY(&xdrs);
827244008Srmacklem	return (TRUE);
828244008Srmacklem}
829244008Srmacklem
830244008Srmacklemstatic bool_t
831184588Sdfrsvc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
832261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
833177633Sdfr{
834177633Sdfr	XDR xdrs;
835177633Sdfr	struct mbuf *mrep;
836184588Sdfr	bool_t stat = TRUE;
837261055Smav	int error, len;
838177633Sdfr
839177633Sdfr	/*
840177633Sdfr	 * Leave space for record mark.
841177633Sdfr	 */
842248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
843177633Sdfr	mrep->m_data += sizeof(uint32_t);
844177633Sdfr
845184588Sdfr	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
846184588Sdfr
847184588Sdfr	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
848184588Sdfr	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
849184588Sdfr		if (!xdr_replymsg(&xdrs, msg))
850184588Sdfr			stat = FALSE;
851184588Sdfr		else
852184588Sdfr			xdrmbuf_append(&xdrs, m);
853184588Sdfr	} else {
854184588Sdfr		stat = xdr_replymsg(&xdrs, msg);
855184588Sdfr	}
856184588Sdfr
857184588Sdfr	if (stat) {
858177633Sdfr		m_fixhdr(mrep);
859177633Sdfr
860177633Sdfr		/*
861177633Sdfr		 * Prepend a record marker containing the reply length.
862177633Sdfr		 */
863243882Sglebius		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
864261055Smav		len = mrep->m_pkthdr.len;
865177633Sdfr		*mtod(mrep, uint32_t *) =
866261055Smav			htonl(0x80000000 | (len - sizeof(uint32_t)));
867261055Smav		atomic_add_acq_32(&xprt->xp_snd_cnt, len);
868177633Sdfr		error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL,
869177633Sdfr		    0, curthread);
870177633Sdfr		if (!error) {
871261055Smav			atomic_add_rel_32(&xprt->xp_snt_cnt, len);
872261055Smav			if (seq)
873261055Smav				*seq = xprt->xp_snd_cnt;
874177633Sdfr			stat = TRUE;
875261055Smav		} else
876261055Smav			atomic_subtract_32(&xprt->xp_snd_cnt, len);
877177633Sdfr	} else {
878177633Sdfr		m_freem(mrep);
879177633Sdfr	}
880177633Sdfr
881184588Sdfr	XDR_DESTROY(&xdrs);
882177633Sdfr
883177633Sdfr	return (stat);
884177633Sdfr}
885177633Sdfr
886177633Sdfrstatic bool_t
887244008Srmacklemsvc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg,
888261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
889244008Srmacklem{
890244008Srmacklem	struct ct_data *ct;
891244008Srmacklem	XDR xdrs;
892244008Srmacklem	struct mbuf *mrep;
893244008Srmacklem	bool_t stat = TRUE;
894244008Srmacklem	int error;
895244008Srmacklem
896244008Srmacklem	/*
897244008Srmacklem	 * Leave space for record mark.
898244008Srmacklem	 */
899248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
900244008Srmacklem	mrep->m_data += sizeof(uint32_t);
901244008Srmacklem
902244008Srmacklem	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
903244008Srmacklem
904244008Srmacklem	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
905244008Srmacklem	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
906244008Srmacklem		if (!xdr_replymsg(&xdrs, msg))
907244008Srmacklem			stat = FALSE;
908244008Srmacklem		else
909244008Srmacklem			xdrmbuf_append(&xdrs, m);
910244008Srmacklem	} else {
911244008Srmacklem		stat = xdr_replymsg(&xdrs, msg);
912244008Srmacklem	}
913244008Srmacklem
914244008Srmacklem	if (stat) {
915244008Srmacklem		m_fixhdr(mrep);
916244008Srmacklem
917244008Srmacklem		/*
918244008Srmacklem		 * Prepend a record marker containing the reply length.
919244008Srmacklem		 */
920244008Srmacklem		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
921244008Srmacklem		*mtod(mrep, uint32_t *) =
922244008Srmacklem			htonl(0x80000000 | (mrep->m_pkthdr.len
923244008Srmacklem				- sizeof(uint32_t)));
924244008Srmacklem		sx_xlock(&xprt->xp_lock);
925244008Srmacklem		ct = (struct ct_data *)xprt->xp_p2;
926244008Srmacklem		if (ct != NULL)
927244008Srmacklem			error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL,
928244008Srmacklem			    0, curthread);
929244008Srmacklem		else
930244008Srmacklem			error = EPIPE;
931244008Srmacklem		sx_xunlock(&xprt->xp_lock);
932244008Srmacklem		if (!error) {
933244008Srmacklem			stat = TRUE;
934244008Srmacklem		}
935244008Srmacklem	} else {
936244008Srmacklem		m_freem(mrep);
937244008Srmacklem	}
938244008Srmacklem
939244008Srmacklem	XDR_DESTROY(&xdrs);
940244008Srmacklem
941244008Srmacklem	return (stat);
942244008Srmacklem}
943244008Srmacklem
944244008Srmacklemstatic bool_t
945177633Sdfrsvc_vc_null()
946177633Sdfr{
947177633Sdfr
948177633Sdfr	return (FALSE);
949177633Sdfr}
950177633Sdfr
951193272Sjhbstatic int
952177633Sdfrsvc_vc_soupcall(struct socket *so, void *arg, int waitflag)
953177633Sdfr{
954177633Sdfr	SVCXPRT *xprt = (SVCXPRT *) arg;
955177633Sdfr
956261047Smav	if (soreadable(xprt->xp_socket))
957261047Smav		xprt_active(xprt);
958193272Sjhb	return (SU_OK);
959177633Sdfr}
960177633Sdfr
961177633Sdfr#if 0
962177633Sdfr/*
963177633Sdfr * Get the effective UID of the sending process. Used by rpcbind, keyserv
964177633Sdfr * and rpc.yppasswdd on AF_LOCAL.
965177633Sdfr */
966177633Sdfrint
967177633Sdfr__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
968177633Sdfr	int sock, ret;
969177633Sdfr	gid_t egid;
970177633Sdfr	uid_t euid;
971177633Sdfr	struct sockaddr *sa;
972177633Sdfr
973177633Sdfr	sock = transp->xp_fd;
974184588Sdfr	sa = (struct sockaddr *)transp->xp_rtaddr;
975177633Sdfr	if (sa->sa_family == AF_LOCAL) {
976177633Sdfr		ret = getpeereid(sock, &euid, &egid);
977177633Sdfr		if (ret == 0)
978177633Sdfr			*uid = euid;
979177633Sdfr		return (ret);
980177633Sdfr	} else
981177633Sdfr		return (-1);
982177633Sdfr}
983177633Sdfr#endif
984