svc_dg.c revision 196503
118334Speter/*	$NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $	*/
2132718Skan
3169689Skan/*
4169689Skan * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
518334Speter * unrestricted use provided that this legend is included on all tape
690075Sobrien * media and as a part of the software program in whole or part.  Users
718334Speter * may copy or modify Sun RPC without charge, but are not authorized
890075Sobrien * to license or distribute it to anyone else except as part of a product or
990075Sobrien * program developed by the user.
1090075Sobrien *
1190075Sobrien * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1218334Speter * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1390075Sobrien * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1490075Sobrien *
1590075Sobrien * Sun RPC is provided with no support and without any obligation on the
1690075Sobrien * part of Sun Microsystems, Inc. to assist in its use, correction,
1718334Speter * modification or enhancement.
1818334Speter *
1990075Sobrien * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20169689Skan * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21169689Skan * OR ANY PART THEREOF.
2218334Speter *
2318334Speter * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2418334Speter * or profits or other special, indirect and consequential damages, even if
2518334Speter * Sun has been advised of the possibility of such damages.
2618334Speter *
2718334Speter * Sun Microsystems, Inc.
2818334Speter * 2550 Garcia Avenue
2918334Speter * Mountain View, California  94043
3018334Speter */
3150397Sobrien
3250397Sobrien/*
3318334Speter * Copyright (c) 1986-1991 by Sun Microsystems Inc.
3418334Speter */
3518334Speter
3618334Speter#if defined(LIBC_SCCS) && !defined(lint)
3718334Speter#ident	"@(#)svc_dg.c	1.17	94/04/24 SMI"
3818334Speter#endif
3918334Speter#include <sys/cdefs.h>
4018334Speter__FBSDID("$FreeBSD: head/sys/rpc/svc_dg.c 196503 2009-08-24 10:09:30Z zec $");
4150397Sobrien
4250397Sobrien/*
43169689Skan * svc_dg.c, Server side for connectionless RPC.
44169689Skan */
45169689Skan
4650397Sobrien#include <sys/param.h>
4750397Sobrien#include <sys/lock.h>
4850397Sobrien#include <sys/kernel.h>
49132718Skan#include <sys/malloc.h>
50132718Skan#include <sys/mbuf.h>
5118334Speter#include <sys/mutex.h>
5218334Speter#include <sys/protosw.h>
53117395Skan#include <sys/queue.h>
5452284Sobrien#include <sys/socket.h>
5590075Sobrien#include <sys/socketvar.h>
5690075Sobrien#include <sys/sx.h>
5750397Sobrien#include <sys/systm.h>
58169689Skan#include <sys/uio.h>
5990075Sobrien
6090075Sobrien#include <net/vnet.h>
61117395Skan
62132718Skan#include <rpc/rpc.h>
6318334Speter
64169689Skan#include <rpc/rpc_com.h>
65169689Skan
66169689Skanstatic enum xprt_stat svc_dg_stat(SVCXPRT *);
67169689Skanstatic bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *,
68169689Skan    struct sockaddr **, struct mbuf **);
69169689Skanstatic bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *,
70169689Skan    struct sockaddr *, struct mbuf *);
71169689Skanstatic void svc_dg_destroy(SVCXPRT *);
72169689Skanstatic bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
73169689Skanstatic int svc_dg_soupcall(struct socket *so, void *arg, int waitflag);
74169689Skan
75169689Skanstatic struct xp_ops svc_dg_ops = {
76169689Skan	.xp_recv =	svc_dg_recv,
77169689Skan	.xp_stat =	svc_dg_stat,
78169689Skan	.xp_reply =	svc_dg_reply,
79169689Skan	.xp_destroy =	svc_dg_destroy,
80169689Skan	.xp_control =	svc_dg_control,
81169689Skan};
82169689Skan
83169689Skan/*
84169689Skan * Usage:
85169689Skan *	xprt = svc_dg_create(sock, sendsize, recvsize);
86169689Skan * Does other connectionless specific initializations.
87169689Skan * Once *xprt is initialized, it is registered.
88169689Skan * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
89169689Skan * system defaults are chosen.
90132718Skan * The routines returns NULL if a problem occurred.
91132718Skan */
92132718Skanstatic const char svc_dg_str[] = "svc_dg_create: %s";
93132718Skanstatic const char svc_dg_err1[] = "could not get transport information";
94132718Skanstatic const char svc_dg_err2[] = "transport does not support data transfer";
95132718Skanstatic const char __no_mem_str[] = "out of memory";
96132718Skan
97132718SkanSVCXPRT *
98169689Skansvc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
99169689Skan    size_t recvsize)
100169689Skan{
101169689Skan	SVCXPRT *xprt;
102132718Skan	struct __rpc_sockinfo si;
103132718Skan	struct sockaddr* sa;
104132718Skan	int error;
105132718Skan
106132718Skan	CURVNET_SET(so->so_vnet);
107132718Skan	if (!__rpc_socket2sockinfo(so, &si)) {
108132718Skan		printf(svc_dg_str, svc_dg_err1);
109132718Skan		CURVNET_RESTORE();
110132718Skan		return (NULL);
111132718Skan	}
112132718Skan	/*
113132718Skan	 * Find the receive and the send size
114132718Skan	 */
115132718Skan	sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
116132718Skan	recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
117169689Skan	if ((sendsize == 0) || (recvsize == 0)) {
118169689Skan		printf(svc_dg_str, svc_dg_err2);
119169689Skan		CURVNET_RESTORE();
120132718Skan		return (NULL);
121132718Skan	}
122132718Skan
123169689Skan	xprt = svc_xprt_alloc();
124169689Skan	sx_init(&xprt->xp_lock, "xprt->xp_lock");
125132718Skan	xprt->xp_pool = pool;
126132718Skan	xprt->xp_socket = so;
127169689Skan	xprt->xp_p1 = NULL;
128169689Skan	xprt->xp_p2 = NULL;
129169689Skan	xprt->xp_ops = &svc_dg_ops;
130132718Skan
131169689Skan	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
132169689Skan	CURVNET_RESTORE();
133169689Skan	if (error)
134132718Skan		goto freedata;
135132718Skan
136132718Skan	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
137132718Skan	free(sa, M_SONAME);
138169689Skan
139132718Skan	xprt_register(xprt);
140169689Skan
141169689Skan	SOCKBUF_LOCK(&so->so_rcv);
142169689Skan	soupcall_set(so, SO_RCV, svc_dg_soupcall, xprt);
143169689Skan	SOCKBUF_UNLOCK(&so->so_rcv);
144169689Skan
14590075Sobrien	return (xprt);
146117395Skanfreedata:
14790075Sobrien	(void) printf(svc_dg_str, __no_mem_str);
14890075Sobrien	if (xprt) {
14990075Sobrien		svc_xprt_free(xprt);
15090075Sobrien	}
15190075Sobrien	return (NULL);
15290075Sobrien}
15390075Sobrien
15490075Sobrien/*ARGSUSED*/
15590075Sobrienstatic enum xprt_stat
15618334Spetersvc_dg_stat(SVCXPRT *xprt)
15718334Speter{
15818334Speter
15990075Sobrien	if (soreadable(xprt->xp_socket))
16090075Sobrien		return (XPRT_MOREREQS);
16118334Speter
16218334Speter	return (XPRT_IDLE);
16390075Sobrien}
16418334Speter
16590075Sobrienstatic bool_t
16690075Sobriensvc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg,
16718334Speter    struct sockaddr **addrp, struct mbuf **mp)
16818334Speter{
16918334Speter	struct uio uio;
17018334Speter	struct sockaddr *raddr;
17118334Speter	struct mbuf *mreq;
17218334Speter	XDR xdrs;
173132718Skan	int error, rcvflag;
17418334Speter
17518334Speter	/*
17618334Speter	 * Serialise access to the socket.
17718334Speter	 */
17818334Speter	sx_xlock(&xprt->xp_lock);
17918334Speter
18018334Speter	/*
18118334Speter	 * The socket upcall calls xprt_active() which will eventually
18218334Speter	 * cause the server to call us here. We attempt to read a
18318334Speter	 * packet from the socket and process it. If the read fails,
18418334Speter	 * we have drained all pending requests so we call
18518334Speter	 * xprt_inactive().
186132718Skan	 */
187132718Skan	uio.uio_resid = 1000000000;
18818334Speter	uio.uio_td = curthread;
18990075Sobrien	mreq = NULL;
19090075Sobrien	rcvflag = MSG_DONTWAIT;
19118334Speter	error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag);
19218334Speter
193169689Skan	if (error == EWOULDBLOCK) {
194169689Skan		/*
195169689Skan		 * We must re-test for readability after taking the
196169689Skan		 * lock to protect us in the case where a new packet
197169689Skan		 * arrives on the socket after our call to soreceive
198169689Skan		 * fails with EWOULDBLOCK. The pool lock protects us
199169689Skan		 * from racing the upcall after our soreadable() call
200169689Skan		 * returns false.
201169689Skan		 */
202169689Skan		mtx_lock(&xprt->xp_pool->sp_lock);
203169689Skan		if (!soreadable(xprt->xp_socket))
204169689Skan			xprt_inactive_locked(xprt);
205169689Skan		mtx_unlock(&xprt->xp_pool->sp_lock);
206169689Skan		sx_xunlock(&xprt->xp_lock);
20718334Speter		return (FALSE);
208169689Skan	}
209169689Skan
210169689Skan	if (error) {
21118334Speter		SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
21290075Sobrien		soupcall_clear(xprt->xp_socket, SO_RCV);
21390075Sobrien		SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
21490075Sobrien		xprt_inactive(xprt);
215169689Skan		sx_xunlock(&xprt->xp_lock);
21618334Speter		return (FALSE);
217169689Skan	}
21818334Speter
21918334Speter	sx_xunlock(&xprt->xp_lock);
22018334Speter
22118334Speter	xdrmbuf_create(&xdrs, mreq, XDR_DECODE);
222132718Skan	if (! xdr_callmsg(&xdrs, msg)) {
223132718Skan		XDR_DESTROY(&xdrs);
22418334Speter		return (FALSE);
22518334Speter	}
22618334Speter
227169689Skan	*addrp = raddr;
228169689Skan	*mp = xdrmbuf_getall(&xdrs);
229169689Skan	XDR_DESTROY(&xdrs);
230169689Skan
23118334Speter	return (TRUE);
23218334Speter}
23318334Speter
234169689Skanstatic bool_t
23518334Spetersvc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg,
23618334Speter    struct sockaddr *addr, struct mbuf *m)
237169689Skan{
23818334Speter	XDR xdrs;
23918334Speter	struct mbuf *mrep;
240169689Skan	bool_t stat = TRUE;
24118334Speter	int error;
242169689Skan
24318334Speter	MGETHDR(mrep, M_WAIT, MT_DATA);
24418334Speter	mrep->m_len = 0;
245169689Skan
246169689Skan	xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
247169689Skan
248169689Skan	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
249169689Skan	    msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
250169689Skan		if (!xdr_replymsg(&xdrs, msg))
251169689Skan			stat = FALSE;
252169689Skan		else
253169689Skan			xdrmbuf_append(&xdrs, m);
254169689Skan	} else {
255169689Skan		stat = xdr_replymsg(&xdrs, msg);
256169689Skan	}
257169689Skan
258169689Skan	if (stat) {
259169689Skan		m_fixhdr(mrep);
260169689Skan		error = sosend(xprt->xp_socket, addr, NULL, mrep, NULL,
261169689Skan		    0, curthread);
262169689Skan		if (!error) {
263169689Skan			stat = TRUE;
264169689Skan		}
265169689Skan	} else {
266169689Skan		m_freem(mrep);
267169689Skan	}
268169689Skan
269169689Skan	XDR_DESTROY(&xdrs);
27018334Speter	xprt->xp_p2 = NULL;
271169689Skan
272169689Skan	return (stat);
273169689Skan}
27418334Speter
275169689Skanstatic void
276169689Skansvc_dg_destroy(SVCXPRT *xprt)
277169689Skan{
278169689Skan
279169689Skan	SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
28018334Speter	soupcall_clear(xprt->xp_socket, SO_RCV);
281169689Skan	SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
282169689Skan
283169689Skan	sx_destroy(&xprt->xp_lock);
28418334Speter	if (xprt->xp_socket)
285169689Skan		(void)soclose(xprt->xp_socket);
286169689Skan
287169689Skan	if (xprt->xp_netid)
288169689Skan		(void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
289169689Skan	svc_xprt_free(xprt);
29018334Speter}
29118334Speter
292169689Skanstatic bool_t
29318334Speter/*ARGSUSED*/
29418334Spetersvc_dg_control(xprt, rq, in)
29518334Speter	SVCXPRT *xprt;
296169689Skan	const u_int	rq;
29718334Speter	void		*in;
29818334Speter{
29918334Speter
30018334Speter	return (FALSE);
30118334Speter}
302169689Skan
303169689Skanstatic int
304169689Skansvc_dg_soupcall(struct socket *so, void *arg, int waitflag)
305169689Skan{
30618334Speter	SVCXPRT *xprt = (SVCXPRT *) arg;
30790075Sobrien
30890075Sobrien	xprt_active(xprt);
30918334Speter	return (SU_OK);
31018334Speter}
31190075Sobrien