Blob


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"
13 static SunStatus
14 authunixunpack(SunRpc *rpc, SunAuthUnix *au)
15 {
16 uchar *p, *ep;
17 SunAuthInfo *ai;
19 ai = &rpc->cred;
20 if(ai->flavor != SunAuthSys)
21 return SunAuthTooWeak;
22 p = ai->data;
23 ep = p+ai->ndata;
24 if(sunauthunixunpack(p, ep, &p, au) < 0)
25 return SunGarbageArgs;
26 if(au->uid == 0)
27 au->uid = -1;
28 if(au->gid == 0)
29 au->gid = -1;
31 return SunSuccess;
32 }
34 static int
35 rnull(SunMsg *m)
36 {
37 NfsMount3RNull rx;
39 memset(&rx, 0, sizeof rx);
40 return sunmsgreply(m, &rx.call);
41 }
43 static int
44 rmnt(SunMsg *m)
45 {
46 Nfs3Handle nh;
47 NfsMount3RMnt rx;
48 SunAuthUnix au;
49 int ok;
51 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
52 return sunmsgreplyerror(m, ok);
54 /* ignore file system path and return the dump tree */
56 memset(&rx, 0, sizeof rx);
57 rx.nauth = 0;
58 rx.status = 0;
59 memset(&nh, 0, sizeof nh);
60 fsgetroot(&nh);
61 rx.handle = nh.h;
62 rx.len = nh.len;
64 return sunmsgreply(m, &rx.call);
65 }
67 static int
68 rumnt(SunMsg *m)
69 {
70 NfsMount3RUmnt rx;
72 /* ignore */
74 memset(&rx, 0, sizeof rx);
75 return sunmsgreply(m, &rx.call);
76 }
78 static int
79 rumntall(SunMsg *m)
80 {
81 NfsMount3RUmntall rx;
83 /* ignore */
85 memset(&rx, 0, sizeof rx);
86 return sunmsgreply(m, &rx.call);
87 }
89 static int
90 rexport(SunMsg *m)
91 {
92 NfsMount3RExport rx;
94 /* ignore */
96 memset(&rx, 0, sizeof rx);
97 rx.count = 0;
98 return sunmsgreply(m, &rx.call);
99 }
101 static void
102 rmount3(void *v)
104 SunMsg *m;
106 m = v;
107 switch(m->call->type){
108 default:
109 sunmsgreplyerror(m, SunProcUnavail);
110 case NfsMount3CallTNull:
111 rnull(m);
112 break;
113 case NfsMount3CallTMnt:
114 rmnt(m);
115 break;
116 case NfsMount3CallTDump:
117 rmnt(m);
118 break;
119 case NfsMount3CallTUmnt:
120 rumnt(m);
121 break;
122 case NfsMount3CallTUmntall:
123 rumntall(m);
124 break;
125 case NfsMount3CallTExport:
126 rexport(m);
127 break;
131 void
132 mount3proc(void *v)
134 Channel *c;
135 SunMsg *m;
137 threadsetname("mount1");
138 c = v;
139 while((m=recvp(c)) != nil)
140 threadcreate(rmount3, m, SunStackSize);
143 static int
144 senderror(SunMsg *m, SunCall *rc, Nfs3Status status)
146 /* knows that status is first field in all replies */
147 ((Nfs3RGetattr*)rc)->status = status;
148 return sunmsgreply(m, rc);
151 static int
152 rnull0(SunMsg *m)
154 Nfs3RNull rx;
156 memset(&rx, 0, sizeof rx);
157 return sunmsgreply(m, &rx.call);
160 static int
161 rgetattr(SunMsg *m)
163 Nfs3TGetattr *tx = (Nfs3TGetattr*)m->call;
164 Nfs3RGetattr rx;
165 SunAuthUnix au;
166 int ok;
168 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
169 return sunmsgreplyerror(m, ok);
171 memset(&rx, 0, sizeof rx);
172 rx.status = fsgetattr(&au, &tx->handle, &rx.attr);
173 return sunmsgreply(m, &rx.call);
176 static int
177 rlookup(SunMsg *m)
179 Nfs3TLookup *tx = (Nfs3TLookup*)m->call;
180 Nfs3RLookup rx;
181 SunAuthUnix au;
182 int ok;
184 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
185 return sunmsgreplyerror(m, ok);
187 memset(&rx, 0, sizeof rx);
188 rx.status = fsgetattr(&au, &tx->handle, &rx.dirAttr);
189 if(rx.status != Nfs3Ok)
190 return sunmsgreply(m, &rx.call);
191 rx.haveDirAttr = 1;
192 rx.status = fslookup(&au, &tx->handle, tx->name, &rx.handle);
193 if(rx.status != Nfs3Ok)
194 return sunmsgreply(m, &rx.call);
195 rx.status = fsgetattr(&au, &rx.handle, &rx.attr);
196 if(rx.status != Nfs3Ok)
197 return sunmsgreply(m, &rx.call);
198 rx.haveAttr = 1;
199 return sunmsgreply(m, &rx.call);
202 static int
203 raccess(SunMsg *m)
205 Nfs3TAccess *tx = (Nfs3TAccess*)m->call;
206 Nfs3RAccess rx;
207 SunAuthUnix au;
208 int ok;
210 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
211 return sunmsgreplyerror(m, ok);
213 memset(&rx, 0, sizeof rx);
214 rx.haveAttr = 1;
215 rx.status = fsaccess(&au, &tx->handle, tx->access, &rx.access, &rx.attr);
216 return sunmsgreply(m, &rx.call);
219 static int
220 rreadlink(SunMsg *m)
222 Nfs3RReadlink rx;
223 Nfs3TReadlink *tx = (Nfs3TReadlink*)m->call;
224 SunAuthUnix au;
225 int ok;
227 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
228 return sunmsgreplyerror(m, ok);
230 memset(&rx, 0, sizeof rx);
231 rx.haveAttr = 0;
232 rx.data = nil;
233 rx.status = fsreadlink(&au, &tx->handle, &rx.data);
234 sunmsgreply(m, &rx.call);
235 free(rx.data);
236 return 0;
239 static int
240 rread(SunMsg *m)
242 Nfs3TRead *tx = (Nfs3TRead*)m->call;
243 Nfs3RRead rx;
244 SunAuthUnix au;
245 int ok;
247 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
248 return sunmsgreplyerror(m, ok);
250 memset(&rx, 0, sizeof rx);
251 rx.haveAttr = 0;
252 rx.data = nil;
253 rx.status = fsreadfile(&au, &tx->handle, tx->count, tx->offset, &rx.data, &rx.count, &rx.eof);
254 if(rx.status == Nfs3Ok)
255 rx.ndata = rx.count;
257 sunmsgreply(m, &rx.call);
258 free(rx.data);
259 return 0;
262 static int
263 rreaddir(SunMsg *m)
265 Nfs3TReadDir *tx = (Nfs3TReadDir*)m->call;
266 Nfs3RReadDir rx;
267 SunAuthUnix au;
268 int ok;
270 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
271 return sunmsgreplyerror(m, ok);
273 memset(&rx, 0, sizeof rx);
274 rx.status = fsreaddir(&au, &tx->handle, tx->count, tx->cookie, &rx.data, &rx.count, &rx.eof);
275 sunmsgreply(m, &rx.call);
276 free(rx.data);
277 return 0;
280 static int
281 rreaddirplus(SunMsg *m)
283 Nfs3RReadDirPlus rx;
285 memset(&rx, 0, sizeof rx);
286 rx.status = Nfs3ErrNotSupp;
287 sunmsgreply(m, &rx.call);
288 return 0;
291 static int
292 rfsstat(SunMsg *m)
294 Nfs3RFsStat rx;
296 /* just make something up */
297 memset(&rx, 0, sizeof rx);
298 rx.status = Nfs3Ok;
299 rx.haveAttr = 0;
300 rx.totalBytes = 1000000000;
301 rx.freeBytes = 0;
302 rx.availBytes = 0;
303 rx.totalFiles = 100000;
304 rx.freeFiles = 0;
305 rx.availFiles = 0;
306 rx.invarSec = 0;
307 return sunmsgreply(m, &rx.call);
310 static int
311 rfsinfo(SunMsg *m)
313 Nfs3RFsInfo rx;
315 /* just make something up */
316 memset(&rx, 0, sizeof rx);
317 rx.status = Nfs3Ok;
318 rx.haveAttr = 0;
319 rx.readMax = MaxDataSize;
320 rx.readPref = MaxDataSize;
321 rx.readMult = MaxDataSize;
322 rx.writeMax = MaxDataSize;
323 rx.writePref = MaxDataSize;
324 rx.writeMult = MaxDataSize;
325 rx.readDirPref = MaxDataSize;
326 rx.maxFileSize = 1LL<<60;
327 rx.timePrec.sec = 1;
328 rx.timePrec.nsec = 0;
329 rx.flags = Nfs3FsHomogeneous|Nfs3FsCanSetTime;
330 return sunmsgreply(m, &rx.call);
333 static int
334 rpathconf(SunMsg *m)
336 Nfs3RPathconf rx;
338 memset(&rx, 0, sizeof rx);
339 rx.status = Nfs3Ok;
340 rx.haveAttr = 0;
341 rx.maxLink = 1;
342 rx.maxName = 1024;
343 rx.noTrunc = 1;
344 rx.chownRestricted = 0;
345 rx.caseInsensitive = 0;
346 rx.casePreserving = 1;
347 return sunmsgreply(m, &rx.call);
350 static int
351 rrofs(SunMsg *m)
353 uchar buf[512]; /* clumsy hack*/
355 memset(buf, 0, sizeof buf);
356 return senderror(m, (SunCall*)buf, Nfs3ErrRoFs);
360 static void
361 rnfs3(void *v)
363 SunMsg *m;
365 m = v;
366 switch(m->call->type){
367 default:
368 abort();
369 case Nfs3CallTNull:
370 rnull0(m);
371 break;
372 case Nfs3CallTGetattr:
373 rgetattr(m);
374 break;
375 case Nfs3CallTLookup:
376 rlookup(m);
377 break;
378 case Nfs3CallTAccess:
379 raccess(m);
380 break;
381 case Nfs3CallTReadlink:
382 rreadlink(m);
383 break;
384 case Nfs3CallTRead:
385 rread(m);
386 break;
387 case Nfs3CallTReadDir:
388 rreaddir(m);
389 break;
390 case Nfs3CallTReadDirPlus:
391 rreaddirplus(m);
392 break;
393 case Nfs3CallTFsStat:
394 rfsstat(m);
395 break;
396 case Nfs3CallTFsInfo:
397 rfsinfo(m);
398 break;
399 case Nfs3CallTPathconf:
400 rpathconf(m);
401 break;
402 case Nfs3CallTSetattr:
403 case Nfs3CallTWrite:
404 case Nfs3CallTCreate:
405 case Nfs3CallTMkdir:
406 case Nfs3CallTSymlink:
407 case Nfs3CallTMknod:
408 case Nfs3CallTRemove:
409 case Nfs3CallTRmdir:
410 case Nfs3CallTLink:
411 case Nfs3CallTCommit:
412 rrofs(m);
413 break;
417 void
418 nfs3proc(void *v)
420 Channel *c;
421 SunMsg *m;
423 c = v;
424 threadsetname("nfs3");
425 while((m = recvp(c)) != nil)
426 threadcreate(rnfs3, m, SunStackSize);