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

Cache object: c1c16120a819582a855c96838337af00


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