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/11.0/sys/rpc/rpc_generic.c 297391 2016-03-29 13:56:59Z trasz $");
   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         
  394         switch (af) {
  395         case AF_INET:
  396                 sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
  397                     M_WAITOK);
  398                 memset(sin, 0, sizeof *sin);
  399                 sin->sin_family = AF_INET;
  400                 sin->sin_port = htons(port);
  401                 if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
  402                         free(sin, M_RPC);
  403                         free(ret, M_RPC);
  404                         ret = NULL;
  405                         goto out;
  406                 }
  407                 sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
  408                 ret->buf = sin;
  409                 break;
  410 #ifdef INET6
  411         case AF_INET6:
  412                 sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
  413                     M_WAITOK);
  414                 memset(sin6, 0, sizeof *sin6);
  415                 sin6->sin6_family = AF_INET6;
  416                 sin6->sin6_port = htons(port);
  417                 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
  418                         free(sin6, M_RPC);
  419                         free(ret, M_RPC);
  420                         ret = NULL;
  421                         goto out;
  422                 }
  423                 sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
  424                 ret->buf = sin6;
  425                 break;
  426 #endif
  427         case AF_LOCAL:
  428                 sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
  429                     M_WAITOK);
  430                 memset(sun, 0, sizeof *sun);
  431                 sun->sun_family = AF_LOCAL;
  432                 strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
  433                 ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
  434                 ret->buf = sun;
  435                 break;
  436         default:
  437                 break;
  438         }
  439 out:
  440         free(addrstr, M_RPC);
  441         return ret;
  442 }
  443 
  444 int
  445 __rpc_seman2socktype(int semantics)
  446 {
  447         switch (semantics) {
  448         case NC_TPI_CLTS:
  449                 return SOCK_DGRAM;
  450         case NC_TPI_COTS_ORD:
  451                 return SOCK_STREAM;
  452         case NC_TPI_RAW:
  453                 return SOCK_RAW;
  454         default:
  455                 break;
  456         }
  457 
  458         return -1;
  459 }
  460 
  461 int
  462 __rpc_socktype2seman(int socktype)
  463 {
  464         switch (socktype) {
  465         case SOCK_DGRAM:
  466                 return NC_TPI_CLTS;
  467         case SOCK_STREAM:
  468                 return NC_TPI_COTS_ORD;
  469         case SOCK_RAW:
  470                 return NC_TPI_RAW;
  471         default:
  472                 break;
  473         }
  474 
  475         return -1;
  476 }
  477 
  478 /*
  479  * Returns the type of the network as defined in <rpc/nettype.h>
  480  * If nettype is NULL, it defaults to NETPATH.
  481  */
  482 static int
  483 getnettype(const char *nettype)
  484 {
  485         int i;
  486 
  487         if ((nettype == NULL) || (nettype[0] == 0)) {
  488                 return (_RPC_NETPATH);  /* Default */
  489         }
  490 
  491 #if 0
  492         nettype = strlocase(nettype);
  493 #endif
  494         for (i = 0; _rpctypelist[i].name; i++)
  495                 if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
  496                         return (_rpctypelist[i].type);
  497                 }
  498         return (_rpctypelist[i].type);
  499 }
  500 
  501 /*
  502  * For the given nettype (tcp or udp only), return the first structure found.
  503  * This should be freed by calling freenetconfigent()
  504  */
  505 struct netconfig *
  506 __rpc_getconfip(const char *nettype)
  507 {
  508         char *netid;
  509         static char *netid_tcp = (char *) NULL;
  510         static char *netid_udp = (char *) NULL;
  511         struct netconfig *dummy;
  512 
  513         if (!netid_udp && !netid_tcp) {
  514                 struct netconfig *nconf;
  515                 void *confighandle;
  516 
  517                 if (!(confighandle = setnetconfig())) {
  518                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  519                         return (NULL);
  520                 }
  521                 while ((nconf = getnetconfig(confighandle)) != NULL) {
  522                         if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
  523                                 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
  524                                         netid_tcp = strdup(nconf->nc_netid,
  525                                             M_RPC);
  526                                 } else
  527                                 if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
  528                                         netid_udp = strdup(nconf->nc_netid,
  529                                             M_RPC);
  530                                 }
  531                         }
  532                 }
  533                 endnetconfig(confighandle);
  534         }
  535         if (strcmp(nettype, "udp") == 0)
  536                 netid = netid_udp;
  537         else if (strcmp(nettype, "tcp") == 0)
  538                 netid = netid_tcp;
  539         else {
  540                 return (NULL);
  541         }
  542         if ((netid == NULL) || (netid[0] == 0)) {
  543                 return (NULL);
  544         }
  545         dummy = getnetconfigent(netid);
  546         return (dummy);
  547 }
  548 
  549 /*
  550  * Returns the type of the nettype, which should then be used with
  551  * __rpc_getconf().
  552  *
  553  * For simplicity in the kernel, we don't support the NETPATH
  554  * environment variable. We behave as userland would then NETPATH is
  555  * unset, i.e. iterate over all visible entries in netconfig.
  556  */
  557 void *
  558 __rpc_setconf(nettype)
  559         const char *nettype;
  560 {
  561         struct handle *handle;
  562 
  563         handle = (struct handle *) malloc(sizeof (struct handle),
  564             M_RPC, M_WAITOK);
  565         switch (handle->nettype = getnettype(nettype)) {
  566         case _RPC_NETPATH:
  567         case _RPC_CIRCUIT_N:
  568         case _RPC_DATAGRAM_N:
  569                 if (!(handle->nhandle = setnetconfig()))
  570                         goto failed;
  571                 handle->nflag = TRUE;
  572                 break;
  573         case _RPC_VISIBLE:
  574         case _RPC_CIRCUIT_V:
  575         case _RPC_DATAGRAM_V:
  576         case _RPC_TCP:
  577         case _RPC_UDP:
  578                 if (!(handle->nhandle = setnetconfig())) {
  579                         log(LOG_ERR, "rpc: failed to open " NETCONFIG);
  580                         goto failed;
  581                 }
  582                 handle->nflag = FALSE;
  583                 break;
  584         default:
  585                 goto failed;
  586         }
  587 
  588         return (handle);
  589 
  590 failed:
  591         free(handle, M_RPC);
  592         return (NULL);
  593 }
  594 
  595 /*
  596  * Returns the next netconfig struct for the given "net" type.
  597  * __rpc_setconf() should have been called previously.
  598  */
  599 struct netconfig *
  600 __rpc_getconf(void *vhandle)
  601 {
  602         struct handle *handle;
  603         struct netconfig *nconf;
  604 
  605         handle = (struct handle *)vhandle;
  606         if (handle == NULL) {
  607                 return (NULL);
  608         }
  609         for (;;) {
  610                 if (handle->nflag) {
  611                         nconf = getnetconfig(handle->nhandle);
  612                         if (nconf && !(nconf->nc_flag & NC_VISIBLE))
  613                                 continue;
  614                 } else {
  615                         nconf = getnetconfig(handle->nhandle);
  616                 }
  617                 if (nconf == NULL)
  618                         break;
  619                 if ((nconf->nc_semantics != NC_TPI_CLTS) &&
  620                         (nconf->nc_semantics != NC_TPI_COTS) &&
  621                         (nconf->nc_semantics != NC_TPI_COTS_ORD))
  622                         continue;
  623                 switch (handle->nettype) {
  624                 case _RPC_VISIBLE:
  625                         if (!(nconf->nc_flag & NC_VISIBLE))
  626                                 continue;
  627                         /* FALLTHROUGH */
  628                 case _RPC_NETPATH:      /* Be happy */
  629                         break;
  630                 case _RPC_CIRCUIT_V:
  631                         if (!(nconf->nc_flag & NC_VISIBLE))
  632                                 continue;
  633                         /* FALLTHROUGH */
  634                 case _RPC_CIRCUIT_N:
  635                         if ((nconf->nc_semantics != NC_TPI_COTS) &&
  636                                 (nconf->nc_semantics != NC_TPI_COTS_ORD))
  637                                 continue;
  638                         break;
  639                 case _RPC_DATAGRAM_V:
  640                         if (!(nconf->nc_flag & NC_VISIBLE))
  641                                 continue;
  642                         /* FALLTHROUGH */
  643                 case _RPC_DATAGRAM_N:
  644                         if (nconf->nc_semantics != NC_TPI_CLTS)
  645                                 continue;
  646                         break;
  647                 case _RPC_TCP:
  648                         if (((nconf->nc_semantics != NC_TPI_COTS) &&
  649                                 (nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
  650                                 (strcmp(nconf->nc_protofmly, NC_INET)
  651 #ifdef INET6
  652                                  && strcmp(nconf->nc_protofmly, NC_INET6))
  653 #else
  654                                 )
  655 #endif
  656                                 ||
  657                                 strcmp(nconf->nc_proto, NC_TCP))
  658                                 continue;
  659                         break;
  660                 case _RPC_UDP:
  661                         if ((nconf->nc_semantics != NC_TPI_CLTS) ||
  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_UDP))
  670                                 continue;
  671                         break;
  672                 }
  673                 break;
  674         }
  675         return (nconf);
  676 }
  677 
  678 void
  679 __rpc_endconf(vhandle)
  680         void * vhandle;
  681 {
  682         struct handle *handle;
  683 
  684         handle = (struct handle *) vhandle;
  685         if (handle == NULL) {
  686                 return;
  687         }
  688         endnetconfig(handle->nhandle);
  689         free(handle, M_RPC);
  690 }
  691 
  692 int
  693 __rpc_sockisbound(struct socket *so)
  694 {
  695         struct sockaddr *sa;
  696         int error, bound;
  697 
  698         CURVNET_SET(so->so_vnet);
  699         error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  700         CURVNET_RESTORE();
  701         if (error)
  702                 return (0);
  703 
  704         switch (sa->sa_family) {
  705                 case AF_INET:
  706                         bound = (((struct sockaddr_in *) sa)->sin_port != 0);
  707                         break;
  708 #ifdef INET6
  709                 case AF_INET6:
  710                         bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0);
  711                         break;
  712 #endif
  713                 case AF_LOCAL:
  714                         /* XXX check this */
  715                         bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0');
  716                         break;
  717                 default:
  718                         bound = FALSE;
  719                         break;
  720         }
  721 
  722         free(sa, M_SONAME);
  723 
  724         return bound;
  725 }
  726 
  727 /*
  728  * Implement XDR-style API for RPC call.
  729  */
  730 enum clnt_stat
  731 clnt_call_private(
  732         CLIENT          *cl,            /* client handle */
  733         struct rpc_callextra *ext,      /* call metadata */
  734         rpcproc_t       proc,           /* procedure number */
  735         xdrproc_t       xargs,          /* xdr routine for args */
  736         void            *argsp,         /* pointer to args */
  737         xdrproc_t       xresults,       /* xdr routine for results */
  738         void            *resultsp,      /* pointer to results */
  739         struct timeval  utimeout)       /* seconds to wait before giving up */
  740 {
  741         XDR xdrs;
  742         struct mbuf *mreq;
  743         struct mbuf *mrep;
  744         enum clnt_stat stat;
  745 
  746         mreq = m_getcl(M_WAITOK, MT_DATA, 0);
  747 
  748         xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
  749         if (!xargs(&xdrs, argsp)) {
  750                 m_freem(mreq);
  751                 return (RPC_CANTENCODEARGS);
  752         }
  753         XDR_DESTROY(&xdrs);
  754 
  755         stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout);
  756         m_freem(mreq);
  757 
  758         if (stat == RPC_SUCCESS) {
  759                 xdrmbuf_create(&xdrs, mrep, XDR_DECODE);
  760                 if (!xresults(&xdrs, resultsp)) {
  761                         XDR_DESTROY(&xdrs);
  762                         return (RPC_CANTDECODERES);
  763                 }
  764                 XDR_DESTROY(&xdrs);
  765         }
  766 
  767         return (stat);
  768 }
  769 
  770 /*
  771  * Bind a socket to a privileged IP port
  772  */
  773 int
  774 bindresvport(struct socket *so, struct sockaddr *sa)
  775 {
  776         int old, error, af;
  777         bool_t freesa = FALSE;
  778         struct sockaddr_in *sin;
  779 #ifdef INET6
  780         struct sockaddr_in6 *sin6;
  781 #endif
  782         struct sockopt opt;
  783         int proto, portrange, portlow;
  784         u_int16_t *portp;
  785         socklen_t salen;
  786 
  787         if (sa == NULL) {
  788                 CURVNET_SET(so->so_vnet);
  789                 error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
  790                 CURVNET_RESTORE();
  791                 if (error)
  792                         return (error);
  793                 freesa = TRUE;
  794                 af = sa->sa_family;
  795                 salen = sa->sa_len;
  796                 memset(sa, 0, sa->sa_len);
  797         } else {
  798                 af = sa->sa_family;
  799                 salen = sa->sa_len;
  800         }
  801 
  802         switch (af) {
  803         case AF_INET:
  804                 proto = IPPROTO_IP;
  805                 portrange = IP_PORTRANGE;
  806                 portlow = IP_PORTRANGE_LOW;
  807                 sin = (struct sockaddr_in *)sa;
  808                 portp = &sin->sin_port;
  809                 break;
  810 #ifdef INET6
  811         case AF_INET6:
  812                 proto = IPPROTO_IPV6;
  813                 portrange = IPV6_PORTRANGE;
  814                 portlow = IPV6_PORTRANGE_LOW;
  815                 sin6 = (struct sockaddr_in6 *)sa;
  816                 portp = &sin6->sin6_port;
  817                 break;
  818 #endif
  819         default:
  820                 return (EPFNOSUPPORT);
  821         }
  822 
  823         sa->sa_family = af;
  824         sa->sa_len = salen;
  825 
  826         if (*portp == 0) {
  827                 bzero(&opt, sizeof(opt));
  828                 opt.sopt_dir = SOPT_GET;
  829                 opt.sopt_level = proto;
  830                 opt.sopt_name = portrange;
  831                 opt.sopt_val = &old;
  832                 opt.sopt_valsize = sizeof(old);
  833                 error = sogetopt(so, &opt);
  834                 if (error) {
  835                         goto out;
  836                 }
  837 
  838                 opt.sopt_dir = SOPT_SET;
  839                 opt.sopt_val = &portlow;
  840                 error = sosetopt(so, &opt);
  841                 if (error)
  842                         goto out;
  843         }
  844 
  845         error = sobind(so, sa, curthread);
  846 
  847         if (*portp == 0) {
  848                 if (error) {
  849                         opt.sopt_dir = SOPT_SET;
  850                         opt.sopt_val = &old;
  851                         sosetopt(so, &opt);
  852                 }
  853         }
  854 out:
  855         if (freesa)
  856                 free(sa, M_SONAME);
  857 
  858         return (error);
  859 }
  860 
  861 /*
  862  * Kernel module glue
  863  */
  864 static int
  865 krpc_modevent(module_t mod, int type, void *data)
  866 {
  867 
  868         return (0);
  869 }
  870 static moduledata_t krpc_mod = {
  871         "krpc",
  872         krpc_modevent,
  873         NULL,
  874 };
  875 DECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY);
  876 
  877 /* So that loader and kldload(2) can find us, wherever we are.. */
  878 MODULE_VERSION(krpc, 1);

Cache object: 6e995291fc9765bbbb3a0281aab0370b


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