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