svc_vc.c revision 281520
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 281520 2015-04-14 09:58:10Z mav $");
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);
153180025Sdfr		error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
154180025Sdfr		if (error)
155180025Sdfr			return (NULL);
156180025Sdfr		xprt = svc_vc_create_conn(pool, so, sa);
157180025Sdfr		free(sa, M_SONAME);
158180025Sdfr		return (xprt);
159180025Sdfr	}
160249263Sjhb	SOCK_UNLOCK(so);
161180025Sdfr
162184588Sdfr	xprt = svc_xprt_alloc();
163184588Sdfr	sx_init(&xprt->xp_lock, "xprt->xp_lock");
164177633Sdfr	xprt->xp_pool = pool;
165177633Sdfr	xprt->xp_socket = so;
166177633Sdfr	xprt->xp_p1 = NULL;
167177633Sdfr	xprt->xp_p2 = NULL;
168177633Sdfr	xprt->xp_ops = &svc_vc_rendezvous_ops;
169177633Sdfr
170177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
171196503Szec	if (error) {
172177633Sdfr		goto cleanup_svc_vc_create;
173196503Szec	}
174177633Sdfr
175184588Sdfr	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
176177633Sdfr	free(sa, M_SONAME);
177177633Sdfr
178177633Sdfr	xprt_register(xprt);
179177633Sdfr
180281520Smav	solisten(so, -1, curthread);
181177633Sdfr
182177633Sdfr	SOCKBUF_LOCK(&so->so_rcv);
183193436Srmacklem	xprt->xp_upcallset = 1;
184193272Sjhb	soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt);
185177633Sdfr	SOCKBUF_UNLOCK(&so->so_rcv);
186177633Sdfr
187177633Sdfr	return (xprt);
188177633Sdfrcleanup_svc_vc_create:
189261055Smav	if (xprt) {
190261055Smav		sx_destroy(&xprt->xp_lock);
191184588Sdfr		svc_xprt_free(xprt);
192261055Smav	}
193177633Sdfr	return (NULL);
194177633Sdfr}
195177633Sdfr
196177633Sdfr/*
197177633Sdfr * Create a new transport for a socket optained via soaccept().
198177633Sdfr */
199177633SdfrSVCXPRT *
200177633Sdfrsvc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
201177633Sdfr{
202177633Sdfr	SVCXPRT *xprt = NULL;
203177633Sdfr	struct cf_conn *cd = NULL;
204177633Sdfr	struct sockaddr* sa = NULL;
205180025Sdfr	struct sockopt opt;
206180025Sdfr	int one = 1;
207177633Sdfr	int error;
208177633Sdfr
209180025Sdfr	bzero(&opt, sizeof(struct sockopt));
210180025Sdfr	opt.sopt_dir = SOPT_SET;
211180025Sdfr	opt.sopt_level = SOL_SOCKET;
212180025Sdfr	opt.sopt_name = SO_KEEPALIVE;
213180025Sdfr	opt.sopt_val = &one;
214180025Sdfr	opt.sopt_valsize = sizeof(one);
215180025Sdfr	error = sosetopt(so, &opt);
216196503Szec	if (error) {
217180025Sdfr		return (NULL);
218196503Szec	}
219180025Sdfr
220180025Sdfr	if (so->so_proto->pr_protocol == IPPROTO_TCP) {
221180025Sdfr		bzero(&opt, sizeof(struct sockopt));
222180025Sdfr		opt.sopt_dir = SOPT_SET;
223180025Sdfr		opt.sopt_level = IPPROTO_TCP;
224180025Sdfr		opt.sopt_name = TCP_NODELAY;
225180025Sdfr		opt.sopt_val = &one;
226180025Sdfr		opt.sopt_valsize = sizeof(one);
227180025Sdfr		error = sosetopt(so, &opt);
228196503Szec		if (error) {
229180025Sdfr			return (NULL);
230196503Szec		}
231180025Sdfr	}
232180025Sdfr
233177633Sdfr	cd = mem_alloc(sizeof(*cd));
234177633Sdfr	cd->strm_stat = XPRT_IDLE;
235177633Sdfr
236184588Sdfr	xprt = svc_xprt_alloc();
237184588Sdfr	sx_init(&xprt->xp_lock, "xprt->xp_lock");
238177633Sdfr	xprt->xp_pool = pool;
239177633Sdfr	xprt->xp_socket = so;
240177633Sdfr	xprt->xp_p1 = cd;
241177633Sdfr	xprt->xp_p2 = NULL;
242177633Sdfr	xprt->xp_ops = &svc_vc_ops;
243177633Sdfr
244184588Sdfr	/*
245184588Sdfr	 * See http://www.connectathon.org/talks96/nfstcp.pdf - client
246184588Sdfr	 * has a 5 minute timer, server has a 6 minute timer.
247184588Sdfr	 */
248184588Sdfr	xprt->xp_idletimeout = 6 * 60;
249177633Sdfr
250184588Sdfr	memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len);
251184588Sdfr
252177633Sdfr	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
253177633Sdfr	if (error)
254177633Sdfr		goto cleanup_svc_vc_create;
255177633Sdfr
256184588Sdfr	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
257177633Sdfr	free(sa, M_SONAME);
258177633Sdfr
259177633Sdfr	xprt_register(xprt);
260177633Sdfr
261177633Sdfr	SOCKBUF_LOCK(&so->so_rcv);
262193436Srmacklem	xprt->xp_upcallset = 1;
263193272Sjhb	soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt);
264177633Sdfr	SOCKBUF_UNLOCK(&so->so_rcv);
265177633Sdfr
266177633Sdfr	/*
267177633Sdfr	 * Throw the transport into the active list in case it already
268177633Sdfr	 * has some data buffered.
269177633Sdfr	 */
270184588Sdfr	sx_xlock(&xprt->xp_lock);
271177633Sdfr	xprt_active(xprt);
272184588Sdfr	sx_xunlock(&xprt->xp_lock);
273177633Sdfr
274177633Sdfr	return (xprt);
275177633Sdfrcleanup_svc_vc_create:
276177633Sdfr	if (xprt) {
277261055Smav		sx_destroy(&xprt->xp_lock);
278261055Smav		svc_xprt_free(xprt);
279177633Sdfr	}
280177633Sdfr	if (cd)
281177633Sdfr		mem_free(cd, sizeof(*cd));
282177633Sdfr	return (NULL);
283177633Sdfr}
284177633Sdfr
285177633Sdfr/*
286244008Srmacklem * Create a new transport for a backchannel on a clnt_vc socket.
287244008Srmacklem */
288244008SrmacklemSVCXPRT *
289244008Srmacklemsvc_vc_create_backchannel(SVCPOOL *pool)
290244008Srmacklem{
291244008Srmacklem	SVCXPRT *xprt = NULL;
292244008Srmacklem	struct cf_conn *cd = NULL;
293244008Srmacklem
294244008Srmacklem	cd = mem_alloc(sizeof(*cd));
295244008Srmacklem	cd->strm_stat = XPRT_IDLE;
296244008Srmacklem
297244008Srmacklem	xprt = svc_xprt_alloc();
298244008Srmacklem	sx_init(&xprt->xp_lock, "xprt->xp_lock");
299244008Srmacklem	xprt->xp_pool = pool;
300244008Srmacklem	xprt->xp_socket = NULL;
301244008Srmacklem	xprt->xp_p1 = cd;
302244008Srmacklem	xprt->xp_p2 = NULL;
303244008Srmacklem	xprt->xp_ops = &svc_vc_backchannel_ops;
304244008Srmacklem	return (xprt);
305244008Srmacklem}
306244008Srmacklem
307244008Srmacklem/*
308177633Sdfr * This does all of the accept except the final call to soaccept. The
309177633Sdfr * caller will call soaccept after dropping its locks (soaccept may
310177633Sdfr * call malloc).
311177633Sdfr */
312177633Sdfrint
313177633Sdfrsvc_vc_accept(struct socket *head, struct socket **sop)
314177633Sdfr{
315177633Sdfr	int error = 0;
316177633Sdfr	struct socket *so;
317177633Sdfr
318177633Sdfr	if ((head->so_options & SO_ACCEPTCONN) == 0) {
319177633Sdfr		error = EINVAL;
320177633Sdfr		goto done;
321177633Sdfr	}
322177633Sdfr#ifdef MAC
323193509Srwatson	error = mac_socket_check_accept(curthread->td_ucred, head);
324177633Sdfr	if (error != 0)
325177633Sdfr		goto done;
326177633Sdfr#endif
327177633Sdfr	ACCEPT_LOCK();
328177633Sdfr	if (TAILQ_EMPTY(&head->so_comp)) {
329177633Sdfr		ACCEPT_UNLOCK();
330177633Sdfr		error = EWOULDBLOCK;
331177633Sdfr		goto done;
332177633Sdfr	}
333177633Sdfr	so = TAILQ_FIRST(&head->so_comp);
334177633Sdfr	KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP"));
335177633Sdfr	KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP"));
336177633Sdfr
337177633Sdfr	/*
338177633Sdfr	 * Before changing the flags on the socket, we have to bump the
339177633Sdfr	 * reference count.  Otherwise, if the protocol calls sofree(),
340177633Sdfr	 * the socket will be released due to a zero refcount.
341177633Sdfr	 * XXX might not need soref() since this is simpler than kern_accept.
342177633Sdfr	 */
343177633Sdfr	SOCK_LOCK(so);			/* soref() and so_state update */
344177633Sdfr	soref(so);			/* file descriptor reference */
345177633Sdfr
346177633Sdfr	TAILQ_REMOVE(&head->so_comp, so, so_list);
347177633Sdfr	head->so_qlen--;
348177633Sdfr	so->so_state |= (head->so_state & SS_NBIO);
349177633Sdfr	so->so_qstate &= ~SQ_COMP;
350177633Sdfr	so->so_head = NULL;
351177633Sdfr
352177633Sdfr	SOCK_UNLOCK(so);
353177633Sdfr	ACCEPT_UNLOCK();
354177633Sdfr
355177633Sdfr	*sop = so;
356177633Sdfr
357177633Sdfr	/* connection has been removed from the listen queue */
358177633Sdfr	KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);
359177633Sdfrdone:
360177633Sdfr	return (error);
361177633Sdfr}
362177633Sdfr
363177633Sdfr/*ARGSUSED*/
364177633Sdfrstatic bool_t
365184588Sdfrsvc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg,
366184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
367177633Sdfr{
368177633Sdfr	struct socket *so = NULL;
369177633Sdfr	struct sockaddr *sa = NULL;
370177633Sdfr	int error;
371194407Srmacklem	SVCXPRT *new_xprt;
372177633Sdfr
373177633Sdfr	/*
374177633Sdfr	 * The socket upcall calls xprt_active() which will eventually
375177633Sdfr	 * cause the server to call us here. We attempt to accept a
376177633Sdfr	 * connection from the socket and turn it into a new
377177633Sdfr	 * transport. If the accept fails, we have drained all pending
378177633Sdfr	 * connections so we call xprt_inactive().
379177633Sdfr	 */
380184588Sdfr	sx_xlock(&xprt->xp_lock);
381177633Sdfr
382177633Sdfr	error = svc_vc_accept(xprt->xp_socket, &so);
383177633Sdfr
384177633Sdfr	if (error == EWOULDBLOCK) {
385184588Sdfr		/*
386184588Sdfr		 * We must re-test for new connections after taking
387184588Sdfr		 * the lock to protect us in the case where a new
388184588Sdfr		 * connection arrives after our call to accept fails
389261047Smav		 * with EWOULDBLOCK.
390184588Sdfr		 */
391184588Sdfr		ACCEPT_LOCK();
392184588Sdfr		if (TAILQ_EMPTY(&xprt->xp_socket->so_comp))
393261053Smav			xprt_inactive_self(xprt);
394184588Sdfr		ACCEPT_UNLOCK();
395184588Sdfr		sx_xunlock(&xprt->xp_lock);
396177633Sdfr		return (FALSE);
397177633Sdfr	}
398177633Sdfr
399177633Sdfr	if (error) {
400177633Sdfr		SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
401193436Srmacklem		if (xprt->xp_upcallset) {
402193436Srmacklem			xprt->xp_upcallset = 0;
403193436Srmacklem			soupcall_clear(xprt->xp_socket, SO_RCV);
404193436Srmacklem		}
405177633Sdfr		SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
406261053Smav		xprt_inactive_self(xprt);
407184588Sdfr		sx_xunlock(&xprt->xp_lock);
408177633Sdfr		return (FALSE);
409177633Sdfr	}
410177633Sdfr
411184588Sdfr	sx_xunlock(&xprt->xp_lock);
412177633Sdfr
413177633Sdfr	sa = 0;
414177633Sdfr	error = soaccept(so, &sa);
415177633Sdfr
416177633Sdfr	if (error) {
417177633Sdfr		/*
418177633Sdfr		 * XXX not sure if I need to call sofree or soclose here.
419177633Sdfr		 */
420177633Sdfr		if (sa)
421177633Sdfr			free(sa, M_SONAME);
422177633Sdfr		return (FALSE);
423177633Sdfr	}
424177633Sdfr
425177633Sdfr	/*
426177633Sdfr	 * svc_vc_create_conn will call xprt_register - we don't need
427194407Srmacklem	 * to do anything with the new connection except derefence it.
428177633Sdfr	 */
429194407Srmacklem	new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa);
430194407Srmacklem	if (!new_xprt) {
431180025Sdfr		soclose(so);
432194407Srmacklem	} else {
433194407Srmacklem		SVC_RELEASE(new_xprt);
434194407Srmacklem	}
435180025Sdfr
436177633Sdfr	free(sa, M_SONAME);
437177633Sdfr
438177633Sdfr	return (FALSE); /* there is never an rpc msg to be processed */
439177633Sdfr}
440177633Sdfr
441177633Sdfr/*ARGSUSED*/
442177633Sdfrstatic enum xprt_stat
443177633Sdfrsvc_vc_rendezvous_stat(SVCXPRT *xprt)
444177633Sdfr{
445177633Sdfr
446177633Sdfr	return (XPRT_IDLE);
447177633Sdfr}
448177633Sdfr
449177633Sdfrstatic void
450177633Sdfrsvc_vc_destroy_common(SVCXPRT *xprt)
451177633Sdfr{
452177633Sdfr	SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
453193436Srmacklem	if (xprt->xp_upcallset) {
454193436Srmacklem		xprt->xp_upcallset = 0;
455193436Srmacklem		soupcall_clear(xprt->xp_socket, SO_RCV);
456193436Srmacklem	}
457177633Sdfr	SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
458177633Sdfr
459177633Sdfr	if (xprt->xp_socket)
460177633Sdfr		(void)soclose(xprt->xp_socket);
461177633Sdfr
462184588Sdfr	if (xprt->xp_netid)
463184588Sdfr		(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
464184588Sdfr	svc_xprt_free(xprt);
465177633Sdfr}
466177633Sdfr
467177633Sdfrstatic void
468177633Sdfrsvc_vc_rendezvous_destroy(SVCXPRT *xprt)
469177633Sdfr{
470177633Sdfr
471177633Sdfr	svc_vc_destroy_common(xprt);
472177633Sdfr}
473177633Sdfr
474177633Sdfrstatic void
475177633Sdfrsvc_vc_destroy(SVCXPRT *xprt)
476177633Sdfr{
477177633Sdfr	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
478177633Sdfr
479177633Sdfr	svc_vc_destroy_common(xprt);
480177633Sdfr
481177633Sdfr	if (cd->mreq)
482177633Sdfr		m_freem(cd->mreq);
483177633Sdfr	if (cd->mpending)
484177633Sdfr		m_freem(cd->mpending);
485177633Sdfr	mem_free(cd, sizeof(*cd));
486177633Sdfr}
487177633Sdfr
488244008Srmacklemstatic void
489244008Srmacklemsvc_vc_backchannel_destroy(SVCXPRT *xprt)
490244008Srmacklem{
491244008Srmacklem	struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1;
492244008Srmacklem	struct mbuf *m, *m2;
493244008Srmacklem
494244008Srmacklem	svc_xprt_free(xprt);
495244008Srmacklem	m = cd->mreq;
496244008Srmacklem	while (m != NULL) {
497244008Srmacklem		m2 = m;
498244008Srmacklem		m = m->m_nextpkt;
499244008Srmacklem		m_freem(m2);
500244008Srmacklem	}
501244008Srmacklem	mem_free(cd, sizeof(*cd));
502244008Srmacklem}
503244008Srmacklem
504177633Sdfr/*ARGSUSED*/
505177633Sdfrstatic bool_t
506177633Sdfrsvc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
507177633Sdfr{
508177633Sdfr	return (FALSE);
509177633Sdfr}
510177633Sdfr
511177633Sdfrstatic bool_t
512177633Sdfrsvc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
513177633Sdfr{
514177633Sdfr
515177633Sdfr	return (FALSE);
516177633Sdfr}
517177633Sdfr
518244008Srmacklemstatic bool_t
519244008Srmacklemsvc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, void *in)
520244008Srmacklem{
521244008Srmacklem
522244008Srmacklem	return (FALSE);
523244008Srmacklem}
524244008Srmacklem
525177633Sdfrstatic enum xprt_stat
526177633Sdfrsvc_vc_stat(SVCXPRT *xprt)
527177633Sdfr{
528177633Sdfr	struct cf_conn *cd;
529177633Sdfr
530177633Sdfr	cd = (struct cf_conn *)(xprt->xp_p1);
531177633Sdfr
532177633Sdfr	if (cd->strm_stat == XPRT_DIED)
533177633Sdfr		return (XPRT_DIED);
534177633Sdfr
535261047Smav	if (cd->mreq != NULL && cd->resid == 0 && cd->eor)
536261047Smav		return (XPRT_MOREREQS);
537177633Sdfr
538184588Sdfr	if (soreadable(xprt->xp_socket))
539184588Sdfr		return (XPRT_MOREREQS);
540184588Sdfr
541177633Sdfr	return (XPRT_IDLE);
542177633Sdfr}
543177633Sdfr
544261055Smavstatic bool_t
545261055Smavsvc_vc_ack(SVCXPRT *xprt, uint32_t *ack)
546261055Smav{
547261055Smav
548261055Smav	*ack = atomic_load_acq_32(&xprt->xp_snt_cnt);
549261055Smav	*ack -= xprt->xp_socket->so_snd.sb_cc;
550261055Smav	return (TRUE);
551261055Smav}
552261055Smav
553244008Srmacklemstatic enum xprt_stat
554244008Srmacklemsvc_vc_backchannel_stat(SVCXPRT *xprt)
555244008Srmacklem{
556244008Srmacklem	struct cf_conn *cd;
557244008Srmacklem
558244008Srmacklem	cd = (struct cf_conn *)(xprt->xp_p1);
559244008Srmacklem
560244008Srmacklem	if (cd->mreq != NULL)
561244008Srmacklem		return (XPRT_MOREREQS);
562244008Srmacklem
563244008Srmacklem	return (XPRT_IDLE);
564244008Srmacklem}
565244008Srmacklem
566261047Smav/*
567261047Smav * If we have an mbuf chain in cd->mpending, try to parse a record from it,
568261047Smav * leaving the result in cd->mreq. If we don't have a complete record, leave
569261047Smav * the partial result in cd->mreq and try to read more from the socket.
570261047Smav */
571261050Smavstatic int
572261047Smavsvc_vc_process_pending(SVCXPRT *xprt)
573261047Smav{
574261047Smav	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
575261047Smav	struct socket *so = xprt->xp_socket;
576261047Smav	struct mbuf *m;
577261047Smav
578261047Smav	/*
579261047Smav	 * If cd->resid is non-zero, we have part of the
580261047Smav	 * record already, otherwise we are expecting a record
581261047Smav	 * marker.
582261047Smav	 */
583261047Smav	if (!cd->resid && cd->mpending) {
584261047Smav		/*
585261047Smav		 * See if there is enough data buffered to
586261047Smav		 * make up a record marker. Make sure we can
587261047Smav		 * handle the case where the record marker is
588261047Smav		 * split across more than one mbuf.
589261047Smav		 */
590261047Smav		size_t n = 0;
591261047Smav		uint32_t header;
592261047Smav
593261047Smav		m = cd->mpending;
594261047Smav		while (n < sizeof(uint32_t) && m) {
595261047Smav			n += m->m_len;
596261047Smav			m = m->m_next;
597261047Smav		}
598261047Smav		if (n < sizeof(uint32_t)) {
599261047Smav			so->so_rcv.sb_lowat = sizeof(uint32_t) - n;
600261050Smav			return (FALSE);
601261047Smav		}
602261047Smav		m_copydata(cd->mpending, 0, sizeof(header),
603261047Smav		    (char *)&header);
604261047Smav		header = ntohl(header);
605261047Smav		cd->eor = (header & 0x80000000) != 0;
606261047Smav		cd->resid = header & 0x7fffffff;
607261047Smav		m_adj(cd->mpending, sizeof(uint32_t));
608261047Smav	}
609261047Smav
610261047Smav	/*
611261047Smav	 * Start pulling off mbufs from cd->mpending
612261047Smav	 * until we either have a complete record or
613261047Smav	 * we run out of data. We use m_split to pull
614261047Smav	 * data - it will pull as much as possible and
615261047Smav	 * split the last mbuf if necessary.
616261047Smav	 */
617261047Smav	while (cd->mpending && cd->resid) {
618261047Smav		m = cd->mpending;
619261047Smav		if (cd->mpending->m_next
620261047Smav		    || cd->mpending->m_len > cd->resid)
621261047Smav			cd->mpending = m_split(cd->mpending,
622261047Smav			    cd->resid, M_WAITOK);
623261047Smav		else
624261047Smav			cd->mpending = NULL;
625261047Smav		if (cd->mreq)
626261047Smav			m_last(cd->mreq)->m_next = m;
627261047Smav		else
628261047Smav			cd->mreq = m;
629261047Smav		while (m) {
630261047Smav			cd->resid -= m->m_len;
631261047Smav			m = m->m_next;
632261047Smav		}
633261047Smav	}
634261047Smav
635261052Smav	/*
636261052Smav	 * Block receive upcalls if we have more data pending,
637261052Smav	 * otherwise report our need.
638261052Smav	 */
639261052Smav	if (cd->mpending)
640261052Smav		so->so_rcv.sb_lowat = INT_MAX;
641261052Smav	else
642261052Smav		so->so_rcv.sb_lowat =
643261052Smav		    imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2));
644261050Smav	return (TRUE);
645261047Smav}
646261047Smav
647177633Sdfrstatic bool_t
648184588Sdfrsvc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
649184588Sdfr    struct sockaddr **addrp, struct mbuf **mp)
650177633Sdfr{
651177633Sdfr	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
652177633Sdfr	struct uio uio;
653177633Sdfr	struct mbuf *m;
654261047Smav	struct socket* so = xprt->xp_socket;
655184588Sdfr	XDR xdrs;
656177633Sdfr	int error, rcvflag;
657269398Srmacklem	uint32_t xid_plus_direction[2];
658177633Sdfr
659184588Sdfr	/*
660184588Sdfr	 * Serialise access to the socket and our own record parsing
661184588Sdfr	 * state.
662184588Sdfr	 */
663184588Sdfr	sx_xlock(&xprt->xp_lock);
664184588Sdfr
665177633Sdfr	for (;;) {
666261047Smav		/* If we have no request ready, check pending queue. */
667261047Smav		while (cd->mpending &&
668261050Smav		    (cd->mreq == NULL || cd->resid != 0 || !cd->eor)) {
669261050Smav			if (!svc_vc_process_pending(xprt))
670261050Smav				break;
671261050Smav		}
672177633Sdfr
673261047Smav		/* Process and return complete request in cd->mreq. */
674261047Smav		if (cd->mreq != NULL && cd->resid == 0 && cd->eor) {
675177633Sdfr
676269398Srmacklem			/*
677269398Srmacklem			 * Now, check for a backchannel reply.
678269398Srmacklem			 * The XID is in the first uint32_t of the reply
679269398Srmacklem			 * and the message direction is the second one.
680269398Srmacklem			 */
681269398Srmacklem			if ((cd->mreq->m_len >= sizeof(xid_plus_direction) ||
682269398Srmacklem			    m_length(cd->mreq, NULL) >=
683269398Srmacklem			    sizeof(xid_plus_direction)) &&
684269398Srmacklem			    xprt->xp_p2 != NULL) {
685269398Srmacklem				m_copydata(cd->mreq, 0,
686269398Srmacklem				    sizeof(xid_plus_direction),
687269398Srmacklem				    (char *)xid_plus_direction);
688269398Srmacklem				xid_plus_direction[0] =
689269398Srmacklem				    ntohl(xid_plus_direction[0]);
690269398Srmacklem				xid_plus_direction[1] =
691269398Srmacklem				    ntohl(xid_plus_direction[1]);
692269398Srmacklem				/* Check message direction. */
693269398Srmacklem				if (xid_plus_direction[1] == REPLY) {
694269398Srmacklem					clnt_bck_svccall(xprt->xp_p2,
695269398Srmacklem					    cd->mreq,
696269398Srmacklem					    xid_plus_direction[0]);
697269398Srmacklem					cd->mreq = NULL;
698269398Srmacklem					continue;
699269398Srmacklem				}
700269398Srmacklem			}
701269398Srmacklem
702261047Smav			xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
703261047Smav			cd->mreq = NULL;
704261047Smav
705261047Smav			/* Check for next request in a pending queue. */
706261047Smav			svc_vc_process_pending(xprt);
707261047Smav			if (cd->mreq == NULL || cd->resid != 0) {
708261047Smav				SOCKBUF_LOCK(&so->so_rcv);
709261047Smav				if (!soreadable(so))
710261053Smav					xprt_inactive_self(xprt);
711261047Smav				SOCKBUF_UNLOCK(&so->so_rcv);
712177633Sdfr			}
713177633Sdfr
714261047Smav			sx_xunlock(&xprt->xp_lock);
715177633Sdfr
716261047Smav			if (! xdr_callmsg(&xdrs, msg)) {
717261047Smav				XDR_DESTROY(&xdrs);
718261047Smav				return (FALSE);
719261047Smav			}
720184588Sdfr
721261047Smav			*addrp = NULL;
722261047Smav			*mp = xdrmbuf_getall(&xdrs);
723261047Smav			XDR_DESTROY(&xdrs);
724177633Sdfr
725261047Smav			return (TRUE);
726177633Sdfr		}
727177633Sdfr
728177633Sdfr		/*
729177633Sdfr		 * The socket upcall calls xprt_active() which will eventually
730177633Sdfr		 * cause the server to call us here. We attempt to
731177633Sdfr		 * read as much as possible from the socket and put
732177633Sdfr		 * the result in cd->mpending. If the read fails,
733177633Sdfr		 * we have drained both cd->mpending and the socket so
734177633Sdfr		 * we can call xprt_inactive().
735177633Sdfr		 */
736177633Sdfr		uio.uio_resid = 1000000000;
737177633Sdfr		uio.uio_td = curthread;
738177633Sdfr		m = NULL;
739177633Sdfr		rcvflag = MSG_DONTWAIT;
740261047Smav		error = soreceive(so, NULL, &uio, &m, NULL, &rcvflag);
741177633Sdfr
742177633Sdfr		if (error == EWOULDBLOCK) {
743184588Sdfr			/*
744184588Sdfr			 * We must re-test for readability after
745184588Sdfr			 * taking the lock to protect us in the case
746184588Sdfr			 * where a new packet arrives on the socket
747184588Sdfr			 * after our call to soreceive fails with
748261047Smav			 * EWOULDBLOCK.
749184588Sdfr			 */
750261047Smav			SOCKBUF_LOCK(&so->so_rcv);
751261047Smav			if (!soreadable(so))
752261053Smav				xprt_inactive_self(xprt);
753261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
754184588Sdfr			sx_xunlock(&xprt->xp_lock);
755177633Sdfr			return (FALSE);
756177633Sdfr		}
757177633Sdfr
758177633Sdfr		if (error) {
759261047Smav			SOCKBUF_LOCK(&so->so_rcv);
760193436Srmacklem			if (xprt->xp_upcallset) {
761193436Srmacklem				xprt->xp_upcallset = 0;
762261047Smav				soupcall_clear(so, SO_RCV);
763193436Srmacklem			}
764261047Smav			SOCKBUF_UNLOCK(&so->so_rcv);
765261053Smav			xprt_inactive_self(xprt);
766177633Sdfr			cd->strm_stat = XPRT_DIED;
767184588Sdfr			sx_xunlock(&xprt->xp_lock);
768177633Sdfr			return (FALSE);
769177633Sdfr		}
770177633Sdfr
771177633Sdfr		if (!m) {
772177633Sdfr			/*
773177633Sdfr			 * EOF - the other end has closed the socket.
774177633Sdfr			 */
775261053Smav			xprt_inactive_self(xprt);
776177633Sdfr			cd->strm_stat = XPRT_DIED;
777184588Sdfr			sx_xunlock(&xprt->xp_lock);
778177633Sdfr			return (FALSE);
779177633Sdfr		}
780177633Sdfr
781177633Sdfr		if (cd->mpending)
782177633Sdfr			m_last(cd->mpending)->m_next = m;
783177633Sdfr		else
784177633Sdfr			cd->mpending = m;
785177633Sdfr	}
786177633Sdfr}
787177633Sdfr
788177633Sdfrstatic bool_t
789244008Srmacklemsvc_vc_backchannel_recv(SVCXPRT *xprt, struct rpc_msg *msg,
790244008Srmacklem    struct sockaddr **addrp, struct mbuf **mp)
791244008Srmacklem{
792244008Srmacklem	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
793244008Srmacklem	struct ct_data *ct;
794244008Srmacklem	struct mbuf *m;
795244008Srmacklem	XDR xdrs;
796244008Srmacklem
797244008Srmacklem	sx_xlock(&xprt->xp_lock);
798244008Srmacklem	ct = (struct ct_data *)xprt->xp_p2;
799244008Srmacklem	if (ct == NULL) {
800244008Srmacklem		sx_xunlock(&xprt->xp_lock);
801244008Srmacklem		return (FALSE);
802244008Srmacklem	}
803244008Srmacklem	mtx_lock(&ct->ct_lock);
804244008Srmacklem	m = cd->mreq;
805244008Srmacklem	if (m == NULL) {
806261053Smav		xprt_inactive_self(xprt);
807244008Srmacklem		mtx_unlock(&ct->ct_lock);
808244008Srmacklem		sx_xunlock(&xprt->xp_lock);
809244008Srmacklem		return (FALSE);
810244008Srmacklem	}
811244008Srmacklem	cd->mreq = m->m_nextpkt;
812244008Srmacklem	mtx_unlock(&ct->ct_lock);
813244008Srmacklem	sx_xunlock(&xprt->xp_lock);
814244008Srmacklem
815244008Srmacklem	xdrmbuf_create(&xdrs, m, XDR_DECODE);
816244008Srmacklem	if (! xdr_callmsg(&xdrs, msg)) {
817244008Srmacklem		XDR_DESTROY(&xdrs);
818244008Srmacklem		return (FALSE);
819244008Srmacklem	}
820244008Srmacklem	*addrp = NULL;
821244008Srmacklem	*mp = xdrmbuf_getall(&xdrs);
822244008Srmacklem	XDR_DESTROY(&xdrs);
823244008Srmacklem	return (TRUE);
824244008Srmacklem}
825244008Srmacklem
826244008Srmacklemstatic bool_t
827184588Sdfrsvc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
828261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
829177633Sdfr{
830177633Sdfr	XDR xdrs;
831177633Sdfr	struct mbuf *mrep;
832184588Sdfr	bool_t stat = TRUE;
833261055Smav	int error, len;
834177633Sdfr
835177633Sdfr	/*
836177633Sdfr	 * Leave space for record mark.
837177633Sdfr	 */
838248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
839177633Sdfr	mrep->m_data += sizeof(uint32_t);
840177633Sdfr
841184588Sdfr	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
842184588Sdfr
843184588Sdfr	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
844184588Sdfr	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
845184588Sdfr		if (!xdr_replymsg(&xdrs, msg))
846184588Sdfr			stat = FALSE;
847184588Sdfr		else
848184588Sdfr			xdrmbuf_append(&xdrs, m);
849184588Sdfr	} else {
850184588Sdfr		stat = xdr_replymsg(&xdrs, msg);
851184588Sdfr	}
852184588Sdfr
853184588Sdfr	if (stat) {
854177633Sdfr		m_fixhdr(mrep);
855177633Sdfr
856177633Sdfr		/*
857177633Sdfr		 * Prepend a record marker containing the reply length.
858177633Sdfr		 */
859243882Sglebius		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
860261055Smav		len = mrep->m_pkthdr.len;
861177633Sdfr		*mtod(mrep, uint32_t *) =
862261055Smav			htonl(0x80000000 | (len - sizeof(uint32_t)));
863261055Smav		atomic_add_acq_32(&xprt->xp_snd_cnt, len);
864177633Sdfr		error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL,
865177633Sdfr		    0, curthread);
866177633Sdfr		if (!error) {
867261055Smav			atomic_add_rel_32(&xprt->xp_snt_cnt, len);
868261055Smav			if (seq)
869261055Smav				*seq = xprt->xp_snd_cnt;
870177633Sdfr			stat = TRUE;
871261055Smav		} else
872261055Smav			atomic_subtract_32(&xprt->xp_snd_cnt, len);
873177633Sdfr	} else {
874177633Sdfr		m_freem(mrep);
875177633Sdfr	}
876177633Sdfr
877184588Sdfr	XDR_DESTROY(&xdrs);
878177633Sdfr
879177633Sdfr	return (stat);
880177633Sdfr}
881177633Sdfr
882177633Sdfrstatic bool_t
883244008Srmacklemsvc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg,
884261055Smav    struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
885244008Srmacklem{
886244008Srmacklem	struct ct_data *ct;
887244008Srmacklem	XDR xdrs;
888244008Srmacklem	struct mbuf *mrep;
889244008Srmacklem	bool_t stat = TRUE;
890244008Srmacklem	int error;
891244008Srmacklem
892244008Srmacklem	/*
893244008Srmacklem	 * Leave space for record mark.
894244008Srmacklem	 */
895248195Sglebius	mrep = m_gethdr(M_WAITOK, MT_DATA);
896244008Srmacklem	mrep->m_data += sizeof(uint32_t);
897244008Srmacklem
898244008Srmacklem	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
899244008Srmacklem
900244008Srmacklem	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
901244008Srmacklem	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
902244008Srmacklem		if (!xdr_replymsg(&xdrs, msg))
903244008Srmacklem			stat = FALSE;
904244008Srmacklem		else
905244008Srmacklem			xdrmbuf_append(&xdrs, m);
906244008Srmacklem	} else {
907244008Srmacklem		stat = xdr_replymsg(&xdrs, msg);
908244008Srmacklem	}
909244008Srmacklem
910244008Srmacklem	if (stat) {
911244008Srmacklem		m_fixhdr(mrep);
912244008Srmacklem
913244008Srmacklem		/*
914244008Srmacklem		 * Prepend a record marker containing the reply length.
915244008Srmacklem		 */
916244008Srmacklem		M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK);
917244008Srmacklem		*mtod(mrep, uint32_t *) =
918244008Srmacklem			htonl(0x80000000 | (mrep->m_pkthdr.len
919244008Srmacklem				- sizeof(uint32_t)));
920244008Srmacklem		sx_xlock(&xprt->xp_lock);
921244008Srmacklem		ct = (struct ct_data *)xprt->xp_p2;
922244008Srmacklem		if (ct != NULL)
923244008Srmacklem			error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL,
924244008Srmacklem			    0, curthread);
925244008Srmacklem		else
926244008Srmacklem			error = EPIPE;
927244008Srmacklem		sx_xunlock(&xprt->xp_lock);
928244008Srmacklem		if (!error) {
929244008Srmacklem			stat = TRUE;
930244008Srmacklem		}
931244008Srmacklem	} else {
932244008Srmacklem		m_freem(mrep);
933244008Srmacklem	}
934244008Srmacklem
935244008Srmacklem	XDR_DESTROY(&xdrs);
936244008Srmacklem
937244008Srmacklem	return (stat);
938244008Srmacklem}
939244008Srmacklem
940244008Srmacklemstatic bool_t
941177633Sdfrsvc_vc_null()
942177633Sdfr{
943177633Sdfr
944177633Sdfr	return (FALSE);
945177633Sdfr}
946177633Sdfr
947193272Sjhbstatic int
948177633Sdfrsvc_vc_soupcall(struct socket *so, void *arg, int waitflag)
949177633Sdfr{
950177633Sdfr	SVCXPRT *xprt = (SVCXPRT *) arg;
951177633Sdfr
952261047Smav	if (soreadable(xprt->xp_socket))
953261047Smav		xprt_active(xprt);
954193272Sjhb	return (SU_OK);
955177633Sdfr}
956177633Sdfr
957177633Sdfr#if 0
958177633Sdfr/*
959177633Sdfr * Get the effective UID of the sending process. Used by rpcbind, keyserv
960177633Sdfr * and rpc.yppasswdd on AF_LOCAL.
961177633Sdfr */
962177633Sdfrint
963177633Sdfr__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
964177633Sdfr	int sock, ret;
965177633Sdfr	gid_t egid;
966177633Sdfr	uid_t euid;
967177633Sdfr	struct sockaddr *sa;
968177633Sdfr
969177633Sdfr	sock = transp->xp_fd;
970184588Sdfr	sa = (struct sockaddr *)transp->xp_rtaddr;
971177633Sdfr	if (sa->sa_family == AF_LOCAL) {
972177633Sdfr		ret = getpeereid(sock, &euid, &egid);
973177633Sdfr		if (ret == 0)
974177633Sdfr			*uid = euid;
975177633Sdfr		return (ret);
976177633Sdfr	} else
977177633Sdfr		return (-1);
978177633Sdfr}
979177633Sdfr#endif
980