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$");
   42 
   43 /*
   44  * svc_dg.c, Server side for connectionless RPC.
   45  */
   46 
   47 #include <sys/param.h>
   48 #include <sys/jail.h>
   49 #include <sys/lock.h>
   50 #include <sys/kernel.h>
   51 #include <sys/malloc.h>
   52 #include <sys/mbuf.h>
   53 #include <sys/mutex.h>
   54 #include <sys/proc.h>
   55 #include <sys/protosw.h>
   56 #include <sys/queue.h>
   57 #include <sys/socket.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/sx.h>
   60 #include <sys/systm.h>
   61 #include <sys/uio.h>
   62 
   63 #include <net/vnet.h>
   64 
   65 #include <rpc/rpc.h>
   66 
   67 #include <rpc/rpc_com.h>
   68 
   69 static enum xprt_stat svc_dg_stat(SVCXPRT *);
   70 static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *,
   71     struct sockaddr **, struct mbuf **);
   72 static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *,
   73     struct sockaddr *, struct mbuf *, uint32_t *);
   74 static void svc_dg_destroy(SVCXPRT *);
   75 static bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
   76 static int svc_dg_soupcall(struct socket *so, void *arg, int waitflag);
   77 
   78 static const struct xp_ops svc_dg_ops = {
   79         .xp_recv =      svc_dg_recv,
   80         .xp_stat =      svc_dg_stat,
   81         .xp_reply =     svc_dg_reply,
   82         .xp_destroy =   svc_dg_destroy,
   83         .xp_control =   svc_dg_control,
   84 };
   85 
   86 /*
   87  * Usage:
   88  *      xprt = svc_dg_create(sock, sendsize, recvsize);
   89  * Does other connectionless specific initializations.
   90  * Once *xprt is initialized, it is registered.
   91  * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
   92  * system defaults are chosen.
   93  * The routines returns NULL if a problem occurred.
   94  */
   95 static const char svc_dg_str[] = "svc_dg_create: %s";
   96 static const char svc_dg_err1[] = "could not get transport information";
   97 static const char svc_dg_err2[] = "transport does not support data transfer";
   98 static const char __no_mem_str[] = "out of memory";
   99 
  100 SVCXPRT *
  101 svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
  102     size_t recvsize)
  103 {
  104         SVCXPRT *xprt;
  105         struct __rpc_sockinfo si;
  106         struct sockaddr* sa;
  107         int error;
  108 
  109         if (jailed(curthread->td_ucred))
  110                 return (NULL);
  111         if (!__rpc_socket2sockinfo(so, &si)) {
  112                 printf(svc_dg_str, svc_dg_err1);
  113                 return (NULL);
  114         }
  115         /*
  116          * Find the receive and the send size
  117          */
  118         sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
  119         recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
  120         if ((sendsize == 0) || (recvsize == 0)) {
  121                 printf(svc_dg_str, svc_dg_err2);
  122                 return (NULL);
  123         }
  124 
  125         xprt = svc_xprt_alloc();
  126         sx_init(&xprt->xp_lock, "xprt->xp_lock");
  127         xprt->xp_pool = pool;
  128         xprt->xp_socket = so;
  129         xprt->xp_p1 = NULL;
  130         xprt->xp_p2 = NULL;
  131         xprt->xp_ops = &svc_dg_ops;
  132 
  133         CURVNET_SET(so->so_vnet);
  134         error = so->so_proto->pr_sockaddr(so, &sa);
  135         CURVNET_RESTORE();
  136         if (error)
  137                 goto freedata;
  138 
  139         memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
  140         free(sa, M_SONAME);
  141 
  142         xprt_register(xprt);
  143 
  144         SOCKBUF_LOCK(&so->so_rcv);
  145         soupcall_set(so, SO_RCV, svc_dg_soupcall, xprt);
  146         SOCKBUF_UNLOCK(&so->so_rcv);
  147 
  148         return (xprt);
  149 freedata:
  150         (void) printf(svc_dg_str, __no_mem_str);
  151         svc_xprt_free(xprt);
  152 
  153         return (NULL);
  154 }
  155 
  156 /*ARGSUSED*/
  157 static enum xprt_stat
  158 svc_dg_stat(SVCXPRT *xprt)
  159 {
  160 
  161         if (soreadable(xprt->xp_socket))
  162                 return (XPRT_MOREREQS);
  163 
  164         return (XPRT_IDLE);
  165 }
  166 
  167 static bool_t
  168 svc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg,
  169     struct sockaddr **addrp, struct mbuf **mp)
  170 {
  171         struct uio uio;
  172         struct sockaddr *raddr;
  173         struct mbuf *mreq;
  174         XDR xdrs;
  175         int error, rcvflag;
  176 
  177         /*
  178          * Serialise access to the socket.
  179          */
  180         sx_xlock(&xprt->xp_lock);
  181 
  182         /*
  183          * The socket upcall calls xprt_active() which will eventually
  184          * cause the server to call us here. We attempt to read a
  185          * packet from the socket and process it. If the read fails,
  186          * we have drained all pending requests so we call
  187          * xprt_inactive().
  188          */
  189         uio.uio_resid = 1000000000;
  190         uio.uio_td = curthread;
  191         mreq = NULL;
  192         rcvflag = MSG_DONTWAIT;
  193         error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag);
  194 
  195         if (error == EWOULDBLOCK) {
  196                 /*
  197                  * We must re-test for readability after taking the
  198                  * lock to protect us in the case where a new packet
  199                  * arrives on the socket after our call to soreceive
  200                  * fails with EWOULDBLOCK. The pool lock protects us
  201                  * from racing the upcall after our soreadable() call
  202                  * returns false.
  203                  */
  204                 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
  205                 if (!soreadable(xprt->xp_socket))
  206                         xprt_inactive_self(xprt);
  207                 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
  208                 sx_xunlock(&xprt->xp_lock);
  209                 return (FALSE);
  210         }
  211 
  212         if (error) {
  213                 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
  214                 soupcall_clear(xprt->xp_socket, SO_RCV);
  215                 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
  216                 xprt_inactive_self(xprt);
  217                 sx_xunlock(&xprt->xp_lock);
  218                 return (FALSE);
  219         }
  220 
  221         sx_xunlock(&xprt->xp_lock);
  222 
  223         xdrmbuf_create(&xdrs, mreq, XDR_DECODE);
  224         if (! xdr_callmsg(&xdrs, msg)) {
  225                 XDR_DESTROY(&xdrs);
  226                 return (FALSE);
  227         }
  228 
  229         *addrp = raddr;
  230         *mp = xdrmbuf_getall(&xdrs);
  231         XDR_DESTROY(&xdrs);
  232 
  233         return (TRUE);
  234 }
  235 
  236 static bool_t
  237 svc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg,
  238     struct sockaddr *addr, struct mbuf *m, uint32_t *seq)
  239 {
  240         XDR xdrs;
  241         struct mbuf *mrep;
  242         bool_t stat = TRUE;
  243         int error;
  244 
  245         mrep = m_gethdr(M_WAITOK, MT_DATA);
  246 
  247         xdrmbuf_create(&xdrs, mrep, XDR_ENCODE);
  248 
  249         if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
  250             msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
  251                 if (!xdr_replymsg(&xdrs, msg))
  252                         stat = FALSE;
  253                 else
  254                         xdrmbuf_append(&xdrs, m);
  255         } else {
  256                 stat = xdr_replymsg(&xdrs, msg);
  257         }
  258 
  259         if (stat) {
  260                 m_fixhdr(mrep);
  261                 error = sosend(xprt->xp_socket, addr, NULL, mrep, NULL,
  262                     0, curthread);
  263                 if (!error) {
  264                         stat = TRUE;
  265                 }
  266         } else {
  267                 m_freem(mrep);
  268         }
  269 
  270         XDR_DESTROY(&xdrs);
  271         xprt->xp_p2 = NULL;
  272 
  273         return (stat);
  274 }
  275 
  276 static void
  277 svc_dg_destroy(SVCXPRT *xprt)
  278 {
  279 
  280         SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
  281         soupcall_clear(xprt->xp_socket, SO_RCV);
  282         SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
  283 
  284         sx_destroy(&xprt->xp_lock);
  285         if (xprt->xp_socket)
  286                 (void)soclose(xprt->xp_socket);
  287 
  288         if (xprt->xp_netid)
  289                 (void) mem_free(xprt->xp_netid, strlen(xprt->xp_netid) + 1);
  290         svc_xprt_free(xprt);
  291 }
  292 
  293 static bool_t
  294 /*ARGSUSED*/
  295 svc_dg_control(xprt, rq, in)
  296         SVCXPRT *xprt;
  297         const u_int     rq;
  298         void            *in;
  299 {
  300 
  301         return (FALSE);
  302 }
  303 
  304 static int
  305 svc_dg_soupcall(struct socket *so, void *arg, int waitflag)
  306 {
  307         SVCXPRT *xprt = (SVCXPRT *) arg;
  308 
  309         xprt_active(xprt);
  310         return (SU_OK);
  311 }

Cache object: ab2b9a1b36d514436ee6eeb7a1229128


[ 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.