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/rpc_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: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink 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  * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
   32  */
   33 
   34 /* #pragma ident        "@(#)rpc_generic.c      1.17    94/04/24 SMI" */
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/10.4/sys/rpc/rpc_generic.c 319615 2017-06-06 07:22:26Z delphij $");
   37 
   38 /*
   39  * rpc_generic.c, Miscl routines for RPC.
   40  *
   41  */
   42 
   43 #include "opt_inet6.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/module.h>
   50 #include <sys/proc.h>
   51 #include <sys/protosw.h>
   52 #include <sys/sbuf.h>
   53 #include <sys/systm.h>
   54 #include <sys/socket.h>
   55 #include <sys/socketvar.h>
   56 #include <sys/syslog.h>
   57 
   58 #include <net/vnet.h>
   59 
   60 #include <rpc/rpc.h>
   61 #include <rpc/nettype.h>
   62 #include <rpc/rpcsec_gss.h>
   63 
   64 #include <rpc/rpc_com.h>
   65 
   66 extern  u_long sb_max_adj;      /* not defined in socketvar.h */
   67 
   68 #if __FreeBSD_version < 700000
   69 #define strrchr rindex
   70 #endif
   71 
   72 /* Provide an entry point hook for the rpcsec_gss module. */
   73 struct rpc_gss_entries  rpc_gss_entries;
   74 
   75 struct handle {
   76         NCONF_HANDLE *nhandle;
   77         int nflag;              /* Whether NETPATH or NETCONFIG */
   78         int nettype;
   79 };
   80 
   81 static const struct _rpcnettype {
   82         const char *name;
   83         const int type;
   84 } _rpctypelist[] = {
   85         { "netpath", _RPC_NETPATH },
   86         { "visible", _RPC_VISIBLE },
   87         { "circuit_v", _RPC_CIRCUIT_V },
   88         { "datagram_v", _RPC_DATAGRAM_V },
   89         { "circuit_n", _RPC_CIRCUIT_N },
   90         { "datagram_n", _RPC_DATAGRAM_N },
   91         { "tcp", _RPC_TCP },
   92         { "udp", _RPC_UDP },
   93         { 0, _RPC_NONE }
   94 };
   95 
   96 struct netid_af {
   97         const char      *netid;
   98         int             af;
   99         int             protocol;
  100 };
  101 
  102 static const struct netid_af na_cvt[] = {
  103         { "udp",  AF_INET,  IPPROTO_UDP },
  104         { "tcp",  AF_INET,  IPPROTO_TCP },
  105 #ifdef INET6
  106         { "udp6", AF_INET6, IPPROTO_UDP },
  107         { "tcp6", AF_INET6, IPPROTO_TCP },
  108 #endif
  109         { "local", AF_LOCAL, 0 }
  110 };
  111 
  112 struct rpc_createerr rpc_createerr;
  113 
  114 /*
  115  * Find the appropriate buffer size
  116  */
  117 u_int
  118 /*ARGSUSED*/
  119 __rpc_get_t_size(int af, int proto, int size)
  120 {
  121         int defsize;
  122 
  123         switch (proto) {
  124         case IPPROTO_TCP:
  125                 defsize = 64 * 1024;    /* XXX */
  126                 break;
  127         case IPPROTO_UDP:
  128                 defsize = UDPMSGSIZE;
  129                 break;
  130         default:
  131                 defsize = RPC_MAXDATASIZE;
  132                 break;
  133         }
  134         if (size == 0)
  135                 return defsize;
  136 
  137         /* Check whether the value is within the upper max limit */
  138         return (size > sb_max_adj ? (u_int)sb_max_adj : (u_int)size);
  139 }
  140 
  141 /*
  142  * Find the appropriate address buffer size
  143  */
  144 u_int
  145 __rpc_get_a_size(af)
  146         int af;
  147 {
  148         switch (af) {
  149         case AF_INET:
  150                 return sizeof (struct sockaddr_in);
  151 #ifdef INET6
  152         case AF_INET6:
  153                 return sizeof (struct sockaddr_in6);
  154 #endif
  155         case AF_LOCAL:
  156                 return sizeof (struct sockaddr_un);
  157         default:
  158                 break;
  159         }
  160         return ((u_int)RPC_MAXADDRSIZE);
  161 }
  162 
  163 #if 0
  164 
  165 /*
  166  * Used to ping the NULL procedure for clnt handle.
  167  * Returns NULL if fails, else a non-NULL pointer.
  168  */
  169 void *
  170 rpc_nullproc(clnt)
  171         CLIENT *clnt;
  172 {
  173         struct timeval TIMEOUT = {25, 0};
  174 
  175         if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
  176                 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
  177                 return (NULL);
  178         }
  179         return ((void *) clnt);
  180 }
  181 
  182 #endif
  183 
  184 int
  185 __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip)
  186 {
  187         int type, proto;
  188         struct sockaddr *sa;
  189         sa_family_t family;
  190         struct sockopt opt;
  191         int error;
  192 
  193         CURVNET_SET(so->so_vnet);
  194         error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  195         CURVNET_RESTORE();
  196         if (error)
  197                 return 0;
  198 
  199         sip->si_alen = sa->sa_len;
  200         family = sa->sa_family;
  201         free(sa, M_SONAME);
  202 
  203         opt.sopt_dir = SOPT_GET;
  204         opt.sopt_level = SOL_SOCKET;
  205         opt.sopt_name = SO_TYPE;
  206         opt.sopt_val = &type;
  207         opt.sopt_valsize = sizeof type;
  208         opt.sopt_td = NULL;
  209         error = sogetopt(so, &opt);
  210         if (error)
  211                 return 0;
  212 
  213         /* XXX */
  214         if (family != AF_LOCAL) {
  215                 if (type == SOCK_STREAM)
  216                         proto = IPPROTO_TCP;
  217                 else if (type == SOCK_DGRAM)
  218                         proto = IPPROTO_UDP;
  219                 else
  220                         return 0;
  221         } else
  222                 proto = 0;
  223 
  224         sip->si_af = family;
  225         sip->si_proto = proto;
  226         sip->si_socktype = type;
  227 
  228         return 1;
  229 }
  230 
  231 /*
  232  * Linear search, but the number of entries is small.
  233  */
  234 int
  235 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
  236 {
  237         int i;
  238 
  239         for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
  240                 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
  241                     strcmp(nconf->nc_netid, "unix") == 0 &&
  242                     strcmp(na_cvt[i].netid, "local") == 0)) {
  243                         sip->si_af = na_cvt[i].af;
  244                         sip->si_proto = na_cvt[i].protocol;
  245                         sip->si_socktype =
  246                             __rpc_seman2socktype((int)nconf->nc_semantics);
  247                         if (sip->si_socktype == -1)
  248                                 return 0;
  249                         sip->si_alen = __rpc_get_a_size(sip->si_af);
  250                         return 1;
  251                 }
  252 
  253         return 0;
  254 }
  255 
  256 struct socket *
  257 __rpc_nconf2socket(const struct netconfig *nconf)
  258 {
  259         struct __rpc_sockinfo si;
  260         struct socket *so;
  261         int error;
  262 
  263         if (!__rpc_nconf2sockinfo(nconf, &si))
  264                 return 0;
  265 
  266         so = NULL;
  267         error =  socreate(si.si_af, &so, si.si_socktype, si.si_proto,
  268             curthread->td_ucred, curthread);
  269 
  270         if (error)
  271                 return NULL;
  272         else
  273                 return so;
  274 }
  275 
  276 char *
  277 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
  278 {
  279         struct __rpc_sockinfo si;
  280 
  281         if (!__rpc_nconf2sockinfo(nconf, &si))
  282                 return NULL;
  283         return __rpc_taddr2uaddr_af(si.si_af, nbuf);
  284 }
  285 
  286 struct netbuf *
  287 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
  288 {
  289         struct __rpc_sockinfo si;
  290         
  291         if (!__rpc_nconf2sockinfo(nconf, &si))
  292                 return NULL;
  293         return __rpc_uaddr2taddr_af(si.si_af, uaddr);
  294 }
  295 
  296 char *
  297 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
  298 {
  299         char *ret;
  300         struct sbuf sb;
  301         struct sockaddr_in *sin;
  302         struct sockaddr_un *sun;
  303         char namebuf[INET_ADDRSTRLEN];
  304 #ifdef INET6
  305         struct sockaddr_in6 *sin6;
  306         char namebuf6[INET6_ADDRSTRLEN];
  307 #endif
  308         u_int16_t port;
  309 
  310         sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND);
  311 
  312         switch (af) {
  313         case AF_INET:
  314                 if (nbuf->len < sizeof(*sin))
  315                         return NULL;
  316                 sin = nbuf->buf;
  317                 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
  318                     == NULL)
  319                         return NULL;
  320                 port = ntohs(sin->sin_port);
  321                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
  322                         ((uint32_t)port) >> 8,
  323                         port & 0xff) < 0)
  324                         return NULL;
  325                 break;
  326 #ifdef INET6
  327         case AF_INET6:
  328                 if (nbuf->len < sizeof(*sin6))
  329                         return NULL;
  330                 sin6 = nbuf->buf;
  331                 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
  332                     == NULL)
  333                         return NULL;
  334                 port = ntohs(sin6->sin6_port);
  335                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
  336                         ((uint32_t)port) >> 8,
  337                         port & 0xff) < 0)
  338                         return NULL;
  339                 break;
  340 #endif
  341         case AF_LOCAL:
  342                 sun = nbuf->buf;
  343                 if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
  344                             offsetof(struct sockaddr_un, sun_path)),
  345                         sun->sun_path) < 0)
  346                         return (NULL);
  347                 break;
  348         default:
  349                 return NULL;
  350         }
  351 
  352         sbuf_finish(&sb);
  353         ret = strdup(sbuf_data(&sb), M_RPC);
  354         sbuf_delete(&sb);
  355 
  356         return ret;
  357 }
  358 
  359 struct netbuf *
  360 __rpc_uaddr2taddr_af(int af, const char *uaddr)
  361 {
  362         struct netbuf *ret = NULL;
  363         char *addrstr, *p;
  364         unsigned port, portlo, porthi;
  365         struct sockaddr_in *sin;
  366 #ifdef INET6
  367         struct sockaddr_in6 *sin6;
  368 #endif
  369         struct sockaddr_un *sun;
  370 
  371         port = 0;
  372         sin = NULL;
  373 
  374         if (uaddr == NULL)
  375                 return NULL;
  376 
  377         addrstr = strdup(uaddr, M_RPC);
  378         if (addrstr == NULL)
  379                 return NULL;
  380 
  381         /*
  382          * AF_LOCAL addresses are expected to be absolute
  383          * pathnames, anything else will be AF_INET or AF_INET6.
  384          */
  385         if (*addrstr != '/') {
  386                 p = strrchr(addrstr, '.');
  387                 if (p == NULL)
  388                         goto out;
  389                 portlo = (unsigned)strtol(p + 1, NULL, 10);
  390                 *p = '\0';
  391 
  392                 p = strrchr(addrstr, '.');
  393                 if (p == NULL)
  394                         goto out;
  395                 porthi = (unsigned)strtol(p + 1, NULL, 10);
  396                 *p = '\0';
  397                 port = (porthi << 8) | portlo;
  398         }
  399 
  400         ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
  401         
  402         switch (af) {
  403         case AF_INET:
  404                 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
  405                     M_WAITOK);
  406                 memset(sin, 0, sizeof *sin);
  407                 sin->sin_family = AF_INET;
  408                 sin->sin_port = htons(port);
  409                 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
  410                         free(sin, M_RPC);
  411                         free(ret, M_RPC);
  412                         ret = NULL;
  413                         goto out;
  414                 }
  415                 sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
  416                 ret->buf = sin;
  417                 break;
  418 #ifdef INET6
  419         case AF_INET6:
  420                 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
  421                     M_WAITOK);
  422                 memset(sin6, 0, sizeof *sin6);
  423                 sin6->sin6_family = AF_INET6;
  424                 sin6->sin6_port = htons(port);
  425                 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
  426                         free(sin6, M_RPC);
  427                         free(ret, M_RPC);
  428                         ret = NULL;
  429                         goto out;
  430                 }
  431                 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
  432                 ret->buf = sin6;
  433                 break;
  434 #endif
  435         case AF_LOCAL:
  436                 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
  437                     M_WAITOK);
  438                 memset(sun, 0, sizeof *sun);
  439                 sun->sun_family = AF_LOCAL;
  440                 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
  441                 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
  442                 ret->buf = sun;
  443                 break;
  444         default:
  445                 break;
  446         }
  447 out:
  448         free(addrstr, M_RPC);
  449         return ret;
  450 }
  451 
  452 int
  453 __rpc_seman2socktype(int semantics)
  454 {
  455         switch (semantics) {
  456         case NC_TPI_CLTS:
  457                 return SOCK_DGRAM;
  458         case NC_TPI_COTS_ORD:
  459                 return SOCK_STREAM;
  460         case NC_TPI_RAW:
  461                 return SOCK_RAW;
  462         default:
  463                 break;
  464         }
  465 
  466         return -1;
  467 }
  468 
  469 int
  470 __rpc_socktype2seman(int socktype)
  471 {
  472         switch (socktype) {
  473         case SOCK_DGRAM:
  474                 return NC_TPI_CLTS;
  475         case SOCK_STREAM:
  476                 return NC_TPI_COTS_ORD;
  477         case SOCK_RAW:
  478                 return NC_TPI_RAW;
  479         default:
  480                 break;
  481         }
  482 
  483         return -1;
  484 }
  485 
  486 /*
  487  * Returns the type of the network as defined in <rpc/nettype.h>
  488  * If nettype is NULL, it defaults to NETPATH.
  489  */
  490 static int
  491 getnettype(const char *nettype)
  492 {
  493         int i;
  494 
  495         if ((nettype == NULL) || (nettype[0] == 0)) {
  496                 return (_RPC_NETPATH);  /* Default */
  497         }
  498 
  499 #if 0
  500         nettype = strlocase(nettype);
  501 #endif
  502         for (i = 0; _rpctypelist[i].name; i++)
  503                 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
  504                         return (_rpctypelist[i].type);
  505                 }
  506         return (_rpctypelist[i].type);
  507 }
  508 
  509 /*
  510  * For the given nettype (tcp or udp only), return the first structure found.
  511  * This should be freed by calling freenetconfigent()
  512  */
  513 struct netconfig *
  514 __rpc_getconfip(const char *nettype)
  515 {
  516         char *netid;
  517         static char *netid_tcp = (char *) NULL;
  518         static char *netid_udp = (char *) NULL;
  519         struct netconfig *dummy;
  520 
  521         if (!netid_udp && !netid_tcp) {
  522                 struct netconfig *nconf;
  523                 void *confighandle;
  524 
  525                 if (!(confighandle = setnetconfig())) {
  526                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  527                         return (NULL);
  528                 }
  529                 while ((nconf = getnetconfig(confighandle)) != NULL) {
  530                         if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
  531                                 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
  532                                         netid_tcp = strdup(nconf->nc_netid,
  533                                             M_RPC);
  534                                 } else
  535                                 if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
  536                                         netid_udp = strdup(nconf->nc_netid,
  537                                             M_RPC);
  538                                 }
  539                         }
  540                 }
  541                 endnetconfig(confighandle);
  542         }
  543         if (strcmp(nettype, "udp") == 0)
  544                 netid = netid_udp;
  545         else if (strcmp(nettype, "tcp") == 0)
  546                 netid = netid_tcp;
  547         else {
  548                 return (NULL);
  549         }
  550         if ((netid == NULL) || (netid[0] == 0)) {
  551                 return (NULL);
  552         }
  553         dummy = getnetconfigent(netid);
  554         return (dummy);
  555 }
  556 
  557 /*
  558  * Returns the type of the nettype, which should then be used with
  559  * __rpc_getconf().
  560  *
  561  * For simplicity in the kernel, we don't support the NETPATH
  562  * environment variable. We behave as userland would then NETPATH is
  563  * unset, i.e. iterate over all visible entries in netconfig.
  564  */
  565 void *
  566 __rpc_setconf(nettype)
  567         const char *nettype;
  568 {
  569         struct handle *handle;
  570 
  571         handle = (struct handle *) malloc(sizeof (struct handle),
  572             M_RPC, M_WAITOK);
  573         switch (handle->nettype = getnettype(nettype)) {
  574         case _RPC_NETPATH:
  575         case _RPC_CIRCUIT_N:
  576         case _RPC_DATAGRAM_N:
  577                 if (!(handle->nhandle = setnetconfig()))
  578                         goto failed;
  579                 handle->nflag = TRUE;
  580                 break;
  581         case _RPC_VISIBLE:
  582         case _RPC_CIRCUIT_V:
  583         case _RPC_DATAGRAM_V:
  584         case _RPC_TCP:
  585         case _RPC_UDP:
  586                 if (!(handle->nhandle = setnetconfig())) {
  587                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  588                         goto failed;
  589                 }
  590                 handle->nflag = FALSE;
  591                 break;
  592         default:
  593                 goto failed;
  594         }
  595 
  596         return (handle);
  597 
  598 failed:
  599         free(handle, M_RPC);
  600         return (NULL);
  601 }
  602 
  603 /*
  604  * Returns the next netconfig struct for the given "net" type.
  605  * __rpc_setconf() should have been called previously.
  606  */
  607 struct netconfig *
  608 __rpc_getconf(void *vhandle)
  609 {
  610         struct handle *handle;
  611         struct netconfig *nconf;
  612 
  613         handle = (struct handle *)vhandle;
  614         if (handle == NULL) {
  615                 return (NULL);
  616         }
  617         for (;;) {
  618                 if (handle->nflag) {
  619                         nconf = getnetconfig(handle->nhandle);
  620                         if (nconf && !(nconf->nc_flag & NC_VISIBLE))
  621                                 continue;
  622                 } else {
  623                         nconf = getnetconfig(handle->nhandle);
  624                 }
  625                 if (nconf == NULL)
  626                         break;
  627                 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
  628                         (nconf->nc_semantics != NC_TPI_COTS) &&
  629                         (nconf->nc_semantics != NC_TPI_COTS_ORD))
  630                         continue;
  631                 switch (handle->nettype) {
  632                 case _RPC_VISIBLE:
  633                         if (!(nconf->nc_flag & NC_VISIBLE))
  634                                 continue;
  635                         /* FALLTHROUGH */
  636                 case _RPC_NETPATH:      /* Be happy */
  637                         break;
  638                 case _RPC_CIRCUIT_V:
  639                         if (!(nconf->nc_flag & NC_VISIBLE))
  640                                 continue;
  641                         /* FALLTHROUGH */
  642                 case _RPC_CIRCUIT_N:
  643                         if ((nconf->nc_semantics != NC_TPI_COTS) &&
  644                                 (nconf->nc_semantics != NC_TPI_COTS_ORD))
  645                                 continue;
  646                         break;
  647                 case _RPC_DATAGRAM_V:
  648                         if (!(nconf->nc_flag & NC_VISIBLE))
  649                                 continue;
  650                         /* FALLTHROUGH */
  651                 case _RPC_DATAGRAM_N:
  652                         if (nconf->nc_semantics != NC_TPI_CLTS)
  653                                 continue;
  654                         break;
  655                 case _RPC_TCP:
  656                         if (((nconf->nc_semantics != NC_TPI_COTS) &&
  657                                 (nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
  658                                 (strcmp(nconf->nc_protofmly, NC_INET)
  659 #ifdef INET6
  660                                  && strcmp(nconf->nc_protofmly, NC_INET6))
  661 #else
  662                                 )
  663 #endif
  664                                 ||
  665                                 strcmp(nconf->nc_proto, NC_TCP))
  666                                 continue;
  667                         break;
  668                 case _RPC_UDP:
  669                         if ((nconf->nc_semantics != NC_TPI_CLTS) ||
  670                                 (strcmp(nconf->nc_protofmly, NC_INET)
  671 #ifdef INET6
  672                                 && strcmp(nconf->nc_protofmly, NC_INET6))
  673 #else
  674                                 )
  675 #endif
  676                                 ||
  677                                 strcmp(nconf->nc_proto, NC_UDP))
  678                                 continue;
  679                         break;
  680                 }
  681                 break;
  682         }
  683         return (nconf);
  684 }
  685 
  686 void
  687 __rpc_endconf(vhandle)
  688         void * vhandle;
  689 {
  690         struct handle *handle;
  691 
  692         handle = (struct handle *) vhandle;
  693         if (handle == NULL) {
  694                 return;
  695         }
  696         endnetconfig(handle->nhandle);
  697         free(handle, M_RPC);
  698 }
  699 
  700 int
  701 __rpc_sockisbound(struct socket *so)
  702 {
  703         struct sockaddr *sa;
  704         int error, bound;
  705 
  706         CURVNET_SET(so->so_vnet);
  707         error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  708         CURVNET_RESTORE();
  709         if (error)
  710                 return (0);
  711 
  712         switch (sa->sa_family) {
  713                 case AF_INET:
  714                         bound = (((struct sockaddr_in *) sa)->sin_port != 0);
  715                         break;
  716 #ifdef INET6
  717                 case AF_INET6:
  718                         bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
  719                         break;
  720 #endif
  721                 case AF_LOCAL:
  722                         /* XXX check this */
  723                         bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
  724                         break;
  725                 default:
  726                         bound = FALSE;
  727                         break;
  728         }
  729 
  730         free(sa, M_SONAME);
  731 
  732         return bound;
  733 }
  734 
  735 /*
  736  * Implement XDR-style API for RPC call.
  737  */
  738 enum clnt_stat
  739 clnt_call_private(
  740         CLIENT          *cl,            /* client handle */
  741         struct rpc_callextra *ext,      /* call metadata */
  742         rpcproc_t       proc,           /* procedure number */
  743         xdrproc_t       xargs,          /* xdr routine for args */
  744         void            *argsp,         /* pointer to args */
  745         xdrproc_t       xresults,       /* xdr routine for results */
  746         void            *resultsp,      /* pointer to results */
  747         struct timeval  utimeout)       /* seconds to wait before giving up */
  748 {
  749         XDR xdrs;
  750         struct mbuf *mreq;
  751         struct mbuf *mrep;
  752         enum clnt_stat stat;
  753 
  754         mreq = m_getcl(M_WAITOK, MT_DATA, 0);
  755 
  756         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
  757         if (!xargs(&xdrs, argsp)) {
  758                 m_freem(mreq);
  759                 return (RPC_CANTENCODEARGS);
  760         }
  761         XDR_DESTROY(&xdrs);
  762 
  763         stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout);
  764         m_freem(mreq);
  765 
  766         if (stat == RPC_SUCCESS) {
  767                 xdrmbuf_create(&xdrs, mrep, XDR_DECODE);
  768                 if (!xresults(&xdrs, resultsp)) {
  769                         XDR_DESTROY(&xdrs);
  770                         return (RPC_CANTDECODERES);
  771                 }
  772                 XDR_DESTROY(&xdrs);
  773         }
  774 
  775         return (stat);
  776 }
  777 
  778 /*
  779  * Bind a socket to a privileged IP port
  780  */
  781 int
  782 bindresvport(struct socket *so, struct sockaddr *sa)
  783 {
  784         int old, error, af;
  785         bool_t freesa = FALSE;
  786         struct sockaddr_in *sin;
  787 #ifdef INET6
  788         struct sockaddr_in6 *sin6;
  789 #endif
  790         struct sockopt opt;
  791         int proto, portrange, portlow;
  792         u_int16_t *portp;
  793         socklen_t salen;
  794 
  795         if (sa == NULL) {
  796                 CURVNET_SET(so->so_vnet);
  797                 error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  798                 CURVNET_RESTORE();
  799                 if (error)
  800                         return (error);
  801                 freesa = TRUE;
  802                 af = sa->sa_family;
  803                 salen = sa->sa_len;
  804                 memset(sa, 0, sa->sa_len);
  805         } else {
  806                 af = sa->sa_family;
  807                 salen = sa->sa_len;
  808         }
  809 
  810         switch (af) {
  811         case AF_INET:
  812                 proto = IPPROTO_IP;
  813                 portrange = IP_PORTRANGE;
  814                 portlow = IP_PORTRANGE_LOW;
  815                 sin = (struct sockaddr_in *)sa;
  816                 portp = &sin->sin_port;
  817                 break;
  818 #ifdef INET6
  819         case AF_INET6:
  820                 proto = IPPROTO_IPV6;
  821                 portrange = IPV6_PORTRANGE;
  822                 portlow = IPV6_PORTRANGE_LOW;
  823                 sin6 = (struct sockaddr_in6 *)sa;
  824                 portp = &sin6->sin6_port;
  825                 break;
  826 #endif
  827         default:
  828                 return (EPFNOSUPPORT);
  829         }
  830 
  831         sa->sa_family = af;
  832         sa->sa_len = salen;
  833 
  834         if (*portp == 0) {
  835                 bzero(&opt, sizeof(opt));
  836                 opt.sopt_dir = SOPT_GET;
  837                 opt.sopt_level = proto;
  838                 opt.sopt_name = portrange;
  839                 opt.sopt_val = &old;
  840                 opt.sopt_valsize = sizeof(old);
  841                 error = sogetopt(so, &opt);
  842                 if (error) {
  843                         goto out;
  844                 }
  845 
  846                 opt.sopt_dir = SOPT_SET;
  847                 opt.sopt_val = &portlow;
  848                 error = sosetopt(so, &opt);
  849                 if (error)
  850                         goto out;
  851         }
  852 
  853         error = sobind(so, sa, curthread);
  854 
  855         if (*portp == 0) {
  856                 if (error) {
  857                         opt.sopt_dir = SOPT_SET;
  858                         opt.sopt_val = &old;
  859                         sosetopt(so, &opt);
  860                 }
  861         }
  862 out:
  863         if (freesa)
  864                 free(sa, M_SONAME);
  865 
  866         return (error);
  867 }
  868 
  869 /*
  870  * Kernel module glue
  871  */
  872 static int
  873 krpc_modevent(module_t mod, int type, void *data)
  874 {
  875 
  876         return (0);
  877 }
  878 static moduledata_t krpc_mod = {
  879         "krpc",
  880         krpc_modevent,
  881         NULL,
  882 };
  883 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY);
  884 
  885 /* So that loader and kldload(2) can find us, wherever we are.. */
  886 MODULE_VERSION(krpc, 1);

Cache object: 6594fe932edb989444bcf87021568726


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