1dfdcada3SDoug Rabson /* $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ */ 2dfdcada3SDoug Rabson 32e322d37SHiroki Sato /*- 451369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 551369649SPedro F. Giffuni * 62e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 72e322d37SHiroki Sato * All rights reserved. 8dfdcada3SDoug Rabson * 92e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 102e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 112e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer. 132e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 142e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 152e322d37SHiroki Sato * and/or other materials provided with the distribution. 162e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 172e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 182e322d37SHiroki Sato * from this software without specific prior written permission. 19dfdcada3SDoug Rabson * 202e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 212e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 222e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 232e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 242e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 252e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 262e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 272e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 282e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 292e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 302e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 31dfdcada3SDoug Rabson */ 32dfdcada3SDoug Rabson 33dfdcada3SDoug Rabson /* 34dfdcada3SDoug Rabson * Copyright (c) 1986-1991 by Sun Microsystems Inc. 35dfdcada3SDoug Rabson */ 36dfdcada3SDoug Rabson 37dfdcada3SDoug Rabson /* 38dfdcada3SDoug Rabson * svc_dg.c, Server side for connectionless RPC. 39dfdcada3SDoug Rabson */ 40dfdcada3SDoug Rabson 41dfdcada3SDoug Rabson #include <sys/param.h> 426a76d35cSRick Macklem #include <sys/jail.h> 43dfdcada3SDoug Rabson #include <sys/lock.h> 44dfdcada3SDoug Rabson #include <sys/kernel.h> 45dfdcada3SDoug Rabson #include <sys/malloc.h> 46dfdcada3SDoug Rabson #include <sys/mbuf.h> 47dfdcada3SDoug Rabson #include <sys/mutex.h> 486a76d35cSRick Macklem #include <sys/proc.h> 49dfdcada3SDoug Rabson #include <sys/protosw.h> 50dfdcada3SDoug Rabson #include <sys/queue.h> 51dfdcada3SDoug Rabson #include <sys/socket.h> 52dfdcada3SDoug Rabson #include <sys/socketvar.h> 53a9148abdSDoug Rabson #include <sys/sx.h> 54dfdcada3SDoug Rabson #include <sys/systm.h> 55dfdcada3SDoug Rabson #include <sys/uio.h> 56dfdcada3SDoug Rabson 570348c661SMarko Zec #include <net/vnet.h> 580348c661SMarko Zec 59dfdcada3SDoug Rabson #include <rpc/rpc.h> 60dfdcada3SDoug Rabson 61ee31b83aSDoug Rabson #include <rpc/rpc_com.h> 62dfdcada3SDoug Rabson 63dfdcada3SDoug Rabson static enum xprt_stat svc_dg_stat(SVCXPRT *); 64a9148abdSDoug Rabson static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *, 65a9148abdSDoug Rabson struct sockaddr **, struct mbuf **); 66a9148abdSDoug Rabson static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *, 67d473bac7SAlexander Motin struct sockaddr *, struct mbuf *, uint32_t *); 68dfdcada3SDoug Rabson static void svc_dg_destroy(SVCXPRT *); 69dfdcada3SDoug Rabson static bool_t svc_dg_control(SVCXPRT *, const u_int, void *); 7074fb0ba7SJohn Baldwin static int svc_dg_soupcall(struct socket *so, void *arg, int waitflag); 71dfdcada3SDoug Rabson 7220d728b5SMark Johnston static const struct xp_ops svc_dg_ops = { 73dfdcada3SDoug Rabson .xp_recv = svc_dg_recv, 74dfdcada3SDoug Rabson .xp_stat = svc_dg_stat, 75dfdcada3SDoug Rabson .xp_reply = svc_dg_reply, 76dfdcada3SDoug Rabson .xp_destroy = svc_dg_destroy, 77dfdcada3SDoug Rabson .xp_control = svc_dg_control, 78dfdcada3SDoug Rabson }; 79dfdcada3SDoug Rabson 80dfdcada3SDoug Rabson /* 81dfdcada3SDoug Rabson * Usage: 82dfdcada3SDoug Rabson * xprt = svc_dg_create(sock, sendsize, recvsize); 83dfdcada3SDoug Rabson * Does other connectionless specific initializations. 84dfdcada3SDoug Rabson * Once *xprt is initialized, it is registered. 85dfdcada3SDoug Rabson * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable 86dfdcada3SDoug Rabson * system defaults are chosen. 87dfdcada3SDoug Rabson * The routines returns NULL if a problem occurred. 88dfdcada3SDoug Rabson */ 89dfdcada3SDoug Rabson static const char svc_dg_str[] = "svc_dg_create: %s"; 90dfdcada3SDoug Rabson static const char svc_dg_err1[] = "could not get transport information"; 91dfdcada3SDoug Rabson static const char svc_dg_err2[] = "transport does not support data transfer"; 92dfdcada3SDoug Rabson static const char __no_mem_str[] = "out of memory"; 93dfdcada3SDoug Rabson 94dfdcada3SDoug Rabson SVCXPRT * 95dfdcada3SDoug Rabson svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, 96dfdcada3SDoug Rabson size_t recvsize) 97dfdcada3SDoug Rabson { 98dfdcada3SDoug Rabson SVCXPRT *xprt; 99dfdcada3SDoug Rabson struct __rpc_sockinfo si; 100dfdcada3SDoug Rabson int error; 101dfdcada3SDoug Rabson 1026a76d35cSRick Macklem if (jailed(curthread->td_ucred)) 1036a76d35cSRick Macklem return (NULL); 104dfdcada3SDoug Rabson if (!__rpc_socket2sockinfo(so, &si)) { 105dfdcada3SDoug Rabson printf(svc_dg_str, svc_dg_err1); 106dfdcada3SDoug Rabson return (NULL); 107dfdcada3SDoug Rabson } 108dfdcada3SDoug Rabson /* 109dfdcada3SDoug Rabson * Find the receive and the send size 110dfdcada3SDoug Rabson */ 111dfdcada3SDoug Rabson sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 112dfdcada3SDoug Rabson recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 113dfdcada3SDoug Rabson if ((sendsize == 0) || (recvsize == 0)) { 114dfdcada3SDoug Rabson printf(svc_dg_str, svc_dg_err2); 115dfdcada3SDoug Rabson return (NULL); 116dfdcada3SDoug Rabson } 117dfdcada3SDoug Rabson 118a9148abdSDoug Rabson xprt = svc_xprt_alloc(); 119a9148abdSDoug Rabson sx_init(&xprt->xp_lock, "xprt->xp_lock"); 120dfdcada3SDoug Rabson xprt->xp_pool = pool; 121dfdcada3SDoug Rabson xprt->xp_socket = so; 122dfdcada3SDoug Rabson xprt->xp_p1 = NULL; 123dfdcada3SDoug Rabson xprt->xp_p2 = NULL; 124dfdcada3SDoug Rabson xprt->xp_ops = &svc_dg_ops; 125dfdcada3SDoug Rabson 1260fac350cSGleb Smirnoff xprt->xp_ltaddr.ss_len = sizeof(xprt->xp_ltaddr); 1270fac350cSGleb Smirnoff error = sosockaddr(so, (struct sockaddr *)&xprt->xp_ltaddr); 128dfdcada3SDoug Rabson if (error) 129dfdcada3SDoug Rabson goto freedata; 130dfdcada3SDoug Rabson 131dfdcada3SDoug Rabson xprt_register(xprt); 132dfdcada3SDoug Rabson 133*e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(so); 13474fb0ba7SJohn Baldwin soupcall_set(so, SO_RCV, svc_dg_soupcall, xprt); 135*e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(so); 136dfdcada3SDoug Rabson 137dfdcada3SDoug Rabson return (xprt); 138dfdcada3SDoug Rabson freedata: 139dfdcada3SDoug Rabson (void) printf(svc_dg_str, __no_mem_str); 140a9148abdSDoug Rabson svc_xprt_free(xprt); 141789872f2SEnji Cooper 142dfdcada3SDoug Rabson return (NULL); 143dfdcada3SDoug Rabson } 144dfdcada3SDoug Rabson 145dfdcada3SDoug Rabson /*ARGSUSED*/ 146dfdcada3SDoug Rabson static enum xprt_stat 147dfdcada3SDoug Rabson svc_dg_stat(SVCXPRT *xprt) 148dfdcada3SDoug Rabson { 149dfdcada3SDoug Rabson 150a9148abdSDoug Rabson if (soreadable(xprt->xp_socket)) 151a9148abdSDoug Rabson return (XPRT_MOREREQS); 152a9148abdSDoug Rabson 153dfdcada3SDoug Rabson return (XPRT_IDLE); 154dfdcada3SDoug Rabson } 155dfdcada3SDoug Rabson 156dfdcada3SDoug Rabson static bool_t 157a9148abdSDoug Rabson svc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg, 158a9148abdSDoug Rabson struct sockaddr **addrp, struct mbuf **mp) 159dfdcada3SDoug Rabson { 160dfdcada3SDoug Rabson struct uio uio; 161dfdcada3SDoug Rabson struct sockaddr *raddr; 162dfdcada3SDoug Rabson struct mbuf *mreq; 163a9148abdSDoug Rabson XDR xdrs; 164dfdcada3SDoug Rabson int error, rcvflag; 165dfdcada3SDoug Rabson 166dfdcada3SDoug Rabson /* 167a9148abdSDoug Rabson * Serialise access to the socket. 168a9148abdSDoug Rabson */ 169a9148abdSDoug Rabson sx_xlock(&xprt->xp_lock); 170a9148abdSDoug Rabson 171a9148abdSDoug Rabson /* 172dfdcada3SDoug Rabson * The socket upcall calls xprt_active() which will eventually 173dfdcada3SDoug Rabson * cause the server to call us here. We attempt to read a 174dfdcada3SDoug Rabson * packet from the socket and process it. If the read fails, 175dfdcada3SDoug Rabson * we have drained all pending requests so we call 176dfdcada3SDoug Rabson * xprt_inactive(). 177dfdcada3SDoug Rabson */ 178dfdcada3SDoug Rabson uio.uio_resid = 1000000000; 179dfdcada3SDoug Rabson uio.uio_td = curthread; 180dfdcada3SDoug Rabson mreq = NULL; 181dfdcada3SDoug Rabson rcvflag = MSG_DONTWAIT; 182dfdcada3SDoug Rabson error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag); 183dfdcada3SDoug Rabson 184dfdcada3SDoug Rabson if (error == EWOULDBLOCK) { 185a9148abdSDoug Rabson /* 186a9148abdSDoug Rabson * We must re-test for readability after taking the 187a9148abdSDoug Rabson * lock to protect us in the case where a new packet 188a9148abdSDoug Rabson * arrives on the socket after our call to soreceive 189a9148abdSDoug Rabson * fails with EWOULDBLOCK. The pool lock protects us 190a9148abdSDoug Rabson * from racing the upcall after our soreadable() call 191a9148abdSDoug Rabson * returns false. 192a9148abdSDoug Rabson */ 193*e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(xprt->xp_socket); 194a9148abdSDoug Rabson if (!soreadable(xprt->xp_socket)) 1955c42b9dcSAlexander Motin xprt_inactive_self(xprt); 196*e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(xprt->xp_socket); 197a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 198dfdcada3SDoug Rabson return (FALSE); 199dfdcada3SDoug Rabson } 200dfdcada3SDoug Rabson 201dfdcada3SDoug Rabson if (error) { 202*e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(xprt->xp_socket); 20374fb0ba7SJohn Baldwin soupcall_clear(xprt->xp_socket, SO_RCV); 204*e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(xprt->xp_socket); 2055c42b9dcSAlexander Motin xprt_inactive_self(xprt); 206a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 207dfdcada3SDoug Rabson return (FALSE); 208dfdcada3SDoug Rabson } 209dfdcada3SDoug Rabson 210a9148abdSDoug Rabson sx_xunlock(&xprt->xp_lock); 211dfdcada3SDoug Rabson 212a9148abdSDoug Rabson xdrmbuf_create(&xdrs, mreq, XDR_DECODE); 213a9148abdSDoug Rabson if (! xdr_callmsg(&xdrs, msg)) { 214a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 215dfdcada3SDoug Rabson return (FALSE); 216dfdcada3SDoug Rabson } 217a9148abdSDoug Rabson 218a9148abdSDoug Rabson *addrp = raddr; 219a9148abdSDoug Rabson *mp = xdrmbuf_getall(&xdrs); 220a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 221dfdcada3SDoug Rabson 222dfdcada3SDoug Rabson return (TRUE); 223dfdcada3SDoug Rabson } 224dfdcada3SDoug Rabson 225dfdcada3SDoug Rabson static bool_t 226a9148abdSDoug Rabson svc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg, 227d473bac7SAlexander Motin struct sockaddr *addr, struct mbuf *m, uint32_t *seq) 228dfdcada3SDoug Rabson { 229a9148abdSDoug Rabson XDR xdrs; 230dfdcada3SDoug Rabson struct mbuf *mrep; 231a9148abdSDoug Rabson bool_t stat = TRUE; 232dfdcada3SDoug Rabson int error; 233dfdcada3SDoug Rabson 234bd54830bSGleb Smirnoff mrep = m_gethdr(M_WAITOK, MT_DATA); 235dfdcada3SDoug Rabson 236a9148abdSDoug Rabson xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); 237a9148abdSDoug Rabson 238a9148abdSDoug Rabson if (msg->rm_reply.rp_stat == MSG_ACCEPTED && 239a9148abdSDoug Rabson msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { 240a9148abdSDoug Rabson if (!xdr_replymsg(&xdrs, msg)) 241a9148abdSDoug Rabson stat = FALSE; 242a9148abdSDoug Rabson else 243a9148abdSDoug Rabson xdrmbuf_append(&xdrs, m); 244a9148abdSDoug Rabson } else { 245a9148abdSDoug Rabson stat = xdr_replymsg(&xdrs, msg); 246a9148abdSDoug Rabson } 247a9148abdSDoug Rabson 248a9148abdSDoug Rabson if (stat) { 249dfdcada3SDoug Rabson m_fixhdr(mrep); 250a9148abdSDoug Rabson error = sosend(xprt->xp_socket, addr, NULL, mrep, NULL, 251dfdcada3SDoug Rabson 0, curthread); 252dfdcada3SDoug Rabson if (!error) { 253dfdcada3SDoug Rabson stat = TRUE; 254dfdcada3SDoug Rabson } 255dfdcada3SDoug Rabson } else { 256dfdcada3SDoug Rabson m_freem(mrep); 257dfdcada3SDoug Rabson } 258dfdcada3SDoug Rabson 259a9148abdSDoug Rabson XDR_DESTROY(&xdrs); 260dfdcada3SDoug Rabson xprt->xp_p2 = NULL; 261dfdcada3SDoug Rabson 262dfdcada3SDoug Rabson return (stat); 263dfdcada3SDoug Rabson } 264dfdcada3SDoug Rabson 265dfdcada3SDoug Rabson static void 266dfdcada3SDoug Rabson svc_dg_destroy(SVCXPRT *xprt) 267dfdcada3SDoug Rabson { 268a9148abdSDoug Rabson 269*e205fd31SGleb Smirnoff SOCK_RECVBUF_LOCK(xprt->xp_socket); 27074fb0ba7SJohn Baldwin soupcall_clear(xprt->xp_socket, SO_RCV); 271*e205fd31SGleb Smirnoff SOCK_RECVBUF_UNLOCK(xprt->xp_socket); 272dfdcada3SDoug Rabson 273a9148abdSDoug Rabson sx_destroy(&xprt->xp_lock); 274dfdcada3SDoug Rabson if (xprt->xp_socket) 275dfdcada3SDoug Rabson (void)soclose(xprt->xp_socket); 276dfdcada3SDoug Rabson 277a9148abdSDoug Rabson if (xprt->xp_netid) 278a9148abdSDoug Rabson (void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1); 279a9148abdSDoug Rabson svc_xprt_free(xprt); 280dfdcada3SDoug Rabson } 281dfdcada3SDoug Rabson 282dfdcada3SDoug Rabson static bool_t 283dfdcada3SDoug Rabson /*ARGSUSED*/ 28471948c15SMateusz Guzik svc_dg_control(SVCXPRT *xprt, const u_int rq, void *in) 285dfdcada3SDoug Rabson { 286dfdcada3SDoug Rabson 287dfdcada3SDoug Rabson return (FALSE); 288dfdcada3SDoug Rabson } 289dfdcada3SDoug Rabson 29074fb0ba7SJohn Baldwin static int 291dfdcada3SDoug Rabson svc_dg_soupcall(struct socket *so, void *arg, int waitflag) 292dfdcada3SDoug Rabson { 293dfdcada3SDoug Rabson SVCXPRT *xprt = (SVCXPRT *) arg; 294dfdcada3SDoug Rabson 295dfdcada3SDoug Rabson xprt_active(xprt); 29674fb0ba7SJohn Baldwin return (SU_OK); 297dfdcada3SDoug Rabson } 298