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_generic.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_generic.c,v 1.3 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_generic.c      1.19    94/04/24 SMI" 
   37 static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
   38 #endif
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/11.0/sys/rpc/svc_generic.c 281199 2015-04-07 10:25:27Z mav $");
   41 
   42 /*
   43  * svc_generic.c, Server side for RPC.
   44  *
   45  */
   46 
   47 #include "opt_inet6.h"
   48 
   49 #include <sys/param.h>
   50 #include <sys/lock.h>
   51 #include <sys/kernel.h>
   52 #include <sys/malloc.h>
   53 #include <sys/mutex.h>
   54 #include <sys/protosw.h>
   55 #include <sys/queue.h>
   56 #include <sys/socket.h>
   57 #include <sys/socketvar.h>
   58 #include <sys/systm.h>
   59 #include <sys/sx.h>
   60 #include <sys/ucred.h>
   61 
   62 #include <net/vnet.h>
   63 
   64 #include <rpc/rpc.h>
   65 #include <rpc/rpcb_clnt.h>
   66 #include <rpc/nettype.h>
   67 
   68 #include <rpc/rpc_com.h>
   69 
   70 extern int __svc_vc_setflag(SVCXPRT *, int);
   71 
   72 /*
   73  * The highest level interface for server creation.
   74  * It tries for all the nettokens in that particular class of token
   75  * and returns the number of handles it can create and/or find.
   76  *
   77  * It creates a link list of all the handles it could create.
   78  * If svc_create() is called multiple times, it uses the handle
   79  * created earlier instead of creating a new handle every time.
   80  */
   81 int
   82 svc_create(
   83         SVCPOOL *pool,
   84         void (*dispatch)(struct svc_req *, SVCXPRT *),
   85         rpcprog_t prognum,              /* Program number */
   86         rpcvers_t versnum,              /* Version number */
   87         const char *nettype)            /* Networktype token */
   88 {
   89         int g, num = 0;
   90         SVCGROUP *grp;
   91         SVCXPRT *xprt;
   92         struct netconfig *nconf;
   93         void *handle;
   94 
   95         if ((handle = __rpc_setconf(nettype)) == NULL) {
   96                 printf("svc_create: unknown protocol");
   97                 return (0);
   98         }
   99         while ((nconf = __rpc_getconf(handle)) != NULL) {
  100                 for (g = 0; g < SVC_MAXGROUPS; g++) {
  101                         grp = &pool->sp_groups[g];
  102                         mtx_lock(&grp->sg_lock);
  103                         TAILQ_FOREACH(xprt, &grp->sg_xlist, xp_link) {
  104                                 if (strcmp(xprt->xp_netid, nconf->nc_netid))
  105                                         continue;
  106                                 /* Found an old one, use it */
  107                                 mtx_unlock(&grp->sg_lock);
  108                                 (void) rpcb_unset(prognum, versnum, nconf);
  109                                 if (svc_reg(xprt, prognum, versnum,
  110                                         dispatch, nconf) == FALSE) {
  111                                         printf(
  112                 "svc_create: could not register prog %u vers %u on %s\n",
  113                                         (unsigned)prognum, (unsigned)versnum,
  114                                          nconf->nc_netid);
  115                                         mtx_lock(&grp->sg_lock);
  116                                 } else {
  117                                         num++;
  118                                         mtx_lock(&grp->sg_lock);
  119                                         break;
  120                                 }
  121                         }
  122                         mtx_unlock(&grp->sg_lock);
  123                 }
  124                 if (xprt == NULL) {
  125                         /* It was not found. Now create a new one */
  126                         xprt = svc_tp_create(pool, dispatch, prognum, versnum,
  127                             NULL, nconf);
  128                         if (xprt) {
  129                                 num++;
  130                                 SVC_RELEASE(xprt);
  131                         }
  132                 }
  133         }
  134         __rpc_endconf(handle);
  135         /*
  136          * In case of num == 0; the error messages are generated by the
  137          * underlying layers; and hence not needed here.
  138          */
  139         return (num);
  140 }
  141 
  142 /*
  143  * The high level interface to svc_tli_create().
  144  * It tries to create a server for "nconf" and registers the service
  145  * with the rpcbind. It calls svc_tli_create();
  146  */
  147 SVCXPRT *
  148 svc_tp_create(
  149         SVCPOOL *pool,
  150         void (*dispatch)(struct svc_req *, SVCXPRT *),
  151         rpcprog_t prognum,              /* Program number */
  152         rpcvers_t versnum,              /* Version number */
  153         const char *uaddr,              /* Address (or null for default) */
  154         const struct netconfig *nconf) /* Netconfig structure for the network */
  155 {
  156         struct netconfig nconfcopy;
  157         struct netbuf *taddr;
  158         struct t_bind bind;
  159         SVCXPRT *xprt;
  160 
  161         if (nconf == NULL) {
  162                 printf(
  163         "svc_tp_create: invalid netconfig structure for prog %u vers %u\n",
  164                                 (unsigned)prognum, (unsigned)versnum);
  165                 return (NULL);
  166         }
  167         if (uaddr) {
  168                 taddr = uaddr2taddr(nconf, uaddr);
  169                 bind.addr = *taddr;
  170                 free(taddr, M_RPC);
  171                 bind.qlen = -1;
  172                 xprt = svc_tli_create(pool, NULL, nconf, &bind, 0, 0);
  173                 free(bind.addr.buf, M_RPC);
  174         } else {
  175                 xprt = svc_tli_create(pool, NULL, nconf, NULL, 0, 0);
  176         }
  177         if (xprt == NULL) {
  178                 return (NULL);
  179         }
  180         /*LINTED const castaway*/
  181         nconfcopy = *nconf;
  182         (void) rpcb_unset(prognum, versnum, &nconfcopy);
  183         if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
  184                 printf(
  185                 "svc_tp_create: Could not register prog %u vers %u on %s\n",
  186                                 (unsigned)prognum, (unsigned)versnum,
  187                                 nconf->nc_netid);
  188                 xprt_unregister(xprt);
  189                 SVC_RELEASE(xprt);
  190                 return (NULL);
  191         }
  192         return (xprt);
  193 }
  194 
  195 /*
  196  * If so is NULL, then it opens a socket for the given transport
  197  * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
  198  * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
  199  * NULL bindadr and Connection oriented transports, the value of qlen
  200  * is set to 8.
  201  *
  202  * If sendsz or recvsz are zero, their default values are chosen.
  203  */
  204 SVCXPRT *
  205 svc_tli_create(
  206         SVCPOOL *pool,
  207         struct socket *so,              /* Connection end point */
  208         const struct netconfig *nconf,  /* Netconfig struct for nettoken */
  209         const struct t_bind *bindaddr,  /* Local bind address */
  210         size_t sendsz,                  /* Max sendsize */
  211         size_t recvsz)                  /* Max recvsize */
  212 {
  213         SVCXPRT *xprt = NULL;           /* service handle */
  214         bool_t madeso = FALSE;          /* whether so opened here  */
  215         struct __rpc_sockinfo si;
  216         struct sockaddr_storage ss;
  217 
  218         if (!so) {
  219                 if (nconf == NULL) {
  220                         printf("svc_tli_create: invalid netconfig\n");
  221                         return (NULL);
  222                 }
  223                 so = __rpc_nconf2socket(nconf);
  224                 if (!so) {
  225                         printf(
  226                             "svc_tli_create: could not open connection for %s\n",
  227                                         nconf->nc_netid);
  228                         return (NULL);
  229                 }
  230                 __rpc_nconf2sockinfo(nconf, &si);
  231                 madeso = TRUE;
  232         } else {
  233                 /*
  234                  * It is an open socket. Get the transport info.
  235                  */
  236                 if (!__rpc_socket2sockinfo(so, &si)) {
  237                         printf(
  238                 "svc_tli_create: could not get transport information\n");
  239                         return (NULL);
  240                 }
  241         }
  242 
  243         /*
  244          * If the socket is unbound, try to bind it.
  245          */
  246         if (madeso || !__rpc_sockisbound(so)) {
  247                 if (bindaddr == NULL) {
  248                         if (bindresvport(so, NULL)) {
  249                                 memset(&ss, 0, sizeof ss);
  250                                 ss.ss_family = si.si_af;
  251                                 ss.ss_len = si.si_alen;
  252                                 if (sobind(so, (struct sockaddr *)&ss,
  253                                         curthread)) {
  254                                         printf(
  255                         "svc_tli_create: could not bind to anonymous port\n");
  256                                         goto freedata;
  257                                 }
  258                         }
  259                         solisten(so, -1, curthread);
  260                 } else {
  261                         if (bindresvport(so,
  262                                 (struct sockaddr *)bindaddr->addr.buf)) {
  263                                 printf(
  264                 "svc_tli_create: could not bind to requested address\n");
  265                                 goto freedata;
  266                         }
  267                         solisten(so, (int)bindaddr->qlen, curthread);
  268                 }
  269                         
  270         }
  271         /*
  272          * call transport specific function.
  273          */
  274         switch (si.si_socktype) {
  275                 case SOCK_STREAM:
  276 #if 0
  277                         slen = sizeof ss;
  278                         if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
  279                             == 0) {
  280                                 /* accepted socket */
  281                                 xprt = svc_fd_create(fd, sendsz, recvsz);
  282                         } else
  283 #endif
  284                                 xprt = svc_vc_create(pool, so, sendsz, recvsz);
  285                         if (!nconf || !xprt)
  286                                 break;
  287 #if 0
  288                         /* XXX fvdl */
  289                         if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
  290                             strcmp(nconf->nc_protofmly, "inet6") == 0)
  291                                 (void) __svc_vc_setflag(xprt, TRUE);
  292 #endif
  293                         break;
  294                 case SOCK_DGRAM:
  295                         xprt = svc_dg_create(pool, so, sendsz, recvsz);
  296                         break;
  297                 default:
  298                         printf("svc_tli_create: bad service type");
  299                         goto freedata;
  300         }
  301 
  302         if (xprt == NULL)
  303                 /*
  304                  * The error messages here are spitted out by the lower layers:
  305                  * svc_vc_create(), svc_fd_create() and svc_dg_create().
  306                  */
  307                 goto freedata;
  308 
  309         /* Fill in type of service */
  310         xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
  311 
  312         if (nconf) {
  313                 xprt->xp_netid = strdup(nconf->nc_netid, M_RPC);
  314         }
  315         return (xprt);
  316 
  317 freedata:
  318         if (madeso)
  319                 (void)soclose(so);
  320         if (xprt) {
  321                 if (!madeso) /* so that svc_destroy doesnt close fd */
  322                         xprt->xp_socket = NULL;
  323                 xprt_unregister(xprt);
  324         }
  325         return (NULL);
  326 }

Cache object: 0d5ac2b8ca7909d1aec4b02459092d08


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