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  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
    5  * unrestricted use provided that this legend is included on all tape
    6  * media and as a part of the software program in whole or part.  Users
    7  * may copy or modify Sun RPC without charge, but are not authorized
    8  * to license or distribute it to anyone else except as part of a product or
    9  * program developed by the user.
   10  * 
   11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
   12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
   13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
   14  * 
   15  * Sun RPC is provided with no support and without any obligation on the
   16  * part of Sun Microsystems, Inc. to assist in its use, correction,
   17  * modification or enhancement.
   18  * 
   19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
   20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
   21  * OR ANY PART THEREOF.
   22  * 
   23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
   24  * or profits or other special, indirect and consequential damages, even if
   25  * Sun has been advised of the possibility of such damages.
   26  * 
   27  * Sun Microsystems, Inc.
   28  * 2550 Garcia Avenue
   29  * Mountain View, California  94043
   30  */
   31 
   32 /*
   33  * Copyright (c) 1986-1991 by Sun Microsystems Inc.
   34  */
   35 
   36 #if defined(LIBC_SCCS) && !defined(lint)
   37 #ident  "@(#)svc_dg.c   1.17    94/04/24 SMI"
   38 #endif
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 /*
   43  * svc_dg.c, Server side for connectionless RPC.
   44  */
   45 
   46 #include <sys/param.h>
   47 #include <sys/lock.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mbuf.h>
   51 #include <sys/mutex.h>
   52 #include <sys/protosw.h>
   53 #include <sys/queue.h>
   54 #include <sys/socket.h>
   55 #include <sys/socketvar.h>
   56 #include <sys/sx.h>
   57 #include <sys/systm.h>
   58 #include <sys/uio.h>
   59 
   60 #include <rpc/rpc.h>
   61 
   62 #include <rpc/rpc_com.h>
   63 
   64 static enum xprt_stat svc_dg_stat(SVCXPRT *);
   65 static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *);
   66 static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *);
   67 static bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *);
   68 static bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *);
   69 static void svc_dg_destroy(SVCXPRT *);
   70 static bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
   71 static void svc_dg_soupcall(struct socket *so, void *arg, int waitflag);
   72 
   73 static struct xp_ops svc_dg_ops = {
   74         .xp_recv =      svc_dg_recv,
   75         .xp_stat =      svc_dg_stat,
   76         .xp_getargs =   svc_dg_getargs,
   77         .xp_reply =     svc_dg_reply,
   78         .xp_freeargs =  svc_dg_freeargs,
   79         .xp_destroy =   svc_dg_destroy,
   80         .xp_control =   svc_dg_control,
   81 };
   82 
   83 /*
   84  * Usage:
   85  *      xprt = svc_dg_create(sock, sendsize, recvsize);
   86  * Does other connectionless specific initializations.
   87  * Once *xprt is initialized, it is registered.
   88  * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
   89  * system defaults are chosen.
   90  * The routines returns NULL if a problem occurred.
   91  */
   92 static const char svc_dg_str[] = "svc_dg_create: %s";
   93 static const char svc_dg_err1[] = "could not get transport information";
   94 static const char svc_dg_err2[] = "transport does not support data transfer";
   95 static const char __no_mem_str[] = "out of memory";
   96 
   97 SVCXPRT *
   98 svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
   99     size_t recvsize)
  100 {
  101         SVCXPRT *xprt;
  102         struct __rpc_sockinfo si;
  103         struct sockaddr* sa;
  104         int error;
  105 
  106         if (!__rpc_socket2sockinfo(so, &si)) {
  107                 printf(svc_dg_str, svc_dg_err1);
  108                 return (NULL);
  109         }
  110         /*
  111          * Find the receive and the send size
  112          */
  113         sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
  114         recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
  115         if ((sendsize == 0) || (recvsize == 0)) {
  116                 printf(svc_dg_str, svc_dg_err2);
  117                 return (NULL);
  118         }
  119 
  120         xprt = mem_alloc(sizeof (SVCXPRT));
  121         memset(xprt, 0, sizeof (SVCXPRT));
  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         error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  130         if (error)
  131                 goto freedata;
  132 
  133         xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
  134         xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
  135         xprt->xp_ltaddr.len = sa->sa_len;
  136         memcpy(xprt->xp_ltaddr.buf, sa, sa->sa_len);
  137         free(sa, M_SONAME);
  138 
  139         xprt->xp_rtaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
  140         xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
  141         xprt->xp_rtaddr.len = 0;
  142 
  143         xprt_register(xprt);
  144 
  145         SOCKBUF_LOCK(&so->so_rcv);
  146         so->so_upcallarg = xprt;
  147         so->so_upcall = svc_dg_soupcall;
  148         so->so_rcv.sb_flags |= SB_UPCALL;
  149         SOCKBUF_UNLOCK(&so->so_rcv);
  150 
  151         return (xprt);
  152 freedata:
  153         (void) printf(svc_dg_str, __no_mem_str);
  154         if (xprt) {
  155                 (void) mem_free(xprt, sizeof (SVCXPRT));
  156         }
  157         return (NULL);
  158 }
  159 
  160 /*ARGSUSED*/
  161 static enum xprt_stat
  162 svc_dg_stat(SVCXPRT *xprt)
  163 {
  164 
  165         if (soreadable(xprt->xp_socket))
  166                 return (XPRT_MOREREQS);
  167 
  168         return (XPRT_IDLE);
  169 }
  170 
  171 static bool_t
  172 svc_dg_recv(SVCXPRT *xprt, struct rpc_msg *msg)
  173 {
  174         struct uio uio;
  175         struct sockaddr *raddr;
  176         struct mbuf *mreq;
  177         int error, rcvflag;
  178 
  179         /*
  180          * Serialise access to the socket.
  181          */
  182         sx_xlock(&xprt->xp_lock);
  183 
  184         /*
  185          * The socket upcall calls xprt_active() which will eventually
  186          * cause the server to call us here. We attempt to read a
  187          * packet from the socket and process it. If the read fails,
  188          * we have drained all pending requests so we call
  189          * xprt_inactive().
  190          */
  191         uio.uio_resid = 1000000000;
  192         uio.uio_td = curthread;
  193         mreq = NULL;
  194         rcvflag = MSG_DONTWAIT;
  195         error = soreceive(xprt->xp_socket, &raddr, &uio, &mreq, NULL, &rcvflag);
  196 
  197         if (error == EWOULDBLOCK) {
  198                 /*
  199                  * We must re-test for readability after taking the
  200                  * lock to protect us in the case where a new packet
  201                  * arrives on the socket after our call to soreceive
  202                  * fails with EWOULDBLOCK. The pool lock protects us
  203                  * from racing the upcall after our soreadable() call
  204                  * returns false.
  205                  */
  206                 mtx_lock(&xprt->xp_pool->sp_lock);
  207                 if (!soreadable(xprt->xp_socket))
  208                         xprt_inactive_locked(xprt);
  209                 mtx_unlock(&xprt->xp_pool->sp_lock);
  210                 sx_xunlock(&xprt->xp_lock);
  211                 return (FALSE);
  212         }
  213 
  214         if (error) {
  215                 SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
  216                 xprt->xp_socket->so_upcallarg = NULL;
  217                 xprt->xp_socket->so_upcall = NULL;
  218                 xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL;
  219                 SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
  220                 xprt_inactive(xprt);
  221                 sx_xunlock(&xprt->xp_lock);
  222                 return (FALSE);
  223         }
  224 
  225         sx_xunlock(&xprt->xp_lock);
  226 
  227         KASSERT(raddr->sa_len < xprt->xp_rtaddr.maxlen,
  228             ("Unexpected remote address length"));
  229         memcpy(xprt->xp_rtaddr.buf, raddr, raddr->sa_len);
  230         xprt->xp_rtaddr.len = raddr->sa_len;
  231         free(raddr, M_SONAME);
  232 
  233         xdrmbuf_create(&xprt->xp_xdrreq, mreq, XDR_DECODE);
  234         if (! xdr_callmsg(&xprt->xp_xdrreq, msg)) {
  235                 XDR_DESTROY(&xprt->xp_xdrreq);
  236                 return (FALSE);
  237         }
  238         xprt->xp_xid = msg->rm_xid;
  239 
  240         return (TRUE);
  241 }
  242 
  243 static bool_t
  244 svc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg)
  245 {
  246         struct mbuf *mrep;
  247         bool_t stat = FALSE;
  248         int error;
  249 
  250         MGETHDR(mrep, M_WAIT, MT_DATA);
  251         MCLGET(mrep, M_WAIT);
  252         mrep->m_len = 0;
  253 
  254         xdrmbuf_create(&xprt->xp_xdrrep, mrep, XDR_ENCODE);
  255         msg->rm_xid = xprt->xp_xid;
  256         if (xdr_replymsg(&xprt->xp_xdrrep, msg)) {
  257                 m_fixhdr(mrep);
  258                 error = sosend(xprt->xp_socket,
  259                     (struct sockaddr *) xprt->xp_rtaddr.buf, NULL, mrep, NULL,
  260                     0, curthread);
  261                 if (!error) {
  262                         stat = TRUE;
  263                 }
  264         } else {
  265                 m_freem(mrep);
  266         }
  267 
  268         /*
  269          * This frees the request mbuf chain as well. The reply mbuf
  270          * chain was consumed by sosend.
  271          */
  272         XDR_DESTROY(&xprt->xp_xdrreq);
  273         XDR_DESTROY(&xprt->xp_xdrrep);
  274         xprt->xp_p2 = NULL;
  275 
  276         return (stat);
  277 }
  278 
  279 static bool_t
  280 svc_dg_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
  281 {
  282 
  283         return (xdr_args(&xprt->xp_xdrreq, args_ptr));
  284 }
  285 
  286 static bool_t
  287 svc_dg_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, void *args_ptr)
  288 {
  289         XDR xdrs;
  290 
  291         /*
  292          * Free the request mbuf here - this allows us to handle
  293          * protocols where not all requests have replies
  294          * (i.e. NLM). Note that xdrmbuf_destroy handles being called
  295          * twice correctly - the mbuf will only be freed once.
  296          */
  297         XDR_DESTROY(&xprt->xp_xdrreq);
  298 
  299         xdrs.x_op = XDR_FREE;
  300         return (xdr_args(&xdrs, args_ptr));
  301 }
  302 
  303 static void
  304 svc_dg_destroy(SVCXPRT *xprt)
  305 {
  306         SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
  307         xprt->xp_socket->so_upcallarg = NULL;
  308         xprt->xp_socket->so_upcall = NULL;
  309         xprt->xp_socket->so_rcv.sb_flags &= ~SB_UPCALL;
  310         SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
  311 
  312         xprt_unregister(xprt);
  313 
  314         sx_destroy(&xprt->xp_lock);
  315         if (xprt->xp_socket)
  316                 (void)soclose(xprt->xp_socket);
  317 
  318         if (xprt->xp_rtaddr.buf)
  319                 (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
  320         if (xprt->xp_ltaddr.buf)
  321                 (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
  322         (void) mem_free(xprt, sizeof (SVCXPRT));
  323 }
  324 
  325 static bool_t
  326 /*ARGSUSED*/
  327 svc_dg_control(xprt, rq, in)
  328         SVCXPRT *xprt;
  329         const u_int     rq;
  330         void            *in;
  331 {
  332 
  333         return (FALSE);
  334 }
  335 
  336 static void
  337 svc_dg_soupcall(struct socket *so, void *arg, int waitflag)
  338 {
  339         SVCXPRT *xprt = (SVCXPRT *) arg;
  340 
  341         xprt_active(xprt);
  342 }

Cache object: b074b0e1dcfcc9733c40b98c227c97e8


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