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