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  * SPDX-License-Identifier: BSD-3-Clause
    5  *
    6  * Copyright (c) 2009, Sun Microsystems, Inc.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without 
   10  * modification, are permitted provided that the following conditions are met:
   11  * - Redistributions of source code must retain the above copyright notice, 
   12  *   this list of conditions and the following disclaimer.
   13  * - Redistributions in binary form must reproduce the above copyright notice, 
   14  *   this list of conditions and the following disclaimer in the documentation 
   15  *   and/or other materials provided with the distribution.
   16  * - Neither the name of Sun Microsystems, Inc. nor the names of its 
   17  *   contributors may be used to endorse or promote products derived 
   18  *   from this software without specific prior written permission.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
   24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 /*
   33  * Copyright (c) 1986-1991 by Sun Microsystems Inc. 
   34  */
   35 
   36 /* #pragma ident        "@(#)rpc_generic.c      1.17    94/04/24 SMI" */
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 /*
   41  * rpc_generic.c, Miscl routines for RPC.
   42  *
   43  */
   44 
   45 #include "opt_inet6.h"
   46 
   47 #include <sys/param.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mbuf.h>
   51 #include <sys/module.h>
   52 #include <sys/proc.h>
   53 #include <sys/protosw.h>
   54 #include <sys/sbuf.h>
   55 #include <sys/systm.h>
   56 #include <sys/socket.h>
   57 #include <sys/socketvar.h>
   58 #include <sys/syslog.h>
   59 
   60 #include <net/vnet.h>
   61 
   62 #include <rpc/rpc.h>
   63 #include <rpc/nettype.h>
   64 #include <rpc/rpcsec_gss.h>
   65 #include <rpc/rpcsec_tls.h>
   66 
   67 #include <rpc/rpc_com.h>
   68 #include <rpc/krpc.h>
   69 
   70 #include <vm/vm.h>
   71 #include <vm/pmap.h>
   72 #include <vm/vm_param.h>
   73 
   74 extern  u_long sb_max_adj;      /* not defined in socketvar.h */
   75 
   76 /* Provide an entry point hook for the rpcsec_gss module. */
   77 struct rpc_gss_entries  rpc_gss_entries;
   78 
   79 struct handle {
   80         NCONF_HANDLE *nhandle;
   81         int nflag;              /* Whether NETPATH or NETCONFIG */
   82         int nettype;
   83 };
   84 
   85 static const struct _rpcnettype {
   86         const char *name;
   87         const int type;
   88 } _rpctypelist[] = {
   89         { "netpath", _RPC_NETPATH },
   90         { "visible", _RPC_VISIBLE },
   91         { "circuit_v", _RPC_CIRCUIT_V },
   92         { "datagram_v", _RPC_DATAGRAM_V },
   93         { "circuit_n", _RPC_CIRCUIT_N },
   94         { "datagram_n", _RPC_DATAGRAM_N },
   95         { "tcp", _RPC_TCP },
   96         { "udp", _RPC_UDP },
   97         { 0, _RPC_NONE }
   98 };
   99 
  100 struct netid_af {
  101         const char      *netid;
  102         int             af;
  103         int             protocol;
  104 };
  105 
  106 static const struct netid_af na_cvt[] = {
  107         { "udp",  AF_INET,  IPPROTO_UDP },
  108         { "tcp",  AF_INET,  IPPROTO_TCP },
  109 #ifdef INET6
  110         { "udp6", AF_INET6, IPPROTO_UDP },
  111         { "tcp6", AF_INET6, IPPROTO_TCP },
  112 #endif
  113         { "local", AF_LOCAL, 0 }
  114 };
  115 
  116 struct rpc_createerr rpc_createerr;
  117 
  118 /*
  119  * Find the appropriate buffer size
  120  */
  121 u_int
  122 /*ARGSUSED*/
  123 __rpc_get_t_size(int af, int proto, int size)
  124 {
  125         int defsize;
  126 
  127         switch (proto) {
  128         case IPPROTO_TCP:
  129                 defsize = 64 * 1024;    /* XXX */
  130                 break;
  131         case IPPROTO_UDP:
  132                 defsize = UDPMSGSIZE;
  133                 break;
  134         default:
  135                 defsize = RPC_MAXDATASIZE;
  136                 break;
  137         }
  138         if (size == 0)
  139                 return defsize;
  140 
  141         /* Check whether the value is within the upper max limit */
  142         return (size > sb_max_adj ? (u_int)sb_max_adj : (u_int)size);
  143 }
  144 
  145 /*
  146  * Find the appropriate address buffer size
  147  */
  148 u_int
  149 __rpc_get_a_size(af)
  150         int af;
  151 {
  152         switch (af) {
  153         case AF_INET:
  154                 return sizeof (struct sockaddr_in);
  155 #ifdef INET6
  156         case AF_INET6:
  157                 return sizeof (struct sockaddr_in6);
  158 #endif
  159         case AF_LOCAL:
  160                 return sizeof (struct sockaddr_un);
  161         default:
  162                 break;
  163         }
  164         return ((u_int)RPC_MAXADDRSIZE);
  165 }
  166 
  167 #if 0
  168 
  169 /*
  170  * Used to ping the NULL procedure for clnt handle.
  171  * Returns NULL if fails, else a non-NULL pointer.
  172  */
  173 void *
  174 rpc_nullproc(clnt)
  175         CLIENT *clnt;
  176 {
  177         struct timeval TIMEOUT = {25, 0};
  178 
  179         if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
  180                 (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
  181                 return (NULL);
  182         }
  183         return ((void *) clnt);
  184 }
  185 
  186 #endif
  187 
  188 int
  189 __rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip)
  190 {
  191         int type, proto;
  192         struct sockaddr *sa;
  193         sa_family_t family;
  194         struct sockopt opt;
  195         int error;
  196 
  197         CURVNET_SET(so->so_vnet);
  198         error = so->so_proto->pr_sockaddr(so, &sa);
  199         CURVNET_RESTORE();
  200         if (error)
  201                 return 0;
  202 
  203         sip->si_alen = sa->sa_len;
  204         family = sa->sa_family;
  205         free(sa, M_SONAME);
  206 
  207         opt.sopt_dir = SOPT_GET;
  208         opt.sopt_level = SOL_SOCKET;
  209         opt.sopt_name = SO_TYPE;
  210         opt.sopt_val = &type;
  211         opt.sopt_valsize = sizeof type;
  212         opt.sopt_td = NULL;
  213         error = sogetopt(so, &opt);
  214         if (error)
  215                 return 0;
  216 
  217         /* XXX */
  218         if (family != AF_LOCAL) {
  219                 if (type == SOCK_STREAM)
  220                         proto = IPPROTO_TCP;
  221                 else if (type == SOCK_DGRAM)
  222                         proto = IPPROTO_UDP;
  223                 else
  224                         return 0;
  225         } else
  226                 proto = 0;
  227 
  228         sip->si_af = family;
  229         sip->si_proto = proto;
  230         sip->si_socktype = type;
  231 
  232         return 1;
  233 }
  234 
  235 /*
  236  * Linear search, but the number of entries is small.
  237  */
  238 int
  239 __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
  240 {
  241         int i;
  242 
  243         for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
  244                 if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
  245                     strcmp(nconf->nc_netid, "unix") == 0 &&
  246                     strcmp(na_cvt[i].netid, "local") == 0)) {
  247                         sip->si_af = na_cvt[i].af;
  248                         sip->si_proto = na_cvt[i].protocol;
  249                         sip->si_socktype =
  250                             __rpc_seman2socktype((int)nconf->nc_semantics);
  251                         if (sip->si_socktype == -1)
  252                                 return 0;
  253                         sip->si_alen = __rpc_get_a_size(sip->si_af);
  254                         return 1;
  255                 }
  256 
  257         return 0;
  258 }
  259 
  260 struct socket *
  261 __rpc_nconf2socket(const struct netconfig *nconf)
  262 {
  263         struct __rpc_sockinfo si;
  264         struct socket *so;
  265         int error;
  266 
  267         if (!__rpc_nconf2sockinfo(nconf, &si))
  268                 return 0;
  269 
  270         so = NULL;
  271         error =  socreate(si.si_af, &so, si.si_socktype, si.si_proto,
  272             curthread->td_ucred, curthread);
  273 
  274         if (error)
  275                 return NULL;
  276         else
  277                 return so;
  278 }
  279 
  280 char *
  281 taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
  282 {
  283         struct __rpc_sockinfo si;
  284 
  285         if (!__rpc_nconf2sockinfo(nconf, &si))
  286                 return NULL;
  287         return __rpc_taddr2uaddr_af(si.si_af, nbuf);
  288 }
  289 
  290 struct netbuf *
  291 uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
  292 {
  293         struct __rpc_sockinfo si;
  294         
  295         if (!__rpc_nconf2sockinfo(nconf, &si))
  296                 return NULL;
  297         return __rpc_uaddr2taddr_af(si.si_af, uaddr);
  298 }
  299 
  300 char *
  301 __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
  302 {
  303         char *ret;
  304         struct sbuf sb;
  305         struct sockaddr_in *sin;
  306         struct sockaddr_un *sun;
  307         char namebuf[INET_ADDRSTRLEN];
  308 #ifdef INET6
  309         struct sockaddr_in6 *sin6;
  310         char namebuf6[INET6_ADDRSTRLEN];
  311 #endif
  312         uint16_t port;
  313 
  314         sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND);
  315 
  316         switch (af) {
  317         case AF_INET:
  318                 if (nbuf->len < sizeof(*sin))
  319                         return NULL;
  320                 sin = nbuf->buf;
  321                 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
  322                     == NULL)
  323                         return NULL;
  324                 port = ntohs(sin->sin_port);
  325                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
  326                         ((uint32_t)port) >> 8,
  327                         port & 0xff) < 0)
  328                         return NULL;
  329                 break;
  330 #ifdef INET6
  331         case AF_INET6:
  332                 if (nbuf->len < sizeof(*sin6))
  333                         return NULL;
  334                 sin6 = nbuf->buf;
  335                 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
  336                     == NULL)
  337                         return NULL;
  338                 port = ntohs(sin6->sin6_port);
  339                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
  340                         ((uint32_t)port) >> 8,
  341                         port & 0xff) < 0)
  342                         return NULL;
  343                 break;
  344 #endif
  345         case AF_LOCAL:
  346                 sun = nbuf->buf;
  347                 if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
  348                             offsetof(struct sockaddr_un, sun_path)),
  349                         sun->sun_path) < 0)
  350                         return (NULL);
  351                 break;
  352         default:
  353                 return NULL;
  354         }
  355 
  356         sbuf_finish(&sb);
  357         ret = strdup(sbuf_data(&sb), M_RPC);
  358         sbuf_delete(&sb);
  359 
  360         return ret;
  361 }
  362 
  363 struct netbuf *
  364 __rpc_uaddr2taddr_af(int af, const char *uaddr)
  365 {
  366         struct netbuf *ret = NULL;
  367         char *addrstr, *p;
  368         unsigned port, portlo, porthi;
  369         struct sockaddr_in *sin;
  370 #ifdef INET6
  371         struct sockaddr_in6 *sin6;
  372 #endif
  373         struct sockaddr_un *sun;
  374 
  375         port = 0;
  376         sin = NULL;
  377 
  378         if (uaddr == NULL)
  379                 return NULL;
  380 
  381         addrstr = strdup(uaddr, M_RPC);
  382         if (addrstr == NULL)
  383                 return NULL;
  384 
  385         /*
  386          * AF_LOCAL addresses are expected to be absolute
  387          * pathnames, anything else will be AF_INET or AF_INET6.
  388          */
  389         if (*addrstr != '/') {
  390                 p = strrchr(addrstr, '.');
  391                 if (p == NULL)
  392                         goto out;
  393                 portlo = (unsigned)strtol(p + 1, NULL, 10);
  394                 *p = '\0';
  395 
  396                 p = strrchr(addrstr, '.');
  397                 if (p == NULL)
  398                         goto out;
  399                 porthi = (unsigned)strtol(p + 1, NULL, 10);
  400                 *p = '\0';
  401                 port = (porthi << 8) | portlo;
  402         }
  403 
  404         ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
  405         
  406         switch (af) {
  407         case AF_INET:
  408                 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
  409                     M_WAITOK);
  410                 memset(sin, 0, sizeof *sin);
  411                 sin->sin_family = AF_INET;
  412                 sin->sin_port = htons(port);
  413                 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
  414                         free(sin, M_RPC);
  415                         free(ret, M_RPC);
  416                         ret = NULL;
  417                         goto out;
  418                 }
  419                 sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
  420                 ret->buf = sin;
  421                 break;
  422 #ifdef INET6
  423         case AF_INET6:
  424                 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
  425                     M_WAITOK);
  426                 memset(sin6, 0, sizeof *sin6);
  427                 sin6->sin6_family = AF_INET6;
  428                 sin6->sin6_port = htons(port);
  429                 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
  430                         free(sin6, M_RPC);
  431                         free(ret, M_RPC);
  432                         ret = NULL;
  433                         goto out;
  434                 }
  435                 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
  436                 ret->buf = sin6;
  437                 break;
  438 #endif
  439         case AF_LOCAL:
  440                 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
  441                     M_WAITOK);
  442                 memset(sun, 0, sizeof *sun);
  443                 sun->sun_family = AF_LOCAL;
  444                 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
  445                 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
  446                 ret->buf = sun;
  447                 break;
  448         default:
  449                 break;
  450         }
  451 out:
  452         free(addrstr, M_RPC);
  453         return ret;
  454 }
  455 
  456 int
  457 __rpc_seman2socktype(int semantics)
  458 {
  459         switch (semantics) {
  460         case NC_TPI_CLTS:
  461                 return SOCK_DGRAM;
  462         case NC_TPI_COTS_ORD:
  463                 return SOCK_STREAM;
  464         case NC_TPI_RAW:
  465                 return SOCK_RAW;
  466         default:
  467                 break;
  468         }
  469 
  470         return -1;
  471 }
  472 
  473 int
  474 __rpc_socktype2seman(int socktype)
  475 {
  476         switch (socktype) {
  477         case SOCK_DGRAM:
  478                 return NC_TPI_CLTS;
  479         case SOCK_STREAM:
  480                 return NC_TPI_COTS_ORD;
  481         case SOCK_RAW:
  482                 return NC_TPI_RAW;
  483         default:
  484                 break;
  485         }
  486 
  487         return -1;
  488 }
  489 
  490 /*
  491  * Returns the type of the network as defined in <rpc/nettype.h>
  492  * If nettype is NULL, it defaults to NETPATH.
  493  */
  494 static int
  495 getnettype(const char *nettype)
  496 {
  497         int i;
  498 
  499         if ((nettype == NULL) || (nettype[0] == 0)) {
  500                 return (_RPC_NETPATH);  /* Default */
  501         }
  502 
  503 #if 0
  504         nettype = strlocase(nettype);
  505 #endif
  506         for (i = 0; _rpctypelist[i].name; i++)
  507                 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
  508                         return (_rpctypelist[i].type);
  509                 }
  510         return (_rpctypelist[i].type);
  511 }
  512 
  513 /*
  514  * For the given nettype (tcp or udp only), return the first structure found.
  515  * This should be freed by calling freenetconfigent()
  516  */
  517 struct netconfig *
  518 __rpc_getconfip(const char *nettype)
  519 {
  520         char *netid;
  521         static char *netid_tcp = (char *) NULL;
  522         static char *netid_udp = (char *) NULL;
  523         struct netconfig *dummy;
  524 
  525         if (!netid_udp && !netid_tcp) {
  526                 struct netconfig *nconf;
  527                 void *confighandle;
  528 
  529                 if (!(confighandle = setnetconfig())) {
  530                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  531                         return (NULL);
  532                 }
  533                 while ((nconf = getnetconfig(confighandle)) != NULL) {
  534                         if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
  535                                 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
  536                                         netid_tcp = strdup(nconf->nc_netid,
  537                                             M_RPC);
  538                                 } else
  539                                 if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
  540                                         netid_udp = strdup(nconf->nc_netid,
  541                                             M_RPC);
  542                                 }
  543                         }
  544                 }
  545                 endnetconfig(confighandle);
  546         }
  547         if (strcmp(nettype, "udp") == 0)
  548                 netid = netid_udp;
  549         else if (strcmp(nettype, "tcp") == 0)
  550                 netid = netid_tcp;
  551         else {
  552                 return (NULL);
  553         }
  554         if ((netid == NULL) || (netid[0] == 0)) {
  555                 return (NULL);
  556         }
  557         dummy = getnetconfigent(netid);
  558         return (dummy);
  559 }
  560 
  561 /*
  562  * Returns the type of the nettype, which should then be used with
  563  * __rpc_getconf().
  564  *
  565  * For simplicity in the kernel, we don't support the NETPATH
  566  * environment variable. We behave as userland would then NETPATH is
  567  * unset, i.e. iterate over all visible entries in netconfig.
  568  */
  569 void *
  570 __rpc_setconf(nettype)
  571         const char *nettype;
  572 {
  573         struct handle *handle;
  574 
  575         handle = (struct handle *) malloc(sizeof (struct handle),
  576             M_RPC, M_WAITOK);
  577         switch (handle->nettype = getnettype(nettype)) {
  578         case _RPC_NETPATH:
  579         case _RPC_CIRCUIT_N:
  580         case _RPC_DATAGRAM_N:
  581                 if (!(handle->nhandle = setnetconfig()))
  582                         goto failed;
  583                 handle->nflag = TRUE;
  584                 break;
  585         case _RPC_VISIBLE:
  586         case _RPC_CIRCUIT_V:
  587         case _RPC_DATAGRAM_V:
  588         case _RPC_TCP:
  589         case _RPC_UDP:
  590                 if (!(handle->nhandle = setnetconfig())) {
  591                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  592                         goto failed;
  593                 }
  594                 handle->nflag = FALSE;
  595                 break;
  596         default:
  597                 goto failed;
  598         }
  599 
  600         return (handle);
  601 
  602 failed:
  603         free(handle, M_RPC);
  604         return (NULL);
  605 }
  606 
  607 /*
  608  * Returns the next netconfig struct for the given "net" type.
  609  * __rpc_setconf() should have been called previously.
  610  */
  611 struct netconfig *
  612 __rpc_getconf(void *vhandle)
  613 {
  614         struct handle *handle;
  615         struct netconfig *nconf;
  616 
  617         handle = (struct handle *)vhandle;
  618         if (handle == NULL) {
  619                 return (NULL);
  620         }
  621         for (;;) {
  622                 if (handle->nflag) {
  623                         nconf = getnetconfig(handle->nhandle);
  624                         if (nconf && !(nconf->nc_flag & NC_VISIBLE))
  625                                 continue;
  626                 } else {
  627                         nconf = getnetconfig(handle->nhandle);
  628                 }
  629                 if (nconf == NULL)
  630                         break;
  631                 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
  632                         (nconf->nc_semantics != NC_TPI_COTS) &&
  633                         (nconf->nc_semantics != NC_TPI_COTS_ORD))
  634                         continue;
  635                 switch (handle->nettype) {
  636                 case _RPC_VISIBLE:
  637                         if (!(nconf->nc_flag & NC_VISIBLE))
  638                                 continue;
  639                         /* FALLTHROUGH */
  640                 case _RPC_NETPATH:      /* Be happy */
  641                         break;
  642                 case _RPC_CIRCUIT_V:
  643                         if (!(nconf->nc_flag & NC_VISIBLE))
  644                                 continue;
  645                         /* FALLTHROUGH */
  646                 case _RPC_CIRCUIT_N:
  647                         if ((nconf->nc_semantics != NC_TPI_COTS) &&
  648                                 (nconf->nc_semantics != NC_TPI_COTS_ORD))
  649                                 continue;
  650                         break;
  651                 case _RPC_DATAGRAM_V:
  652                         if (!(nconf->nc_flag & NC_VISIBLE))
  653                                 continue;
  654                         /* FALLTHROUGH */
  655                 case _RPC_DATAGRAM_N:
  656                         if (nconf->nc_semantics != NC_TPI_CLTS)
  657                                 continue;
  658                         break;
  659                 case _RPC_TCP:
  660                         if (((nconf->nc_semantics != NC_TPI_COTS) &&
  661                                 (nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
  662                                 (strcmp(nconf->nc_protofmly, NC_INET)
  663 #ifdef INET6
  664                                  && strcmp(nconf->nc_protofmly, NC_INET6))
  665 #else
  666                                 )
  667 #endif
  668                                 ||
  669                                 strcmp(nconf->nc_proto, NC_TCP))
  670                                 continue;
  671                         break;
  672                 case _RPC_UDP:
  673                         if ((nconf->nc_semantics != NC_TPI_CLTS) ||
  674                                 (strcmp(nconf->nc_protofmly, NC_INET)
  675 #ifdef INET6
  676                                 && strcmp(nconf->nc_protofmly, NC_INET6))
  677 #else
  678                                 )
  679 #endif
  680                                 ||
  681                                 strcmp(nconf->nc_proto, NC_UDP))
  682                                 continue;
  683                         break;
  684                 }
  685                 break;
  686         }
  687         return (nconf);
  688 }
  689 
  690 void
  691 __rpc_endconf(vhandle)
  692         void * vhandle;
  693 {
  694         struct handle *handle;
  695 
  696         handle = (struct handle *) vhandle;
  697         if (handle == NULL) {
  698                 return;
  699         }
  700         endnetconfig(handle->nhandle);
  701         free(handle, M_RPC);
  702 }
  703 
  704 int
  705 __rpc_sockisbound(struct socket *so)
  706 {
  707         struct sockaddr *sa;
  708         int error, bound;
  709 
  710         CURVNET_SET(so->so_vnet);
  711         error = so->so_proto->pr_sockaddr(so, &sa);
  712         CURVNET_RESTORE();
  713         if (error)
  714                 return (0);
  715 
  716         switch (sa->sa_family) {
  717                 case AF_INET:
  718                         bound = (((struct sockaddr_in *) sa)->sin_port != 0);
  719                         break;
  720 #ifdef INET6
  721                 case AF_INET6:
  722                         bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
  723                         break;
  724 #endif
  725                 case AF_LOCAL:
  726                         /* XXX check this */
  727                         bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
  728                         break;
  729                 default:
  730                         bound = FALSE;
  731                         break;
  732         }
  733 
  734         free(sa, M_SONAME);
  735 
  736         return bound;
  737 }
  738 
  739 /*
  740  * Implement XDR-style API for RPC call.
  741  */
  742 enum clnt_stat
  743 clnt_call_private(
  744         CLIENT          *cl,            /* client handle */
  745         struct rpc_callextra *ext,      /* call metadata */
  746         rpcproc_t       proc,           /* procedure number */
  747         xdrproc_t       xargs,          /* xdr routine for args */
  748         void            *argsp,         /* pointer to args */
  749         xdrproc_t       xresults,       /* xdr routine for results */
  750         void            *resultsp,      /* pointer to results */
  751         struct timeval  utimeout)       /* seconds to wait before giving up */
  752 {
  753         XDR xdrs;
  754         struct mbuf *mreq;
  755         struct mbuf *mrep;
  756         enum clnt_stat stat;
  757 
  758         mreq = m_getcl(M_WAITOK, MT_DATA, 0);
  759 
  760         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
  761         if (!xargs(&xdrs, argsp)) {
  762                 m_freem(mreq);
  763                 return (RPC_CANTENCODEARGS);
  764         }
  765         XDR_DESTROY(&xdrs);
  766 
  767         stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout);
  768         m_freem(mreq);
  769 
  770         if (stat == RPC_SUCCESS) {
  771                 xdrmbuf_create(&xdrs, mrep, XDR_DECODE);
  772                 if (!xresults(&xdrs, resultsp)) {
  773                         XDR_DESTROY(&xdrs);
  774                         return (RPC_CANTDECODERES);
  775                 }
  776                 XDR_DESTROY(&xdrs);
  777         }
  778 
  779         return (stat);
  780 }
  781 
  782 /*
  783  * Bind a socket to a privileged IP port
  784  */
  785 int
  786 bindresvport(struct socket *so, struct sockaddr *sa)
  787 {
  788         int old, error, af;
  789         bool_t freesa = FALSE;
  790         struct sockaddr_in *sin;
  791 #ifdef INET6
  792         struct sockaddr_in6 *sin6;
  793 #endif
  794         struct sockopt opt;
  795         int proto, portrange, portlow;
  796         uint16_t *portp;
  797         socklen_t salen;
  798 
  799         if (sa == NULL) {
  800                 CURVNET_SET(so->so_vnet);
  801                 error = so->so_proto->pr_sockaddr(so, &sa);
  802                 CURVNET_RESTORE();
  803                 if (error)
  804                         return (error);
  805                 freesa = TRUE;
  806                 af = sa->sa_family;
  807                 salen = sa->sa_len;
  808                 memset(sa, 0, sa->sa_len);
  809         } else {
  810                 af = sa->sa_family;
  811                 salen = sa->sa_len;
  812         }
  813 
  814         switch (af) {
  815         case AF_INET:
  816                 proto = IPPROTO_IP;
  817                 portrange = IP_PORTRANGE;
  818                 portlow = IP_PORTRANGE_LOW;
  819                 sin = (struct sockaddr_in *)sa;
  820                 portp = &sin->sin_port;
  821                 break;
  822 #ifdef INET6
  823         case AF_INET6:
  824                 proto = IPPROTO_IPV6;
  825                 portrange = IPV6_PORTRANGE;
  826                 portlow = IPV6_PORTRANGE_LOW;
  827                 sin6 = (struct sockaddr_in6 *)sa;
  828                 portp = &sin6->sin6_port;
  829                 break;
  830 #endif
  831         default:
  832                 return (EPFNOSUPPORT);
  833         }
  834 
  835         sa->sa_family = af;
  836         sa->sa_len = salen;
  837 
  838         if (*portp == 0) {
  839                 bzero(&opt, sizeof(opt));
  840                 opt.sopt_dir = SOPT_GET;
  841                 opt.sopt_level = proto;
  842                 opt.sopt_name = portrange;
  843                 opt.sopt_val = &old;
  844                 opt.sopt_valsize = sizeof(old);
  845                 error = sogetopt(so, &opt);
  846                 if (error) {
  847                         goto out;
  848                 }
  849 
  850                 opt.sopt_dir = SOPT_SET;
  851                 opt.sopt_val = &portlow;
  852                 error = sosetopt(so, &opt);
  853                 if (error)
  854                         goto out;
  855         }
  856 
  857         error = sobind(so, sa, curthread);
  858 
  859         if (*portp == 0) {
  860                 if (error) {
  861                         opt.sopt_dir = SOPT_SET;
  862                         opt.sopt_val = &old;
  863                         sosetopt(so, &opt);
  864                 }
  865         }
  866 out:
  867         if (freesa)
  868                 free(sa, M_SONAME);
  869 
  870         return (error);
  871 }
  872 
  873 /*
  874  * Make sure an mbuf list is made up entirely of ext_pgs mbufs.
  875  * This is needed for sosend() when KERN_TLS is being used.
  876  * (There might also be a performance improvement for certain
  877  *  network interfaces that handle ext_pgs mbufs efficiently.)
  878  * It expects at least one non-ext_pgs mbuf followed by zero
  879  * or more ext_pgs mbufs.  It does not handle the case where
  880  * non-ext_pgs mbuf(s) follow ext_pgs ones.
  881  * It also performs sanity checks on the resultant list.
  882  * The "mp" argument list is consumed.
  883  * The "maxextsiz" argument is the upper bound on the data
  884  * size for each mbuf (usually 16K for KERN_TLS).
  885  */
  886 struct mbuf *
  887 _rpc_copym_into_ext_pgs(struct mbuf *mp, int maxextsiz)
  888 {
  889         struct mbuf *m, *m2, *m3, *mhead;
  890         int tlen;
  891 
  892         KASSERT((mp->m_flags & (M_EXT | M_EXTPG)) !=
  893             (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
  894             " first mbuf is an ext_pgs"));
  895         /*
  896          * Find the last non-ext_pgs mbuf and the total
  897          * length of the non-ext_pgs mbuf(s).
  898          * The first mbuf must always be a non-ext_pgs
  899          * mbuf.
  900          */
  901         tlen = mp->m_len;
  902         m2 = mp;
  903         for (m = mp->m_next; m != NULL; m = m->m_next) {
  904                 if ((m->m_flags & M_EXTPG) != 0)
  905                         break;
  906                 tlen += m->m_len;
  907                 m2 = m;
  908         }
  909 
  910         /*
  911          * Copy the non-ext_pgs mbuf(s) into an ext_pgs
  912          * mbuf list.
  913          */
  914         m2->m_next = NULL;
  915         mhead = mb_mapped_to_unmapped(mp, tlen, maxextsiz,
  916             M_WAITOK, &m2);
  917 
  918         /*
  919          * Link the ext_pgs list onto the newly copied
  920          * list and free up the non-ext_pgs mbuf(s).
  921          */
  922         m2->m_next = m;
  923         m_freem(mp);
  924 
  925         /*
  926          * Sanity check the resultant mbuf list.  Check for and
  927          * remove any 0 length mbufs in the list, since the
  928          * KERN_TLS code does not expect any 0 length mbuf(s)
  929          * in the list.
  930          */
  931         m3 = NULL;
  932         m2 = mhead;
  933         tlen = 0;
  934         while (m2 != NULL) {
  935                 KASSERT(m2->m_len >= 0, ("_rpc_copym_into_ext_pgs:"
  936                     " negative m_len"));
  937                 KASSERT((m2->m_flags & (M_EXT | M_EXTPG)) ==
  938                     (M_EXT | M_EXTPG), ("_rpc_copym_into_ext_pgs:"
  939                             " non-nomap mbuf in list"));
  940                 if (m2->m_len == 0) {
  941                         if (m3 != NULL)
  942                                 m3->m_next = m2->m_next;
  943                         else
  944                                 m = m2->m_next;
  945                         m2->m_next = NULL;
  946                         m_free(m2);
  947                         if (m3 != NULL)
  948                                 m2 = m3->m_next;
  949                         else
  950                                 m2 = m;
  951                 } else {
  952                         MBUF_EXT_PGS_ASSERT_SANITY(m2);
  953                         m3 = m2;
  954                         tlen += m2->m_len;
  955                         m2 = m2->m_next;
  956                 }
  957         }
  958         return (mhead);
  959 }
  960 
  961 /*
  962  * Kernel module glue
  963  */
  964 static int
  965 krpc_modevent(module_t mod, int type, void *data)
  966 {
  967         int error = 0;
  968 
  969         switch (type) {
  970         case MOD_LOAD:
  971                 error = rpctls_init();
  972                 break;
  973         case MOD_UNLOAD:
  974                 /*
  975                  * Cannot be unloaded, since the rpctlssd or rpctlscd daemons
  976                  * might be performing a rpctls syscall.
  977                  */
  978                 /* FALLTHROUGH */
  979         default:
  980                 error = EOPNOTSUPP;
  981         }
  982         return (error);
  983 }
  984 static moduledata_t krpc_mod = {
  985         "krpc",
  986         krpc_modevent,
  987         NULL,
  988 };
  989 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY);
  990 
  991 /* So that loader and kldload(2) can find us, wherever we are.. */
  992 MODULE_VERSION(krpc, 1);
  993 MODULE_DEPEND(krpc, xdr, 1, 1, 1);

Cache object: b0062c4104dafc15cb03b8b4d26648f7


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