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

Cache object: 82c36b252ae530860c3fbbbc9a412ee1


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