[ 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  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

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

Cache object: b33949e8bb3af415698ea9cec71af251


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