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/fs/nfsclient/nfs_clkrpc.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 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include "opt_kgssapi.h"
   40 #include "opt_kern_tls.h"
   41 
   42 #include <fs/nfs/nfsport.h>
   43 
   44 #include <rpc/rpc.h>
   45 #include <rpc/replay.h>
   46 #include <rpc/rpcsec_gss.h>
   47 #include <rpc/rpcsec_tls.h>
   48 
   49 NFSDLOCKMUTEX;
   50 
   51 extern SVCPOOL  *nfscbd_pool;
   52 
   53 static int nfs_cbproc(struct nfsrv_descript *, u_int32_t);
   54 
   55 extern u_long sb_max_adj;
   56 extern int nfs_numnfscbd;
   57 extern int nfscl_debuglevel;
   58 
   59 /*
   60  * NFS client system calls for handling callbacks.
   61  */
   62 
   63 /*
   64  * Handles server to client callbacks.
   65  */
   66 static void
   67 nfscb_program(struct svc_req *rqst, SVCXPRT *xprt)
   68 {
   69         struct nfsrv_descript nd;
   70         int cacherep, credflavor;
   71 #ifdef KERN_TLS
   72         u_int maxlen;
   73 #endif
   74 
   75         memset(&nd, 0, sizeof(nd));
   76         if (rqst->rq_proc != NFSPROC_NULL &&
   77             rqst->rq_proc != NFSV4PROC_CBCOMPOUND) {
   78                 svcerr_noproc(rqst);
   79                 svc_freereq(rqst);
   80                 return;
   81         }
   82         nd.nd_procnum = rqst->rq_proc;
   83         nd.nd_flag = (ND_NFSCB | ND_NFSV4);
   84 
   85         /*
   86          * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 -
   87          * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP
   88          * mounts.
   89          */
   90         nd.nd_mrep = rqst->rq_args;
   91         rqst->rq_args = NULL;
   92         newnfs_realign(&nd.nd_mrep, M_WAITOK);
   93         nd.nd_md = nd.nd_mrep;
   94         nd.nd_dpos = mtod(nd.nd_md, caddr_t);
   95         nd.nd_nam = svc_getrpccaller(rqst);
   96         nd.nd_nam2 = rqst->rq_addr;
   97         nd.nd_mreq = NULL;
   98         nd.nd_cred = NULL;
   99 
  100         NFSCL_DEBUG(1, "cbproc=%d\n",nd.nd_procnum);
  101         if (nd.nd_procnum != NFSPROC_NULL) {
  102                 if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) {
  103                         svcerr_weakauth(rqst);
  104                         svc_freereq(rqst);
  105                         m_freem(nd.nd_mrep);
  106                         return;
  107                 }
  108 
  109                 /* For now, I don't care what credential flavor was used. */
  110 #ifdef notyet
  111 #ifdef MAC
  112                 mac_cred_associate_nfsd(nd.nd_cred);
  113 #endif
  114 #endif
  115 #ifdef KERN_TLS
  116                 if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0 &&
  117                     rpctls_getinfo(&maxlen, false, false)) {
  118                         nd.nd_flag |= ND_EXTPG;
  119                         nd.nd_maxextsiz = maxlen;
  120                 }
  121 #endif
  122                 cacherep = nfs_cbproc(&nd, rqst->rq_xid);
  123         } else {
  124                 NFSMGET(nd.nd_mreq);
  125                 nd.nd_mreq->m_len = 0;
  126                 cacherep = RC_REPLY;
  127         }
  128         if (nd.nd_mrep != NULL)
  129                 m_freem(nd.nd_mrep);
  130 
  131         if (nd.nd_cred != NULL)
  132                 crfree(nd.nd_cred);
  133 
  134         if (cacherep == RC_DROPIT) {
  135                 if (nd.nd_mreq != NULL)
  136                         m_freem(nd.nd_mreq);
  137                 svc_freereq(rqst);
  138                 return;
  139         }
  140 
  141         if (nd.nd_mreq == NULL) {
  142                 svcerr_decode(rqst);
  143                 svc_freereq(rqst);
  144                 return;
  145         }
  146 
  147         if (nd.nd_repstat & NFSERR_AUTHERR) {
  148                 svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR);
  149                 if (nd.nd_mreq != NULL)
  150                         m_freem(nd.nd_mreq);
  151         } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq))
  152                 svcerr_systemerr(rqst);
  153         else
  154                 NFSCL_DEBUG(1, "cbrep sent\n");
  155         svc_freereq(rqst);
  156 }
  157 
  158 /*
  159  * Check the cache and, optionally, do the RPC.
  160  * Return the appropriate cache response.
  161  */
  162 static int
  163 nfs_cbproc(struct nfsrv_descript *nd, u_int32_t xid)
  164 {
  165         struct thread *td = curthread;
  166         int cacherep;
  167 
  168         if (nd->nd_nam2 == NULL)
  169                 nd->nd_flag |= ND_STREAMSOCK;
  170 
  171         nfscl_docb(nd, td);
  172         if (nd->nd_repstat == NFSERR_DONTREPLY)
  173                 cacherep = RC_DROPIT;
  174         else
  175                 cacherep = RC_REPLY;
  176         return (cacherep);
  177 }
  178 
  179 /*
  180  * Adds a socket to the list for servicing by nfscbds.
  181  */
  182 int
  183 nfscbd_addsock(struct file *fp)
  184 {
  185         int siz;
  186         struct socket *so;
  187         int error;
  188         SVCXPRT *xprt;
  189 
  190         so = fp->f_data;
  191 
  192         siz = sb_max_adj;
  193         error = soreserve(so, siz, siz);
  194         if (error)
  195                 return (error);
  196 
  197         /*
  198          * Steal the socket from userland so that it doesn't close
  199          * unexpectedly.
  200          */
  201         if (so->so_type == SOCK_DGRAM)
  202                 xprt = svc_dg_create(nfscbd_pool, so, 0, 0);
  203         else
  204                 xprt = svc_vc_create(nfscbd_pool, so, 0, 0);
  205         if (xprt) {
  206                 fp->f_ops = &badfileops;
  207                 fp->f_data = NULL;
  208                 svc_reg(xprt, NFS_CALLBCKPROG, NFSV4_CBVERS, nfscb_program,
  209                     NULL);
  210                 SVC_RELEASE(xprt);
  211         }
  212 
  213         return (0);
  214 }
  215 
  216 /*
  217  * Called by nfssvc() for nfscbds. Just loops around servicing rpc requests
  218  * until it is killed by a signal.
  219  *
  220  * For now, only support callbacks via RPCSEC_GSS if there is a KerberosV
  221  * keytab entry with a host based entry in it on the client. (I'm not even
  222  * sure that getting Acceptor credentials for a user principal with a
  223  * credentials cache is possible, but even if it is, major changes to the
  224  * kgssapi would be required.)
  225  * I don't believe that this is a serious limitation since, as of 2009, most
  226  * NFSv4 servers supporting callbacks are using AUTH_SYS for callbacks even
  227  * when the client is using RPCSEC_GSS. (This BSD server uses AUTH_SYS
  228  * for callbacks unless nfsrv_gsscallbackson is set non-zero.)
  229  */
  230 int
  231 nfscbd_nfsd(struct thread *td, struct nfsd_nfscbd_args *args)
  232 {
  233         char principal[128];
  234         int error;
  235 
  236         if (args != NULL) {
  237                 error = copyinstr(args->principal, principal,
  238                     sizeof(principal), NULL);
  239                 if (error)
  240                         return (error);
  241         } else {
  242                 principal[0] = '\0';
  243         }
  244 
  245         /*
  246          * Only the first nfsd actually does any work. The RPC code
  247          * adds threads to it as needed. Any extra processes offered
  248          * by nfsd just exit. If nfsd is new enough, it will call us
  249          * once with a structure that specifies how many threads to
  250          * use.
  251          */
  252         NFSD_LOCK();
  253         if (nfs_numnfscbd == 0) {
  254                 nfs_numnfscbd++;
  255 
  256                 NFSD_UNLOCK();
  257 
  258                 if (principal[0] != '\0')
  259                         rpc_gss_set_svc_name_call(principal, "kerberosv5",
  260                             GSS_C_INDEFINITE, NFS_CALLBCKPROG, NFSV4_CBVERS);
  261 
  262                 nfscbd_pool->sp_minthreads = 4;
  263                 nfscbd_pool->sp_maxthreads = 4;
  264                         
  265                 svc_run(nfscbd_pool);
  266 
  267                 rpc_gss_clear_svc_name_call(NFS_CALLBCKPROG, NFSV4_CBVERS);
  268 
  269                 NFSD_LOCK();
  270                 nfs_numnfscbd--;
  271                 nfsrvd_cbinit(1);
  272         }
  273         NFSD_UNLOCK();
  274 
  275         return (0);
  276 }
  277 
  278 /*
  279  * Initialize the data structures for the server.
  280  * Handshake with any new nfsds starting up to avoid any chance of
  281  * corruption.
  282  */
  283 void
  284 nfsrvd_cbinit(int terminating)
  285 {
  286 
  287         NFSD_LOCK_ASSERT();
  288 
  289         if (terminating) {
  290                 /* Wait for any xprt registrations to complete. */
  291                 while (nfs_numnfscbd > 0)
  292                         msleep(&nfs_numnfscbd, NFSDLOCKMUTEXPTR, PZERO, 
  293                             "nfscbdt", 0);
  294                 if (nfscbd_pool != NULL) {
  295                         NFSD_UNLOCK();
  296                         svcpool_close(nfscbd_pool);
  297                         NFSD_LOCK();
  298                 }
  299         }
  300 
  301         if (nfscbd_pool == NULL) {
  302                 NFSD_UNLOCK();
  303                 nfscbd_pool = svcpool_create("nfscbd", NULL);
  304                 nfscbd_pool->sp_rcache = NULL;
  305                 nfscbd_pool->sp_assign = NULL;
  306                 nfscbd_pool->sp_done = NULL;
  307                 NFSD_LOCK();
  308         }
  309 }

Cache object: c2688fecd22f007c8a0255bf56280bef


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