svc_dg.c revision 177685
1177633Sdfr/* $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ */ 2177633Sdfr 3177633Sdfr/* 4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5177633Sdfr * unrestricted use provided that this legend is included on all tape 6177633Sdfr * media and as a part of the software program in whole or part. Users 7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized 8177633Sdfr * to license or distribute it to anyone else except as part of a product or 9177633Sdfr * program developed by the user. 10177633Sdfr * 11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14177633Sdfr * 15177633Sdfr * Sun RPC is provided with no support and without any obligation on the 16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction, 17177633Sdfr * modification or enhancement. 18177633Sdfr * 19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21177633Sdfr * OR ANY PART THEREOF. 22177633Sdfr * 23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24177633Sdfr * or profits or other special, indirect and consequential damages, even if 25177633Sdfr * Sun has been advised of the possibility of such damages. 26177633Sdfr * 27177633Sdfr * Sun Microsystems, Inc. 28177633Sdfr * 2550 Garcia Avenue 29177633Sdfr * Mountain View, California 94043 30177633Sdfr */ 31177633Sdfr 32177633Sdfr/* 33177633Sdfr * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34177633Sdfr */ 35177633Sdfr 36177633Sdfr#if defined(LIBC_SCCS) && !defined(lint) 37177633Sdfr#ident "@(#)svc_dg.c 1.17 94/04/24 SMI" 38177633Sdfr#endif 39177633Sdfr#include <sys/cdefs.h> 40177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/svc_dg.c 177685 2008-03-28 09:50:32Z dfr $"); 41177633Sdfr 42177633Sdfr/* 43177633Sdfr * svc_dg.c, Server side for connectionless RPC. 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> 52177633Sdfr#include <sys/protosw.h> 53177633Sdfr#include <sys/queue.h> 54177633Sdfr#include <sys/socket.h> 55177633Sdfr#include <sys/socketvar.h> 56177633Sdfr#include <sys/systm.h> 57177633Sdfr#include <sys/uio.h> 58177633Sdfr 59177633Sdfr#include <rpc/rpc.h> 60177633Sdfr 61177685Sdfr#include <rpc/rpc_com.h> 62177633Sdfr 63177633Sdfrstatic enum xprt_stat svc_dg_stat(SVCXPRT *); 64177633Sdfrstatic bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *); 65177633Sdfrstatic bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *); 66177633Sdfrstatic bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *); 67177633Sdfrstatic bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *); 68177633Sdfrstatic void svc_dg_destroy(SVCXPRT *); 69177633Sdfrstatic bool_t svc_dg_control(SVCXPRT *, const u_int, void *); 70177633Sdfrstatic void svc_dg_soupcall(struct socket *so, void *arg, int waitflag); 71177633Sdfr 72177633Sdfrstatic struct xp_ops svc_dg_ops = { 73177633Sdfr .xp_recv = svc_dg_recv, 74177633Sdfr .xp_stat = svc_dg_stat, 75177633Sdfr .xp_getargs = svc_dg_getargs, 76177633Sdfr .xp_reply = svc_dg_reply, 77177633Sdfr .xp_freeargs = svc_dg_freeargs, 78177633Sdfr .xp_destroy = svc_dg_destroy, 79177633Sdfr .xp_control = svc_dg_control, 80177633Sdfr}; 81177633Sdfr 82177633Sdfr/* 83177633Sdfr * Usage: 84177633Sdfr * xprt = svc_dg_create(sock, sendsize, recvsize); 85177633Sdfr * Does other connectionless specific initializations. 86177633Sdfr * Once *xprt is initialized, it is registered. 87177633Sdfr * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable 88177633Sdfr * system defaults are chosen. 89177633Sdfr * The routines returns NULL if a problem occurred. 90177633Sdfr */ 91177633Sdfrstatic const char svc_dg_str[] = "svc_dg_create: %s"; 92177633Sdfrstatic const char svc_dg_err1[] = "could not get transport information"; 93177633Sdfrstatic const char svc_dg_err2[] = "transport does not support data transfer"; 94177633Sdfrstatic const char __no_mem_str[] = "out of memory"; 95177633Sdfr 96177633SdfrSVCXPRT * 97177633Sdfrsvc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, 98177633Sdfr size_t recvsize) 99177633Sdfr{ 100177633Sdfr SVCXPRT *xprt; 101177633Sdfr struct __rpc_sockinfo si; 102177633Sdfr struct sockaddr* sa; 103177633Sdfr int error; 104177633Sdfr 105177633Sdfr if (!__rpc_socket2sockinfo(so, &si)) { 106177633Sdfr printf(svc_dg_str, svc_dg_err1); 107177633Sdfr return (NULL); 108177633Sdfr } 109177633Sdfr /* 110177633Sdfr * Find the receive and the send size 111177633Sdfr */ 112177633Sdfr sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 113177633Sdfr recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 114177633Sdfr if ((sendsize == 0) || (recvsize == 0)) { 115177633Sdfr printf(svc_dg_str, svc_dg_err2); 116177633Sdfr return (NULL); 117177633Sdfr } 118177633Sdfr 119177633Sdfr xprt = mem_alloc(sizeof (SVCXPRT)); 120177633Sdfr memset(xprt, 0, sizeof (SVCXPRT)); 121177633Sdfr mtx_init(&xprt->xp_lock, "xprt->xp_lock", NULL, MTX_DEF); 122177633Sdfr xprt->xp_pool = pool; 123177633Sdfr xprt->xp_socket = so; 124177633Sdfr xprt->xp_p1 = NULL; 125177633Sdfr xprt->xp_p2 = NULL; 126177633Sdfr xprt->xp_ops = &svc_dg_ops; 127177633Sdfr 128177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 129177633Sdfr if (error) 130177633Sdfr goto freedata; 131177633Sdfr 132177633Sdfr xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage)); 133177633Sdfr xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage); 134177633Sdfr xprt->xp_ltaddr.len = sa->sa_len; 135177633Sdfr memcpy(xprt->xp_ltaddr.buf, sa, sa->sa_len); 136177633Sdfr free(sa, M_SONAME); 137177633Sdfr 138177633Sdfr xprt->xp_rtaddr.buf = mem_alloc(sizeof (struct sockaddr_storage)); 139177633Sdfr xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 140177633Sdfr xprt->xp_rtaddr.len = 0; 141177633Sdfr 142177633Sdfr xprt_register(xprt); 143177633Sdfr 144177633Sdfr SOCKBUF_LOCK(&so->so_rcv); 145177633Sdfr so->so_upcallarg = xprt; 146177633Sdfr so->so_upcall = svc_dg_soupcall; 147177633Sdfr so->so_rcv.sb_flags |= SB_UPCALL; 148177633Sdfr SOCKBUF_UNLOCK(&so->so_rcv); 149177633Sdfr 150177633Sdfr return (xprt); 151177633Sdfrfreedata: 152177633Sdfr (void) printf(svc_dg_str, __no_mem_str); 153177633Sdfr if (xprt) { 154177633Sdfr (void) mem_free(xprt, sizeof (SVCXPRT)); 155177633Sdfr } 156177633Sdfr return (NULL); 157177633Sdfr} 158177633Sdfr 159177633Sdfr/*ARGSUSED*/ 160177633Sdfrstatic enum xprt_stat 161177633Sdfrsvc_dg_stat(SVCXPRT *xprt) 162177633Sdfr{ 163177633Sdfr 164177633Sdfr return (XPRT_IDLE); 165177633Sdfr} 166177633Sdfr 167177633Sdfrstatic bool_t 168177633Sdfrsvc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg) 169177633Sdfr{ 170177633Sdfr struct uio uio; 171177633Sdfr struct sockaddr *raddr; 172177633Sdfr struct mbuf *mreq; 173177633Sdfr int error, rcvflag; 174177633Sdfr 175177633Sdfr /* 176177633Sdfr * The socket upcall calls xprt_active() which will eventually 177177633Sdfr * cause the server to call us here. We attempt to read a 178177633Sdfr * packet from the socket and process it. If the read fails, 179177633Sdfr * we have drained all pending requests so we call 180177633Sdfr * xprt_inactive(). 181177633Sdfr * 182177633Sdfr * The lock protects us in the case where a new packet arrives 183177633Sdfr * on the socket after our call to soreceive fails with 184177633Sdfr * EWOULDBLOCK - the call to xprt_active() in the upcall will 185177633Sdfr * happen only after our call to xprt_inactive() which ensures 186177633Sdfr * that we will remain active. It might be possible to use 187177633Sdfr * SOCKBUF_LOCK for this - its not clear to me what locks are 188177633Sdfr * held during the upcall. 189177633Sdfr */ 190177633Sdfr mtx_lock(&xprt->xp_lock); 191177633Sdfr 192177633Sdfr uio.uio_resid = 1000000000; 193177633Sdfr uio.uio_td = curthread; 194177633Sdfr mreq = NULL; 195177633Sdfr rcvflag = MSG_DONTWAIT; 196177633Sdfr error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag); 197177633Sdfr 198177633Sdfr if (error == EWOULDBLOCK) { 199177633Sdfr xprt_inactive(xprt); 200177633Sdfr mtx_unlock(&xprt->xp_lock); 201177633Sdfr return (FALSE); 202177633Sdfr } 203177633Sdfr 204177633Sdfr if (error) { 205177633Sdfr SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); 206177633Sdfr xprt->xp_socket->so_upcallarg = NULL; 207177633Sdfr xprt->xp_socket->so_upcall = NULL; 208177633Sdfr xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL; 209177633Sdfr SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); 210177633Sdfr xprt_inactive(xprt); 211177633Sdfr mtx_unlock(&xprt->xp_lock); 212177633Sdfr return (FALSE); 213177633Sdfr } 214177633Sdfr 215177633Sdfr mtx_unlock(&xprt->xp_lock); 216177633Sdfr 217177633Sdfr KASSERT(raddr->sa_len < xprt->xp_rtaddr.maxlen, 218177633Sdfr ("Unexpected remote address length")); 219177633Sdfr memcpy(xprt->xp_rtaddr.buf, raddr, raddr->sa_len); 220177633Sdfr xprt->xp_rtaddr.len = raddr->sa_len; 221177633Sdfr free(raddr, M_SONAME); 222177633Sdfr 223177633Sdfr xdrmbuf_create(&xprt->xp_xdrreq, mreq, XDR_DECODE); 224177633Sdfr if (! xdr_callmsg(&xprt->xp_xdrreq, msg)) { 225177633Sdfr XDR_DESTROY(&xprt->xp_xdrreq); 226177633Sdfr return (FALSE); 227177633Sdfr } 228177633Sdfr xprt->xp_xid = msg->rm_xid; 229177633Sdfr 230177633Sdfr return (TRUE); 231177633Sdfr} 232177633Sdfr 233177633Sdfrstatic bool_t 234177633Sdfrsvc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg) 235177633Sdfr{ 236177633Sdfr struct mbuf *mrep; 237177633Sdfr bool_t stat = FALSE; 238177633Sdfr int error; 239177633Sdfr 240177633Sdfr MGETHDR(mrep, M_WAIT, MT_DATA); 241177633Sdfr MCLGET(mrep, M_WAIT); 242177633Sdfr mrep->m_len = 0; 243177633Sdfr 244177633Sdfr xdrmbuf_create(&xprt->xp_xdrrep, mrep, XDR_ENCODE); 245177633Sdfr msg->rm_xid = xprt->xp_xid; 246177633Sdfr if (xdr_replymsg(&xprt->xp_xdrrep, msg)) { 247177633Sdfr m_fixhdr(mrep); 248177633Sdfr error = sosend(xprt->xp_socket, 249177633Sdfr (struct sockaddr *) xprt->xp_rtaddr.buf, NULL, mrep, NULL, 250177633Sdfr 0, curthread); 251177633Sdfr if (!error) { 252177633Sdfr stat = TRUE; 253177633Sdfr } 254177633Sdfr } else { 255177633Sdfr m_freem(mrep); 256177633Sdfr } 257177633Sdfr 258177633Sdfr /* 259177633Sdfr * This frees the request mbuf chain as well. The reply mbuf 260177633Sdfr * chain was consumed by sosend. 261177633Sdfr */ 262177633Sdfr XDR_DESTROY(&xprt->xp_xdrreq); 263177633Sdfr XDR_DESTROY(&xprt->xp_xdrrep); 264177633Sdfr xprt->xp_p2 = NULL; 265177633Sdfr 266177633Sdfr return (stat); 267177633Sdfr} 268177633Sdfr 269177633Sdfrstatic bool_t 270177633Sdfrsvc_dg_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) 271177633Sdfr{ 272177633Sdfr 273177633Sdfr return (xdr_args(&xprt->xp_xdrreq, args_ptr)); 274177633Sdfr} 275177633Sdfr 276177633Sdfrstatic bool_t 277177633Sdfrsvc_dg_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) 278177633Sdfr{ 279177633Sdfr XDR xdrs; 280177633Sdfr 281177633Sdfr /* 282177633Sdfr * Free the request mbuf here - this allows us to handle 283177633Sdfr * protocols where not all requests have replies 284177633Sdfr * (i.e. NLM). Note that xdrmbuf_destroy handles being called 285177633Sdfr * twice correctly - the mbuf will only be freed once. 286177633Sdfr */ 287177633Sdfr XDR_DESTROY(&xprt->xp_xdrreq); 288177633Sdfr 289177633Sdfr xdrs.x_op = XDR_FREE; 290177633Sdfr return (xdr_args(&xdrs, args_ptr)); 291177633Sdfr} 292177633Sdfr 293177633Sdfrstatic void 294177633Sdfrsvc_dg_destroy(SVCXPRT *xprt) 295177633Sdfr{ 296177633Sdfr SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); 297177633Sdfr xprt->xp_socket->so_upcallarg = NULL; 298177633Sdfr xprt->xp_socket->so_upcall = NULL; 299177633Sdfr xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL; 300177633Sdfr SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); 301177633Sdfr 302177633Sdfr xprt_unregister(xprt); 303177633Sdfr 304177633Sdfr mtx_destroy(&xprt->xp_lock); 305177633Sdfr if (xprt->xp_socket) 306177633Sdfr (void)soclose(xprt->xp_socket); 307177633Sdfr 308177633Sdfr if (xprt->xp_rtaddr.buf) 309177633Sdfr (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 310177633Sdfr if (xprt->xp_ltaddr.buf) 311177633Sdfr (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 312177633Sdfr (void) mem_free(xprt, sizeof (SVCXPRT)); 313177633Sdfr} 314177633Sdfr 315177633Sdfrstatic bool_t 316177633Sdfr/*ARGSUSED*/ 317177633Sdfrsvc_dg_control(xprt, rq, in) 318177633Sdfr SVCXPRT *xprt; 319177633Sdfr const u_int rq; 320177633Sdfr void *in; 321177633Sdfr{ 322177633Sdfr 323177633Sdfr return (FALSE); 324177633Sdfr} 325177633Sdfr 326177633Sdfrstatic void 327177633Sdfrsvc_dg_soupcall(struct socket *so, void *arg, int waitflag) 328177633Sdfr{ 329177633Sdfr SVCXPRT *xprt = (SVCXPRT *) arg; 330177633Sdfr 331177633Sdfr mtx_lock(&xprt->xp_lock); 332177633Sdfr xprt_active(xprt); 333177633Sdfr mtx_unlock(&xprt->xp_lock); 334177633Sdfr} 335