00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
00046
00047 #ifndef ROOT_UID
00048 #define ROOT_UID 0
00049 #endif
00050
00051 #ifndef NOBODY_UID
00052 #define NOBODY_UID ((uid_t) 65534)
00053 #endif
00054
00055 #ifndef NOBODY_GID
00056 #define NOBODY_GID ((gid_t) 65534)
00057 #endif
00058
00059 struct authunix_parms nobody_cred =
00060 { 0, "", NOBODY_UID, NOBODY_GID, 0, NULL };
00061
00062
00063
00064
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
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
00132 memset(&result, 0, dent->res_size);
00133
00134
00135
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
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
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
00161 result.r_nfsstat = (nfsstat) (*dent->funct)(&argument, &result, &cred);
00162 } else {
00163
00164
00165
00166
00167
00168
00169
00170 Repos::dprintf(DBG_NFS, "unauthorized client, returning NFSERR_ACCES\n");
00171 result.r_nfsstat = NFSERR_ACCES;
00172 }
00173
00174
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
00190 if (proc_index == NFSPROC_READDIR) {
00191 xdr_free((xdrproc_t)xdr_readdirres, (char*)&result.r_readdirres);
00192 }
00193 }