svc_dg.c revision 218757
11590Srgrimes/*	$NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $	*/
21590Srgrimes
31590Srgrimes/*
41590Srgrimes * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
51590Srgrimes * unrestricted use provided that this legend is included on all tape
61590Srgrimes * media and as a part of the software program in whole or part.  Users
71590Srgrimes * may copy or modify Sun RPC without charge, but are not authorized
81590Srgrimes * to license or distribute it to anyone else except as part of a product or
91590Srgrimes * program developed by the user.
101590Srgrimes *
111590Srgrimes * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
121590Srgrimes * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
131590Srgrimes * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
141590Srgrimes *
151590Srgrimes * Sun RPC is provided with no support and without any obligation on the
161590Srgrimes * part of Sun Microsystems, Inc. to assist in its use, correction,
171590Srgrimes * modification or enhancement.
181590Srgrimes *
191590Srgrimes * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
201590Srgrimes * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
211590Srgrimes * OR ANY PART THEREOF.
221590Srgrimes *
231590Srgrimes * In no event will Sun Microsystems, Inc. be liable for any lost revenue
241590Srgrimes * or profits or other special, indirect and consequential damages, even if
251590Srgrimes * Sun has been advised of the possibility of such damages.
261590Srgrimes *
271590Srgrimes * Sun Microsystems, Inc.
281590Srgrimes * 2550 Garcia Avenue
291590Srgrimes * Mountain View, California  94043
301590Srgrimes */
311590Srgrimes
321590Srgrimes/*
331590Srgrimes * Copyright (c) 1986-1991 by Sun Microsystems Inc.
341590Srgrimes */
351590Srgrimes
361590Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
371590Srgrimes#ident	"@(#)svc_dg.c	1.17	94/04/24 SMI"
381590Srgrimes#endif
391590Srgrimes#include <sys/cdefs.h>
401590Srgrimes__FBSDID("$FreeBSD: head/sys/rpc/svc_dg.c 218757 2011-02-16 21:29:13Z bz $");
4127185Scharnier
421590Srgrimes/*
4327185Scharnier * svc_dg.c, Server side for connectionless RPC.
4427185Scharnier */
4530009Sjoerg
4627185Scharnier#include <sys/param.h>
471590Srgrimes#include <sys/lock.h>
481590Srgrimes#include <sys/kernel.h>
491590Srgrimes#include <sys/malloc.h>
5027185Scharnier#include <sys/mbuf.h>
5111765Sache#include <sys/mutex.h>
5227185Scharnier#include <sys/protosw.h>
5312317Sjoerg#include <sys/queue.h>
5427185Scharnier#include <sys/socket.h>
551590Srgrimes#include <sys/socketvar.h>
561590Srgrimes#include <sys/sx.h>
571590Srgrimes#include <sys/systm.h>
581590Srgrimes#include <sys/uio.h>
591590Srgrimes
601590Srgrimes#include <net/vnet.h>
611590Srgrimes
621590Srgrimes#include <rpc/rpc.h>
631590Srgrimes
641590Srgrimes#include <rpc/rpc_com.h>
651590Srgrimes
661590Srgrimesstatic enum xprt_stat svc_dg_stat(SVCXPRT *);
671590Srgrimesstatic bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *,
681590Srgrimes    struct sockaddr **, struct mbuf **);
691590Srgrimesstatic bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *,
701590Srgrimes    struct sockaddr *, struct mbuf *);
711590Srgrimesstatic void svc_dg_destroy(SVCXPRT *);
721590Srgrimesstatic bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
731590Srgrimesstatic int svc_dg_soupcall(struct socket *so, void *arg, int waitflag);
741590Srgrimes
751590Srgrimesstatic struct xp_ops svc_dg_ops = {
761590Srgrimes	.xp_recv =	svc_dg_recv,
771590Srgrimes	.xp_stat =	svc_dg_stat,
7818227Sphk	.xp_reply =	svc_dg_reply,
791590Srgrimes	.xp_destroy =	svc_dg_destroy,
801590Srgrimes	.xp_control =	svc_dg_control,
811590Srgrimes};
8227185Scharnier
8327185Scharnier/*
8427185Scharnier * Usage:
8527185Scharnier *	xprt = svc_dg_create(sock, sendsize, recvsize);
8627185Scharnier * Does other connectionless specific initializations.
8727185Scharnier * Once *xprt is initialized, it is registered.
8827185Scharnier * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
8927185Scharnier * system defaults are chosen.
9027185Scharnier * The routines returns NULL if a problem occurred.
9127185Scharnier */
921590Srgrimesstatic const char svc_dg_str[] = "svc_dg_create: %s";
931590Srgrimesstatic const char svc_dg_err1[] = "could not get transport information";
941590Srgrimesstatic const char svc_dg_err2[] = "transport does not support data transfer";
951590Srgrimesstatic const char __no_mem_str[] = "out of memory";
961590Srgrimes
971590SrgrimesSVCXPRT *
9827185Scharniersvc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
991590Srgrimes    size_t recvsize)
1001590Srgrimes{
1011590Srgrimes	SVCXPRT *xprt;
1021590Srgrimes	struct __rpc_sockinfo si;
1031590Srgrimes	struct sockaddr* sa;
1041590Srgrimes	int error;
1051590Srgrimes
1061590Srgrimes	if (!__rpc_socket2sockinfo(so, &si)) {
10711765Sache		printf(svc_dg_str, svc_dg_err1);
10811765Sache		return (NULL);
1091590Srgrimes	}
1101590Srgrimes	/*
1111590Srgrimes	 * Find the receive and the send size
1121590Srgrimes	 */
1131590Srgrimes	sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
1141590Srgrimes	recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
1158874Srgrimes	if ((sendsize == 0) || (recvsize == 0)) {
1161590Srgrimes		printf(svc_dg_str, svc_dg_err2);
11718227Sphk		return (NULL);
11818227Sphk	}
11918227Sphk
12018227Sphk	xprt = svc_xprt_alloc();
12118227Sphk	sx_init(&xprt->xp_lock, "xprt->xp_lock");
1221590Srgrimes	xprt->xp_pool = pool;
1231590Srgrimes	xprt->xp_socket = so;
1241590Srgrimes	xprt->xp_p1 = NULL;
1251590Srgrimes	xprt->xp_p2 = NULL;
1261590Srgrimes	xprt->xp_ops = &svc_dg_ops;
1271590Srgrimes
1281590Srgrimes	CURVNET_SET(so->so_vnet);
1291590Srgrimes	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
1301590Srgrimes	CURVNET_RESTORE();
1311590Srgrimes	if (error)
13227185Scharnier		goto freedata;
13327185Scharnier
1341590Srgrimes	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
1351590Srgrimes	free(sa, M_SONAME);
1361590Srgrimes
1371590Srgrimes	xprt_register(xprt);
1381590Srgrimes
1391590Srgrimes	SOCKBUF_LOCK(&so->so_rcv);
1401590Srgrimes	soupcall_set(so, SO_RCV, svc_dg_soupcall, xprt);
1411590Srgrimes	SOCKBUF_UNLOCK(&so->so_rcv);
1421590Srgrimes
1431590Srgrimes	return (xprt);
1441590Srgrimesfreedata:
1451590Srgrimes	(void) printf(svc_dg_str, __no_mem_str);
1461590Srgrimes	if (xprt) {
1471590Srgrimes		svc_xprt_free(xprt);
1481590Srgrimes	}
1491590Srgrimes	return (NULL);
1501590Srgrimes}
1511590Srgrimes
1521590Srgrimes/*ARGSUSED*/
1531590Srgrimesstatic enum xprt_stat
1541590Srgrimessvc_dg_stat(SVCXPRT *xprt)
1551590Srgrimes{
1561590Srgrimes
15727185Scharnier	if (soreadable(xprt->xp_socket))
1581590Srgrimes		return (XPRT_MOREREQS);
1591590Srgrimes
1601590Srgrimes	return (XPRT_IDLE);
16112317Sjoerg}
1628461Sache
1631590Srgrimesstatic bool_t
16412317Sjoergsvc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg,
16528478Sjlemon    struct sockaddr **addrp, struct mbuf **mp)
1661590Srgrimes{
16728478Sjlemon	struct uio uio;
16828478Sjlemon	struct sockaddr *raddr;
16928478Sjlemon	struct mbuf *mreq;
17028478Sjlemon	XDR xdrs;
17118227Sphk	int error, rcvflag;
17218227Sphk
17318227Sphk	/*
17418227Sphk	 * Serialise access to the socket.
17518227Sphk	 */
17618227Sphk	sx_xlock(&xprt->xp_lock);
17718227Sphk
17818227Sphk	/*
17918227Sphk	 * The socket upcall calls xprt_active() which will eventually
18018227Sphk	 * cause the server to call us here. We attempt to read a
18118227Sphk	 * packet from the socket and process it. If the read fails,
18218227Sphk	 * we have drained all pending requests so we call
18318227Sphk	 * xprt_inactive().
18418227Sphk	 */
18518227Sphk	uio.uio_resid = 1000000000;
18618227Sphk	uio.uio_td = curthread;
18718227Sphk	mreq = NULL;
18818227Sphk	rcvflag = MSG_DONTWAIT;
18918227Sphk	error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag);
19018227Sphk
19118227Sphk	if (error == EWOULDBLOCK) {
1921590Srgrimes		/*
1931590Srgrimes		 * We must re-test for readability after taking the
1941590Srgrimes		 * lock to protect us in the case where a new packet
1951590Srgrimes		 * arrives on the socket after our call to soreceive
1961590Srgrimes		 * fails with EWOULDBLOCK. The pool lock protects us
1971590Srgrimes		 * from racing the upcall after our soreadable() call
1981590Srgrimes		 * returns false.
19912317Sjoerg		 */
20012317Sjoerg		mtx_lock(&xprt->xp_pool->sp_lock);
20112317Sjoerg		if (!soreadable(xprt->xp_socket))
20212317Sjoerg			xprt_inactive_locked(xprt);
20312317Sjoerg		mtx_unlock(&xprt->xp_pool->sp_lock);
20412317Sjoerg		sx_xunlock(&xprt->xp_lock);
20512317Sjoerg		return (FALSE);
20612317Sjoerg	}
20712317Sjoerg
2081590Srgrimes	if (error) {
2091590Srgrimes		SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
2101590Srgrimes		soupcall_clear(xprt->xp_socket, SO_RCV);
2111590Srgrimes		SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
2121590Srgrimes		xprt_inactive(xprt);
2131590Srgrimes		sx_xunlock(&xprt->xp_lock);
2148461Sache		return (FALSE);
2151590Srgrimes	}
2161590Srgrimes
2171590Srgrimes	sx_xunlock(&xprt->xp_lock);
2181590Srgrimes
2191590Srgrimes	xdrmbuf_create(&xdrs, mreq, XDR_DECODE);
2201590Srgrimes	if (! xdr_callmsg(&xdrs, msg)) {
2211590Srgrimes		XDR_DESTROY(&xdrs);
2221590Srgrimes		return (FALSE);
2231590Srgrimes	}
2241590Srgrimes
2251590Srgrimes	*addrp = raddr;
2261590Srgrimes	*mp = xdrmbuf_getall(&xdrs);
2278874Srgrimes	XDR_DESTROY(&xdrs);
22815344Ssmpatel
22915344Ssmpatel	return (TRUE);
23015344Ssmpatel}
23115344Ssmpatel
23215344Ssmpatelstatic bool_t
23315344Ssmpatelsvc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg,
23415344Ssmpatel    struct sockaddr *addr, struct mbuf *m)
23515344Ssmpatel{
2361590Srgrimes	XDR xdrs;
2371590Srgrimes	struct mbuf *mrep;
2381590Srgrimes	bool_t stat = TRUE;
2391590Srgrimes	int error;
2401590Srgrimes
2411590Srgrimes	MGETHDR(mrep, M_WAIT, MT_DATA);
24227185Scharnier	mrep->m_len = 0;
2438461Sache
2441590Srgrimes	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
24512317Sjoerg
24612317Sjoerg	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
24712317Sjoerg	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
24812317Sjoerg		if (!xdr_replymsg(&xdrs, msg))
24912317Sjoerg			stat = FALSE;
25012317Sjoerg		else
25112317Sjoerg			xdrmbuf_append(&xdrs, m);
25212317Sjoerg	} else {
25312317Sjoerg		stat = xdr_replymsg(&xdrs, msg);
2541590Srgrimes	}
2551590Srgrimes
2561590Srgrimes	if (stat) {
25712317Sjoerg		m_fixhdr(mrep);
25812317Sjoerg		error = sosend(xprt->xp_socket, addr, NULL, mrep, NULL,
25912317Sjoerg		    0, curthread);
26012317Sjoerg		if (!error) {
26112317Sjoerg			stat = TRUE;
26212317Sjoerg		}
26312317Sjoerg	} else {
26412317Sjoerg		m_freem(mrep);
26512317Sjoerg	}
2661590Srgrimes
2671590Srgrimes	XDR_DESTROY(&xdrs);
2681590Srgrimes	xprt->xp_p2 = NULL;
2691590Srgrimes
2701590Srgrimes	return (stat);
2711590Srgrimes}
2721590Srgrimes
2731590Srgrimesstatic void
2741590Srgrimessvc_dg_destroy(SVCXPRT *xprt)
2751590Srgrimes{
2761590Srgrimes
2771590Srgrimes	SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
2781590Srgrimes	soupcall_clear(xprt->xp_socket, SO_RCV);
2791590Srgrimes	SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
2801590Srgrimes
2811590Srgrimes	sx_destroy(&xprt->xp_lock);
2821590Srgrimes	if (xprt->xp_socket)
2831590Srgrimes		(void)soclose(xprt->xp_socket);
2841590Srgrimes
2851590Srgrimes	if (xprt->xp_netid)
2861590Srgrimes		(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
2871590Srgrimes	svc_xprt_free(xprt);
2881590Srgrimes}
28927185Scharnier
2901590Srgrimesstatic bool_t
2911590Srgrimes/*ARGSUSED*/
2921590Srgrimessvc_dg_control(xprt, rq, in)
2931590Srgrimes	SVCXPRT *xprt;
2941590Srgrimes	const u_int	rq;
2951590Srgrimes	void		*in;
2968461Sache{
2971590Srgrimes
2981590Srgrimes	return (FALSE);
2991590Srgrimes}
3001590Srgrimes
3011590Srgrimesstatic int
3021590Srgrimessvc_dg_soupcall(struct socket *so, void *arg, int waitflag)
3031590Srgrimes{
3041590Srgrimes	SVCXPRT *xprt = (SVCXPRT *) arg;
3051590Srgrimes
3061590Srgrimes	xprt_active(xprt);
3071590Srgrimes	return (SU_OK);
3081590Srgrimes}
3091590Srgrimes