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

Cache object: 23ac05173c396c5b45dee2f4e0778e7d


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