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.1/sys/rpc/rpc_generic.c 261046 2014-01-22 23:45:27Z mav $");
   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                 sin = nbuf->buf;
  315                 if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
  316                     == NULL)
  317                         return NULL;
  318                 port = ntohs(sin->sin_port);
  319                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf,
  320                         ((uint32_t)port) >> 8,
  321                         port & 0xff) < 0)
  322                         return NULL;
  323                 break;
  324 #ifdef INET6
  325         case AF_INET6:
  326                 sin6 = nbuf->buf;
  327                 if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
  328                     == NULL)
  329                         return NULL;
  330                 port = ntohs(sin6->sin6_port);
  331                 if (sbuf_printf(&sb, "%s.%u.%u", namebuf6,
  332                         ((uint32_t)port) >> 8,
  333                         port & 0xff) < 0)
  334                         return NULL;
  335                 break;
  336 #endif
  337         case AF_LOCAL:
  338                 sun = nbuf->buf;
  339                 if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len -
  340                             offsetof(struct sockaddr_un, sun_path)),
  341                         sun->sun_path) < 0)
  342                         return (NULL);
  343                 break;
  344         default:
  345                 return NULL;
  346         }
  347 
  348         sbuf_finish(&sb);
  349         ret = strdup(sbuf_data(&sb), M_RPC);
  350         sbuf_delete(&sb);
  351 
  352         return ret;
  353 }
  354 
  355 struct netbuf *
  356 __rpc_uaddr2taddr_af(int af, const char *uaddr)
  357 {
  358         struct netbuf *ret = NULL;
  359         char *addrstr, *p;
  360         unsigned port, portlo, porthi;
  361         struct sockaddr_in *sin;
  362 #ifdef INET6
  363         struct sockaddr_in6 *sin6;
  364 #endif
  365         struct sockaddr_un *sun;
  366 
  367         port = 0;
  368         sin = NULL;
  369         addrstr = strdup(uaddr, M_RPC);
  370         if (addrstr == NULL)
  371                 return NULL;
  372 
  373         /*
  374          * AF_LOCAL addresses are expected to be absolute
  375          * pathnames, anything else will be AF_INET or AF_INET6.
  376          */
  377         if (*addrstr != '/') {
  378                 p = strrchr(addrstr, '.');
  379                 if (p == NULL)
  380                         goto out;
  381                 portlo = (unsigned)strtol(p + 1, NULL, 10);
  382                 *p = '\0';
  383 
  384                 p = strrchr(addrstr, '.');
  385                 if (p == NULL)
  386                         goto out;
  387                 porthi = (unsigned)strtol(p + 1, NULL, 10);
  388                 *p = '\0';
  389                 port = (porthi << 8) | portlo;
  390         }
  391 
  392         ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
  393         if (ret == NULL)
  394                 goto out;
  395         
  396         switch (af) {
  397         case AF_INET:
  398                 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
  399                     M_WAITOK);
  400                 if (sin == NULL)
  401                         goto out;
  402                 memset(sin, 0, sizeof *sin);
  403                 sin->sin_family = AF_INET;
  404                 sin->sin_port = htons(port);
  405                 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
  406                         free(sin, M_RPC);
  407                         free(ret, M_RPC);
  408                         ret = NULL;
  409                         goto out;
  410                 }
  411                 sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
  412                 ret->buf = sin;
  413                 break;
  414 #ifdef INET6
  415         case AF_INET6:
  416                 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
  417                     M_WAITOK);
  418                 if (sin6 == NULL)
  419                         goto out;
  420                 memset(sin6, 0, sizeof *sin6);
  421                 sin6->sin6_family = AF_INET6;
  422                 sin6->sin6_port = htons(port);
  423                 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
  424                         free(sin6, M_RPC);
  425                         free(ret, M_RPC);
  426                         ret = NULL;
  427                         goto out;
  428                 }
  429                 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
  430                 ret->buf = sin6;
  431                 break;
  432 #endif
  433         case AF_LOCAL:
  434                 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
  435                     M_WAITOK);
  436                 if (sun == NULL)
  437                         goto out;
  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         error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  707         if (error)
  708                 return (0);
  709 
  710         switch (sa->sa_family) {
  711                 case AF_INET:
  712                         bound = (((struct sockaddr_in *) sa)->sin_port != 0);
  713                         break;
  714 #ifdef INET6
  715                 case AF_INET6:
  716                         bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
  717                         break;
  718 #endif
  719                 case AF_LOCAL:
  720                         /* XXX check this */
  721                         bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
  722                         break;
  723                 default:
  724                         bound = FALSE;
  725                         break;
  726         }
  727 
  728         free(sa, M_SONAME);
  729 
  730         return bound;
  731 }
  732 
  733 /*
  734  * Implement XDR-style API for RPC call.
  735  */
  736 enum clnt_stat
  737 clnt_call_private(
  738         CLIENT          *cl,            /* client handle */
  739         struct rpc_callextra *ext,      /* call metadata */
  740         rpcproc_t       proc,           /* procedure number */
  741         xdrproc_t       xargs,          /* xdr routine for args */
  742         void            *argsp,         /* pointer to args */
  743         xdrproc_t       xresults,       /* xdr routine for results */
  744         void            *resultsp,      /* pointer to results */
  745         struct timeval  utimeout)       /* seconds to wait before giving up */
  746 {
  747         XDR xdrs;
  748         struct mbuf *mreq;
  749         struct mbuf *mrep;
  750         enum clnt_stat stat;
  751 
  752         mreq = m_getcl(M_WAITOK, MT_DATA, 0);
  753 
  754         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
  755         if (!xargs(&xdrs, argsp)) {
  756                 m_freem(mreq);
  757                 return (RPC_CANTENCODEARGS);
  758         }
  759         XDR_DESTROY(&xdrs);
  760 
  761         stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout);
  762         m_freem(mreq);
  763 
  764         if (stat == RPC_SUCCESS) {
  765                 xdrmbuf_create(&xdrs, mrep, XDR_DECODE);
  766                 if (!xresults(&xdrs, resultsp)) {
  767                         XDR_DESTROY(&xdrs);
  768                         return (RPC_CANTDECODERES);
  769                 }
  770                 XDR_DESTROY(&xdrs);
  771         }
  772 
  773         return (stat);
  774 }
  775 
  776 /*
  777  * Bind a socket to a privileged IP port
  778  */
  779 int
  780 bindresvport(struct socket *so, struct sockaddr *sa)
  781 {
  782         int old, error, af;
  783         bool_t freesa = FALSE;
  784         struct sockaddr_in *sin;
  785 #ifdef INET6
  786         struct sockaddr_in6 *sin6;
  787 #endif
  788         struct sockopt opt;
  789         int proto, portrange, portlow;
  790         u_int16_t *portp;
  791         socklen_t salen;
  792 
  793         if (sa == NULL) {
  794                 error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  795                 if (error)
  796                         return (error);
  797                 freesa = TRUE;
  798                 af = sa->sa_family;
  799                 salen = sa->sa_len;
  800                 memset(sa, 0, sa->sa_len);
  801         } else {
  802                 af = sa->sa_family;
  803                 salen = sa->sa_len;
  804         }
  805 
  806         switch (af) {
  807         case AF_INET:
  808                 proto = IPPROTO_IP;
  809                 portrange = IP_PORTRANGE;
  810                 portlow = IP_PORTRANGE_LOW;
  811                 sin = (struct sockaddr_in *)sa;
  812                 portp = &sin->sin_port;
  813                 break;
  814 #ifdef INET6
  815         case AF_INET6:
  816                 proto = IPPROTO_IPV6;
  817                 portrange = IPV6_PORTRANGE;
  818                 portlow = IPV6_PORTRANGE_LOW;
  819                 sin6 = (struct sockaddr_in6 *)sa;
  820                 portp = &sin6->sin6_port;
  821                 break;
  822 #endif
  823         default:
  824                 return (EPFNOSUPPORT);
  825         }
  826 
  827         sa->sa_family = af;
  828         sa->sa_len = salen;
  829 
  830         if (*portp == 0) {
  831                 bzero(&opt, sizeof(opt));
  832                 opt.sopt_dir = SOPT_GET;
  833                 opt.sopt_level = proto;
  834                 opt.sopt_name = portrange;
  835                 opt.sopt_val = &old;
  836                 opt.sopt_valsize = sizeof(old);
  837                 error = sogetopt(so, &opt);
  838                 if (error) {
  839                         goto out;
  840                 }
  841 
  842                 opt.sopt_dir = SOPT_SET;
  843                 opt.sopt_val = &portlow;
  844                 error = sosetopt(so, &opt);
  845                 if (error)
  846                         goto out;
  847         }
  848 
  849         error = sobind(so, sa, curthread);
  850 
  851         if (*portp == 0) {
  852                 if (error) {
  853                         opt.sopt_dir = SOPT_SET;
  854                         opt.sopt_val = &old;
  855                         sosetopt(so, &opt);
  856                 }
  857         }
  858 out:
  859         if (freesa)
  860                 free(sa, M_SONAME);
  861 
  862         return (error);
  863 }
  864 
  865 /*
  866  * Kernel module glue
  867  */
  868 static int
  869 krpc_modevent(module_t mod, int type, void *data)
  870 {
  871 
  872         return (0);
  873 }
  874 static moduledata_t krpc_mod = {
  875         "krpc",
  876         krpc_modevent,
  877         NULL,
  878 };
  879 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY);
  880 
  881 /* So that loader and kldload(2) can find us, wherever we are.. */
  882 MODULE_VERSION(krpc, 1);

Cache object: 7be7cdec39812daccab1c2e121aab696


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