Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

dispatch.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Thu May 19 14:00:56 EDT 2005 by ken@xorian.net
00020 
00021 /*
00022  * dispatch.C   This file contains the function dispatch table.
00023  *
00024  * Adapted for Vesta:
00025  *              Tim Mann, <mann@pa.dec.com>
00026  *
00027  * Authors of original user-space NFS server:
00028  *              Donald J. Becker, <becker@super.org>
00029  *              Rick Sladkey, <jrs@world.std.com>
00030  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
00031  *
00032  *              This software maybe be used for any purpose provided
00033  *              the above copyright notice is retained.  It is supplied
00034  *              as is, with no warranty expressed or implied.
00035  */
00036 
00037 #include <Basics.H>
00038 #include <pthread.h>
00039 #include "logging.H"
00040 #include "nfsd.H"
00041 #include "AccessControl.H"
00042 
00043 #include "timing.H"
00044 
00045 /* Allow the following to be over-ridden at compile time. */
00046 
00047 #ifndef ROOT_UID
00048 #define ROOT_UID        0               /* Root user's ID. */
00049 #endif
00050 
00051 #ifndef NOBODY_UID
00052 #define NOBODY_UID      ((uid_t) 65534) /* The unprivileged user. */
00053 #endif
00054 
00055 #ifndef NOBODY_GID
00056 #define NOBODY_GID      ((gid_t) 65534) /* The unprivileged group. */
00057 #endif
00058 
00059 struct authunix_parms nobody_cred =
00060     { 0, "", NOBODY_UID, NOBODY_GID, 0, NULL };
00061 
00062 /*
00063  * This is a dispatch table to simplify error checking,
00064  * and supply return attributes for NFS functions.
00065  */
00066 
00067 #define CONCAT(a,b)     a##b
00068 #define CONCAT3(a,b,c)  a##b##c
00069 #define STRING(a)       #a
00070 
00071 #define table_ent(auth, ro, cred, res_type, arg_type, funct) {      \
00072         auth, ro, cred, sizeof(res_type), sizeof(arg_type),         \
00073         (xdrproc_t)CONCAT(xdr_,res_type),                           \
00074         (xdrproc_t)CONCAT(xdr_,arg_type),                           \
00075         (funct_proc)CONCAT3(nfsd_nfsproc_,funct,_2), STRING(funct), \
00076         (print_proc)CONCAT(Repos::pr_,arg_type),                           \
00077         (print_res_proc)CONCAT(Repos::pr_,res_type)                        \
00078 }
00079 
00080 #define nil     char
00081 #define xdr_nil xdr_void
00082 #define pr_nil  pr_void
00083 #define pr_char pr_void
00084 
00085 struct dispatch_entry dtable[] = {
00086         table_ent(0,0,0,nil,nil,null),
00087         table_ent(1,0,1,attrstat,nfs_fh,getattr),
00088         table_ent(1,1,1,attrstat,sattrargs,setattr),
00089         table_ent(0,0,0,nil,nil,root),
00090         table_ent(1,0,1,diropres,diropargs,lookup),
00091         table_ent(1,0,1,readlinkres,nfs_fh,readlink),
00092         table_ent(1,0,1,readres,readargs,read),
00093         table_ent(0,0,0,nil,nil,writecache),
00094         table_ent(1,1,1,attrstat,writeargs,write),
00095         table_ent(1,1,1,diropres,createargs,create),
00096         table_ent(1,1,1,nfsstat,diropargs,remove),
00097         table_ent(1,1,1,nfsstat,renameargs,rename),
00098         table_ent(1,1,1,nfsstat,linkargs,link),
00099         table_ent(1,1,1,nfsstat,symlinkargs,symlink),
00100         table_ent(1,1,1,diropres,createargs,mkdir),
00101         table_ent(1,1,1,nfsstat,diropargs,rmdir),
00102         table_ent(1,0,1,readdirres,readdirargs,readdir),
00103         table_ent(1,0,0,statfsres,nfs_fh,statfs),
00104 };
00105 
00106 void nfs_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
00107 {
00108     union argument_types argument;
00109     union result_types result;
00110     char iobuf[NFS_MAXDATA]; 
00111     struct authunix_parms *unix_cred;
00112     /* assert(NFS_MAXDATA >= NFS_MAXPATHLEN + 1); */
00113 
00114     unsigned int proc_index = rqstp->rq_proc;
00115     struct dispatch_entry *dent;
00116 
00117     if (proc_index >= (sizeof(dtable) / sizeof(dtable[0]))) {
00118         svcerr_noproc(transp);
00119         return;
00120     }
00121     dent = &dtable[proc_index];
00122 
00123     memset(&argument, 0, dent->arg_size);
00124     RECORD_TIME_POINT;
00125     if (!svc_getargs(transp, (xdrproc_t)dent->xdr_argument,
00126                      (char*)&argument)) {
00127         svcerr_decode(transp);
00128         return;
00129     }
00130     RECORD_TIME_POINT;
00131     /* Clear the result structure. */
00132     memset(&result, 0, dent->res_size);
00133 
00134     /* Ugly special case code: Provide a stack-allocated buffer for
00135        routines that return large data. */ 
00136     if (proc_index == NFSPROC_READ) {
00137         result.r_readres.readres_u.reply.data.data_val = iobuf;
00138     } else if (proc_index == NFSPROC_READLINK) {
00139         result.r_readlinkres.readlinkres_u.data = iobuf;
00140     }
00141 
00142     /* Log the call. */
00143     Repos::log_call(rqstp, dent, &argument);
00144 
00145     RECORD_TIME_POINT;
00146 
00147     if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
00148         unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
00149     } else {
00150         // !!Need code here to support GSSAPI credentials
00151         unix_cred = &nobody_cred;
00152     }
00153     AccessControl::UnixIdentityRep cred(unix_cred, &rqstp->rq_xprt->xp_raddr, false);
00154 
00155     RECORD_TIME_POINT;
00156 
00157     if (AccessControl::admit(&cred) || !dent->authenticate) {
00158       if(dent->authenticate)
00159         cred.validate();
00160       /* Do the function call itself. */
00161       result.r_nfsstat = (nfsstat) (*dent->funct)(&argument, &result, &cred);
00162     } else {
00163       // Kernel NFS servers return NFSERR_STALE for this case.  That
00164       // makes sense because their clients go through the mount daemon
00165       // first, which is responsible for denying permission if the
00166       // client is not authorized.  The repository doesn't use the
00167       // mount daemon, so it seems better to return a more
00168       // user-understandable error code here.
00169 
00170       Repos::dprintf(DBG_NFS, "unauthorized client, returning NFSERR_ACCES\n");
00171       result.r_nfsstat = NFSERR_ACCES;
00172     }
00173 
00174     /* Log the result. */
00175     Repos::log_result(rqstp, dent, &result);
00176 
00177     RECORD_TIME_POINT;
00178 
00179     if (!svc_sendreply(transp, (xdrproc_t)dent->xdr_result, (char*)&result)) {
00180         svcerr_systemerr(transp);
00181     }
00182 
00183     RECORD_TIME_POINT;
00184 
00185     svc_freeargs(transp, (xdrproc_t)dent->xdr_argument, (char*) &argument);
00186 
00187     RECORD_TIME_POINT;
00188 
00189     /* More ugly special case code: Free the reply only if needed */
00190     if (proc_index == NFSPROC_READDIR) {
00191         xdr_free((xdrproc_t)xdr_readdirres, (char*)&result.r_readdirres);
00192     }
00193 }

Generated on Mon May 8 00:48:43 2006 for Vesta by  doxygen 1.4.2