The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/rpc/svc_dg.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8dea924b0659174e7f0ab13a48e53ea2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.