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

Cache object: 01c741ab95364b50f64a44c440c31f19


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