tnfs3srv.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tnfs3srv.c (7555B)
       ---
            1 /*
            2  * Simple read-only NFS v3 server.
            3  * Runs every request in its own thread.
            4  * Expects client to provide the fsxxx routines in nfs3srv.h.
            5  */
            6 #include <u.h>
            7 #include <libc.h>
            8 #include <thread.h>
            9 #include <sunrpc.h>
           10 #include <nfs3.h>
           11 #include "nfs3srv.h"
           12 
           13 int                        insecure = 0;
           14 
           15 static SunStatus
           16 authunixunpack(SunRpc *rpc, SunAuthUnix *au)
           17 {
           18         uchar *p, *ep;
           19         SunAuthInfo *ai;
           20 
           21         ai = &rpc->cred;
           22         if(ai->flavor != SunAuthSys)
           23                 return SunAuthTooWeak;
           24         p = ai->data;
           25         ep = p+ai->ndata;
           26         if(sunauthunixunpack(p, ep, &p, au) < 0)
           27                 return SunGarbageArgs;
           28         if(!insecure){
           29                 if(au->uid == 0)
           30                         au->uid = -1;
           31                 if(au->gid == 0)
           32                         au->gid = -1;
           33         }
           34 
           35         return SunSuccess;
           36 }
           37 
           38 static int
           39 rnull(SunMsg *m)
           40 {
           41         NfsMount3RNull rx;
           42 
           43         memset(&rx, 0, sizeof rx);
           44         return sunmsgreply(m, &rx.call);
           45 }
           46 
           47 static int
           48 rmnt(SunMsg *m)
           49 {
           50         Nfs3Handle nh;
           51         NfsMount3RMnt rx;
           52         SunAuthUnix au;
           53         int ok;
           54 
           55         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
           56                 return sunmsgreplyerror(m, ok);
           57 
           58         /* ignore file system path and return the dump tree */
           59 
           60         memset(&rx, 0, sizeof rx);
           61         rx.nauth = 0;
           62         rx.status = 0;
           63         memset(&nh, 0, sizeof nh);
           64         fsgetroot(&nh);
           65         rx.handle = nh.h;
           66         rx.len = nh.len;
           67 
           68         return sunmsgreply(m, &rx.call);
           69 }
           70 
           71 static int
           72 rumnt(SunMsg *m)
           73 {
           74         NfsMount3RUmnt rx;
           75 
           76         /* ignore */
           77 
           78         memset(&rx, 0, sizeof rx);
           79         return sunmsgreply(m, &rx.call);
           80 }
           81 
           82 static int
           83 rumntall(SunMsg *m)
           84 {
           85         NfsMount3RUmntall rx;
           86 
           87         /* ignore */
           88 
           89         memset(&rx, 0, sizeof rx);
           90         return sunmsgreply(m, &rx.call);
           91 }
           92 
           93 static int
           94 rexport(SunMsg *m)
           95 {
           96         NfsMount3RExport rx;
           97 
           98         /* ignore */
           99 
          100         memset(&rx, 0, sizeof rx);
          101         rx.count = 0;
          102         return sunmsgreply(m, &rx.call);
          103 }
          104 
          105 static void
          106 rmount3(void *v)
          107 {
          108         SunMsg *m;
          109 
          110         m = v;
          111         switch(m->call->type){
          112         default:
          113                 sunmsgreplyerror(m, SunProcUnavail);
          114         case NfsMount3CallTNull:
          115                 rnull(m);
          116                 break;
          117         case NfsMount3CallTMnt:
          118                 rmnt(m);
          119                 break;
          120         case NfsMount3CallTDump:
          121                 rmnt(m);
          122                 break;
          123         case NfsMount3CallTUmnt:
          124                 rumnt(m);
          125                 break;
          126         case NfsMount3CallTUmntall:
          127                 rumntall(m);
          128                 break;
          129         case NfsMount3CallTExport:
          130                 rexport(m);
          131                 break;
          132         }
          133 }
          134 
          135 void
          136 mount3proc(void *v)
          137 {
          138         Channel *c;
          139         SunMsg *m;
          140 
          141         threadsetname("mount1");
          142         c = v;
          143         while((m=recvp(c)) != nil)
          144                 threadcreate(rmount3, m, SunStackSize);
          145 }
          146 
          147 static int
          148 senderror(SunMsg *m, SunCall *rc, Nfs3Status status)
          149 {
          150         /* knows that status is first field in all replies */
          151         ((Nfs3RGetattr*)rc)->status = status;
          152         return sunmsgreply(m, rc);
          153 }
          154 
          155 static int
          156 rnull0(SunMsg *m)
          157 {
          158         Nfs3RNull rx;
          159 
          160         memset(&rx, 0, sizeof rx);
          161         return sunmsgreply(m, &rx.call);
          162 }
          163 
          164 static int
          165 rgetattr(SunMsg *m)
          166 {
          167         Nfs3TGetattr *tx = (Nfs3TGetattr*)m->call;
          168         Nfs3RGetattr rx;
          169         SunAuthUnix au;
          170         int ok;
          171 
          172         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          173                 return sunmsgreplyerror(m, ok);
          174 
          175         memset(&rx, 0, sizeof rx);
          176         rx.status = fsgetattr(&au, &tx->handle, &rx.attr);
          177         return sunmsgreply(m, &rx.call);
          178 }
          179 
          180 static int
          181 rlookup(SunMsg *m)
          182 {
          183         Nfs3TLookup *tx = (Nfs3TLookup*)m->call;
          184         Nfs3RLookup rx;
          185         SunAuthUnix au;
          186         int ok;
          187 
          188         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          189                 return sunmsgreplyerror(m, ok);
          190 
          191         memset(&rx, 0, sizeof rx);
          192         rx.status = fsgetattr(&au, &tx->handle, &rx.dirAttr);
          193         if(rx.status != Nfs3Ok)
          194                 return sunmsgreply(m, &rx.call);
          195         rx.haveDirAttr = 1;
          196         rx.status = fslookup(&au, &tx->handle, tx->name, &rx.handle);
          197         if(rx.status != Nfs3Ok)
          198                 return sunmsgreply(m, &rx.call);
          199         rx.status = fsgetattr(&au, &rx.handle, &rx.attr);
          200         if(rx.status != Nfs3Ok)
          201                 return sunmsgreply(m, &rx.call);
          202         rx.haveAttr = 1;
          203         return sunmsgreply(m, &rx.call);
          204 }
          205 
          206 static int
          207 raccess(SunMsg *m)
          208 {
          209         Nfs3TAccess *tx = (Nfs3TAccess*)m->call;
          210         Nfs3RAccess rx;
          211         SunAuthUnix au;
          212         int ok;
          213 
          214         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          215                 return sunmsgreplyerror(m, ok);
          216 
          217         memset(&rx, 0, sizeof rx);
          218         rx.haveAttr = 1;
          219         rx.status = fsaccess(&au, &tx->handle, tx->access, &rx.access, &rx.attr);
          220         return sunmsgreply(m, &rx.call);
          221 }
          222 
          223 static int
          224 rreadlink(SunMsg *m)
          225 {
          226         Nfs3RReadlink rx;
          227         Nfs3TReadlink *tx = (Nfs3TReadlink*)m->call;
          228         SunAuthUnix au;
          229         int ok;
          230 
          231         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          232                 return sunmsgreplyerror(m, ok);
          233 
          234         memset(&rx, 0, sizeof rx);
          235         rx.haveAttr = 0;
          236         rx.data = nil;
          237         rx.status = fsreadlink(&au, &tx->handle, &rx.data);
          238         sunmsgreply(m, &rx.call);
          239         free(rx.data);
          240         return 0;
          241 }
          242 
          243 static int
          244 rread(SunMsg *m)
          245 {
          246         Nfs3TRead *tx = (Nfs3TRead*)m->call;
          247         Nfs3RRead rx;
          248         SunAuthUnix au;
          249         int ok;
          250 
          251         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          252                 return sunmsgreplyerror(m, ok);
          253 
          254         memset(&rx, 0, sizeof rx);
          255         rx.haveAttr = 0;
          256         rx.data = nil;
          257         rx.status = fsreadfile(&au, &tx->handle, tx->count, tx->offset, &rx.data, &rx.count, &rx.eof);
          258         if(rx.status == Nfs3Ok)
          259                 rx.ndata = rx.count;
          260 
          261         sunmsgreply(m, &rx.call);
          262         free(rx.data);
          263         return 0;
          264 }
          265 
          266 static int
          267 rreaddir(SunMsg *m)
          268 {
          269         Nfs3TReadDir *tx = (Nfs3TReadDir*)m->call;
          270         Nfs3RReadDir rx;
          271         SunAuthUnix au;
          272         int ok;
          273 
          274         if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
          275                 return sunmsgreplyerror(m, ok);
          276 
          277         memset(&rx, 0, sizeof rx);
          278         rx.status = fsreaddir(&au, &tx->handle, tx->count, tx->cookie, &rx.data, &rx.count, &rx.eof);
          279         sunmsgreply(m, &rx.call);
          280         free(rx.data);
          281         return 0;
          282 }
          283 
          284 static int
          285 rreaddirplus(SunMsg *m)
          286 {
          287         Nfs3RReadDirPlus rx;
          288 
          289         memset(&rx, 0, sizeof rx);
          290         rx.status = Nfs3ErrNotSupp;
          291         sunmsgreply(m, &rx.call);
          292         return 0;
          293 }
          294 
          295 static int
          296 rfsstat(SunMsg *m)
          297 {
          298         Nfs3RFsStat rx;
          299 
          300         /* just make something up */
          301         memset(&rx, 0, sizeof rx);
          302         rx.status = Nfs3Ok;
          303         rx.haveAttr = 0;
          304         rx.totalBytes = 1000000000;
          305         rx.freeBytes = 0;
          306         rx.availBytes = 0;
          307         rx.totalFiles = 100000;
          308         rx.freeFiles = 0;
          309         rx.availFiles = 0;
          310         rx.invarSec = 0;
          311         return sunmsgreply(m, &rx.call);
          312 }
          313 
          314 static int
          315 rfsinfo(SunMsg *m)
          316 {
          317         Nfs3RFsInfo rx;
          318 
          319         /* just make something up */
          320         memset(&rx, 0, sizeof rx);
          321         rx.status = Nfs3Ok;
          322         rx.haveAttr = 0;
          323         rx.readMax = MaxDataSize;
          324         rx.readPref = MaxDataSize;
          325         rx.readMult = MaxDataSize;
          326         rx.writeMax = MaxDataSize;
          327         rx.writePref = MaxDataSize;
          328         rx.writeMult = MaxDataSize;
          329         rx.readDirPref = MaxDataSize;
          330         rx.maxFileSize = 1LL<<60;
          331         rx.timePrec.sec = 1;
          332         rx.timePrec.nsec = 0;
          333         rx.flags = Nfs3FsHomogeneous|Nfs3FsCanSetTime;
          334         return sunmsgreply(m, &rx.call);
          335 }
          336 
          337 static int
          338 rpathconf(SunMsg *m)
          339 {
          340         Nfs3RPathconf rx;
          341 
          342         memset(&rx, 0, sizeof rx);
          343         rx.status = Nfs3Ok;
          344         rx.haveAttr = 0;
          345         rx.maxLink = 1;
          346         rx.maxName = 1024;
          347         rx.noTrunc = 1;
          348         rx.chownRestricted = 0;
          349         rx.caseInsensitive = 0;
          350         rx.casePreserving = 1;
          351         return sunmsgreply(m, &rx.call);
          352 }
          353 
          354 static int
          355 rrofs(SunMsg *m)
          356 {
          357         uchar buf[512];        /* clumsy hack*/
          358 
          359         memset(buf, 0, sizeof buf);
          360         return senderror(m, (SunCall*)buf, Nfs3ErrRoFs);
          361 }
          362 
          363 
          364 static void
          365 rnfs3(void *v)
          366 {
          367         SunMsg *m;
          368 
          369         m = v;
          370         switch(m->call->type){
          371         default:
          372                 abort();
          373         case Nfs3CallTNull:
          374                 rnull0(m);
          375                 break;
          376         case Nfs3CallTGetattr:
          377                 rgetattr(m);
          378                 break;
          379         case Nfs3CallTLookup:
          380                 rlookup(m);
          381                 break;
          382         case Nfs3CallTAccess:
          383                 raccess(m);
          384                 break;
          385         case Nfs3CallTReadlink:
          386                 rreadlink(m);
          387                 break;
          388         case Nfs3CallTRead:
          389                 rread(m);
          390                 break;
          391         case Nfs3CallTReadDir:
          392                 rreaddir(m);
          393                 break;
          394         case Nfs3CallTReadDirPlus:
          395                 rreaddirplus(m);
          396                 break;
          397         case Nfs3CallTFsStat:
          398                 rfsstat(m);
          399                 break;
          400         case Nfs3CallTFsInfo:
          401                 rfsinfo(m);
          402                 break;
          403         case Nfs3CallTPathconf:
          404                 rpathconf(m);
          405                 break;
          406         case Nfs3CallTSetattr:
          407         case Nfs3CallTWrite:
          408         case Nfs3CallTCreate:
          409         case Nfs3CallTMkdir:
          410         case Nfs3CallTSymlink:
          411         case Nfs3CallTMknod:
          412         case Nfs3CallTRemove:
          413         case Nfs3CallTRmdir:
          414         case Nfs3CallTLink:
          415         case Nfs3CallTCommit:
          416                 rrofs(m);
          417                 break;
          418         }
          419 }
          420 
          421 void
          422 nfs3proc(void *v)
          423 {
          424         Channel *c;
          425         SunMsg *m;
          426 
          427         c = v;
          428         threadsetname("nfs3");
          429         while((m = recvp(c)) != nil)
          430                 threadcreate(rnfs3, m, SunStackSize);
          431 }