plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

nfs3srv.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 }