svc_dg.c revision 177633
1139790Simp/* $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ */ 2123120Simp 3123120Simp/* 4123120Simp * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5123120Simp * unrestricted use provided that this legend is included on all tape 6123120Simp * media and as a part of the software program in whole or part. Users 7155049Srik * may copy or modify Sun RPC without charge, but are not authorized 8155049Srik * to license or distribute it to anyone else except as part of a product or 9123120Simp * program developed by the user. 10155049Srik * 11155049Srik * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12155049Srik * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13123120Simp * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14123120Simp * 15123120Simp * Sun RPC is provided with no support and without any obligation on the 16123120Simp * part of Sun Microsystems, Inc. to assist in its use, correction, 17123120Simp * modification or enhancement. 18123120Simp * 19123120Simp * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20155049Srik * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21123120Simp * OR ANY PART THEREOF. 22123120Simp * 23123120Simp * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24123120Simp * or profits or other special, indirect and consequential damages, even if 25123120Simp * Sun has been advised of the possibility of such damages. 26123120Simp * 27123120Simp * Sun Microsystems, Inc. 28123120Simp * 2550 Garcia Avenue 29123120Simp * Mountain View, California 94043 30123120Simp */ 31123120Simp 32123120Simp/* 33123120Simp * Copyright (c) 1986-1991 by Sun Microsystems Inc. 34123120Simp */ 35123120Simp 36123120Simp#if defined(LIBC_SCCS) && !defined(lint) 37123120Simp#ident "@(#)svc_dg.c 1.17 94/04/24 SMI" 38123120Simp#endif 39123120Simp#include <sys/cdefs.h> 40123120Simp__FBSDID("$FreeBSD: head/sys/rpc/svc_dg.c 177633 2008-03-26 15:23:12Z dfr $"); 41123120Simp 42123120Simp/* 43123120Simp * svc_dg.c, Server side for connectionless RPC. 44123120Simp */ 45123120Simp 46123120Simp#include <sys/param.h> 47123120Simp#include <sys/lock.h> 48123120Simp#include <sys/kernel.h> 49123120Simp#include <sys/malloc.h> 50123120Simp#include <sys/mbuf.h> 51123120Simp#include <sys/mutex.h> 52123120Simp#include <sys/protosw.h> 53123120Simp#include <sys/queue.h> 54123120Simp#include <sys/socket.h> 55123120Simp#include <sys/socketvar.h> 56123120Simp#include <sys/systm.h> 57123120Simp#include <sys/uio.h> 58123120Simp 59123120Simp#include <rpc/rpc.h> 60123120Simp 61123120Simp#include "rpc_com.h" 62123120Simp 63123120Simpstatic enum xprt_stat svc_dg_stat(SVCXPRT *); 64123120Simpstatic bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *); 65123120Simpstatic bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *); 66123120Simpstatic bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *); 67123120Simpstatic bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *); 68123120Simpstatic void svc_dg_destroy(SVCXPRT *); 69123120Simpstatic bool_t svc_dg_control(SVCXPRT *, const u_int, void *); 70123120Simpstatic void svc_dg_soupcall(struct socket *so, void *arg, int waitflag); 71123120Simp 72123120Simpstatic struct xp_ops svc_dg_ops = { 73123120Simp .xp_recv = svc_dg_recv, 74123120Simp .xp_stat = svc_dg_stat, 75123120Simp .xp_getargs = svc_dg_getargs, 76123120Simp .xp_reply = svc_dg_reply, 77123120Simp .xp_freeargs = svc_dg_freeargs, 78123120Simp .xp_destroy = svc_dg_destroy, 79123120Simp .xp_control = svc_dg_control, 80123120Simp}; 81123120Simp 82123120Simp/* 83123120Simp * Usage: 84123120Simp * xprt = svc_dg_create(sock, sendsize, recvsize); 85123120Simp * Does other connectionless specific initializations. 86123120Simp * Once *xprt is initialized, it is registered. 87123120Simp * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable 88123120Simp * system defaults are chosen. 89123120Simp * The routines returns NULL if a problem occurred. 90123120Simp */ 91123120Simpstatic const char svc_dg_str[] = "svc_dg_create: %s"; 92155049Srikstatic const char svc_dg_err1[] = "could not get transport information"; 93155049Srikstatic const char svc_dg_err2[] = "transport does not support data transfer"; 94123120Simpstatic const char __no_mem_str[] = "out of memory"; 95123120Simp 96123120SimpSVCXPRT * 97123120Simpsvc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, 98123120Simp size_t recvsize) 99123120Simp{ 100155049Srik SVCXPRT *xprt; 101123120Simp struct __rpc_sockinfo si; 102123120Simp struct sockaddr* sa; 103123120Simp int error; 104123120Simp 105123120Simp if (!__rpc_socket2sockinfo(so, &si)) { 106123120Simp printf(svc_dg_str, svc_dg_err1); 107123120Simp return (NULL); 108123120Simp } 109123120Simp /* 110123120Simp * Find the receive and the send size 111123120Simp */ 112123120Simp sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 113123120Simp recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 114123120Simp if ((sendsize == 0) || (recvsize == 0)) { 115123120Simp printf(svc_dg_str, svc_dg_err2); 116123120Simp return (NULL); 117123120Simp } 118123120Simp 119123120Simp xprt = mem_alloc(sizeof (SVCXPRT)); 120123120Simp memset(xprt, 0, sizeof (SVCXPRT)); 121123120Simp mtx_init(&xprt->xp_lock, "xprt->xp_lock", NULL, MTX_DEF); 122123120Simp xprt->xp_pool = pool; 123123120Simp xprt->xp_socket = so; 124123120Simp xprt->xp_p1 = NULL; 125123120Simp xprt->xp_p2 = NULL; 126123120Simp xprt->xp_ops = &svc_dg_ops; 127123120Simp 128123120Simp error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 129123120Simp if (error) 130123120Simp goto freedata; 131123120Simp 132123120Simp xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage)); 133123120Simp xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage); 134155049Srik xprt->xp_ltaddr.len = sa->sa_len; 135123120Simp memcpy(xprt->xp_ltaddr.buf, sa, sa->sa_len); 136123120Simp free(sa, M_SONAME); 137123120Simp 138123120Simp xprt->xp_rtaddr.buf = mem_alloc(sizeof (struct sockaddr_storage)); 139123120Simp xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 140123120Simp xprt->xp_rtaddr.len = 0; 141123120Simp 142123120Simp xprt_register(xprt); 143123120Simp 144123120Simp SOCKBUF_LOCK(&so->so_rcv); 145123120Simp so->so_upcallarg = xprt; 146123120Simp so->so_upcall = svc_dg_soupcall; 147123120Simp so->so_rcv.sb_flags |= SB_UPCALL; 148123120Simp SOCKBUF_UNLOCK(&so->so_rcv); 149123120Simp 150123120Simp return (xprt); 151123120Simpfreedata: 152123120Simp (void) printf(svc_dg_str, __no_mem_str); 153123120Simp if (xprt) { 154123120Simp (void) mem_free(xprt, sizeof (SVCXPRT)); 155123120Simp } 156123120Simp return (NULL); 157123120Simp} 158123120Simp 159123120Simp/*ARGSUSED*/ 160123120Simpstatic enum xprt_stat 161123120Simpsvc_dg_stat(SVCXPRT *xprt) 162123120Simp{ 163123120Simp 164123120Simp return (XPRT_IDLE); 165123120Simp} 166123120Simp 167123120Simpstatic bool_t 168123120Simpsvc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg) 169123120Simp{ 170123120Simp struct uio uio; 171123120Simp struct sockaddr *raddr; 172123120Simp struct mbuf *mreq; 173123120Simp int error, rcvflag; 174123120Simp 175123120Simp /* 176123120Simp * The socket upcall calls xprt_active() which will eventually 177123120Simp * cause the server to call us here. We attempt to read a 178123120Simp * packet from the socket and process it. If the read fails, 179123120Simp * we have drained all pending requests so we call 180123120Simp * xprt_inactive(). 181123120Simp * 182123120Simp * The lock protects us in the case where a new packet arrives 183155049Srik * on the socket after our call to soreceive fails with 184123120Simp * EWOULDBLOCK - the call to xprt_active() in the upcall will 185123120Simp * happen only after our call to xprt_inactive() which ensures 186123120Simp * that we will remain active. It might be possible to use 187123120Simp * SOCKBUF_LOCK for this - its not clear to me what locks are 188123120Simp * held during the upcall. 189123120Simp */ 190123120Simp mtx_lock(&xprt->xp_lock); 191123120Simp 192123120Simp uio.uio_resid = 1000000000; 193123120Simp uio.uio_td = curthread; 194123120Simp mreq = NULL; 195123120Simp rcvflag = MSG_DONTWAIT; 196123120Simp error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag); 197123120Simp 198123120Simp if (error == EWOULDBLOCK) { 199123120Simp xprt_inactive(xprt); 200123120Simp mtx_unlock(&xprt->xp_lock); 201123120Simp return (FALSE); 202123120Simp } 203123120Simp 204123120Simp if (error) { 205123120Simp SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); 206123120Simp xprt->xp_socket->so_upcallarg = NULL; 207123120Simp xprt->xp_socket->so_upcall = NULL; 208123120Simp xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL; 209123120Simp SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); 210123120Simp xprt_inactive(xprt); 211123120Simp mtx_unlock(&xprt->xp_lock); 212123120Simp return (FALSE); 213123120Simp } 214123120Simp 215123120Simp mtx_unlock(&xprt->xp_lock); 216123120Simp 217123120Simp KASSERT(raddr->sa_len < xprt->xp_rtaddr.maxlen, 218123120Simp ("Unexpected remote address length")); 219123120Simp memcpy(xprt->xp_rtaddr.buf, raddr, raddr->sa_len); 220123120Simp xprt->xp_rtaddr.len = raddr->sa_len; 221123120Simp free(raddr, M_SONAME); 222123120Simp 223123120Simp xdrmbuf_create(&xprt->xp_xdrreq, mreq, XDR_DECODE); 224123120Simp if (! xdr_callmsg(&xprt->xp_xdrreq, msg)) { 225123120Simp XDR_DESTROY(&xprt->xp_xdrreq); 226123120Simp return (FALSE); 227123120Simp } 228123120Simp xprt->xp_xid = msg->rm_xid; 229123120Simp 230123120Simp return (TRUE); 231123120Simp} 232123120Simp 233123120Simpstatic bool_t 234123120Simpsvc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg) 235123120Simp{ 236123120Simp struct mbuf *mrep; 237123120Simp bool_t stat = FALSE; 238123120Simp int error; 239123120Simp 240123120Simp MGETHDR(mrep, M_WAIT, MT_DATA); 241123120Simp MCLGET(mrep, M_WAIT); 242123120Simp mrep->m_len = 0; 243123120Simp 244123120Simp xdrmbuf_create(&xprt->xp_xdrrep, mrep, XDR_ENCODE); 245123120Simp msg->rm_xid = xprt->xp_xid; 246123120Simp if (xdr_replymsg(&xprt->xp_xdrrep, msg)) { 247123120Simp m_fixhdr(mrep); 248123120Simp error = sosend(xprt->xp_socket, 249123120Simp (struct sockaddr *) xprt->xp_rtaddr.buf, NULL, mrep, NULL, 250123120Simp 0, curthread); 251123120Simp if (!error) { 252123120Simp stat = TRUE; 253123120Simp } 254123120Simp } else { 255123120Simp m_freem(mrep); 256123120Simp } 257123120Simp 258123120Simp /* 259123120Simp * This frees the request mbuf chain as well. The reply mbuf 260123120Simp * chain was consumed by sosend. 261123120Simp */ 262123120Simp XDR_DESTROY(&xprt->xp_xdrreq); 263123120Simp XDR_DESTROY(&xprt->xp_xdrrep); 264123120Simp xprt->xp_p2 = NULL; 265123120Simp 266123120Simp return (stat); 267123120Simp} 268123120Simp 269123120Simpstatic bool_t 270123120Simpsvc_dg_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) 271123120Simp{ 272123120Simp 273123120Simp return (xdr_args(&xprt->xp_xdrreq, args_ptr)); 274123120Simp} 275123120Simp 276123120Simpstatic bool_t 277123120Simpsvc_dg_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr) 278123120Simp{ 279123120Simp XDR xdrs; 280123120Simp 281123120Simp /* 282123120Simp * Free the request mbuf here - this allows us to handle 283123120Simp * protocols where not all requests have replies 284123120Simp * (i.e. NLM). Note that xdrmbuf_destroy handles being called 285123120Simp * twice correctly - the mbuf will only be freed once. 286123120Simp */ 287123120Simp XDR_DESTROY(&xprt->xp_xdrreq); 288123120Simp 289123120Simp xdrs.x_op = XDR_FREE; 290123120Simp return (xdr_args(&xdrs, args_ptr)); 291123120Simp} 292123120Simp 293123120Simpstatic void 294123120Simpsvc_dg_destroy(SVCXPRT *xprt) 295123120Simp{ 296123120Simp SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); 297123120Simp xprt->xp_socket->so_upcallarg = NULL; 298123120Simp xprt->xp_socket->so_upcall = NULL; 299123120Simp xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL; 300123120Simp SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); 301123120Simp 302123120Simp xprt_unregister(xprt); 303123120Simp 304123120Simp mtx_destroy(&xprt->xp_lock); 305123120Simp if (xprt->xp_socket) 306123120Simp (void)soclose(xprt->xp_socket); 307123120Simp 308123120Simp if (xprt->xp_rtaddr.buf) 309123120Simp (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 310123120Simp if (xprt->xp_ltaddr.buf) 311123120Simp (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 312123120Simp (void) mem_free(xprt, sizeof (SVCXPRT)); 313123120Simp} 314123120Simp 315123120Simpstatic bool_t 316123120Simp/*ARGSUSED*/ 317123120Simpsvc_dg_control(xprt, rq, in) 318123120Simp SVCXPRT *xprt; 319123120Simp const u_int rq; 320123120Simp void *in; 321123120Simp{ 322123120Simp 323123120Simp return (FALSE); 324123120Simp} 325123120Simp 326123120Simpstatic void 327123120Simpsvc_dg_soupcall(struct socket *so, void *arg, int waitflag) 328123120Simp{ 329123120Simp SVCXPRT *xprt = (SVCXPRT *) arg; 330123120Simp 331123120Simp mtx_lock(&xprt->xp_lock); 332123120Simp xprt_active(xprt); 333123120Simp mtx_unlock(&xprt->xp_lock); 334123120Simp} 335123120Simp