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 int insecure = 0;
15 static SunStatus
16 authunixunpack(SunRpc *rpc, SunAuthUnix *au)
17 {
18 uchar *p, *ep;
19 SunAuthInfo *ai;
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 }
35 return SunSuccess;
36 }
38 static int
39 rnull(SunMsg *m)
40 {
41 NfsMount3RNull rx;
43 memset(&rx, 0, sizeof rx);
44 return sunmsgreply(m, &rx.call);
45 }
47 static int
48 rmnt(SunMsg *m)
49 {
50 Nfs3Handle nh;
51 NfsMount3RMnt rx;
52 SunAuthUnix au;
53 int ok;
55 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
56 return sunmsgreplyerror(m, ok);
58 /* ignore file system path and return the dump tree */
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;
68 return sunmsgreply(m, &rx.call);
69 }
71 static int
72 rumnt(SunMsg *m)
73 {
74 NfsMount3RUmnt rx;
76 /* ignore */
78 memset(&rx, 0, sizeof rx);
79 return sunmsgreply(m, &rx.call);
80 }
82 static int
83 rumntall(SunMsg *m)
84 {
85 NfsMount3RUmntall rx;
87 /* ignore */
89 memset(&rx, 0, sizeof rx);
90 return sunmsgreply(m, &rx.call);
91 }
93 static int
94 rexport(SunMsg *m)
95 {
96 NfsMount3RExport rx;
98 /* ignore */
100 memset(&rx, 0, sizeof rx);
101 rx.count = 0;
102 return sunmsgreply(m, &rx.call);
105 static void
106 rmount3(void *v)
108 SunMsg *m;
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;
135 void
136 mount3proc(void *v)
138 Channel *c;
139 SunMsg *m;
141 threadsetname("mount1");
142 c = v;
143 while((m=recvp(c)) != nil)
144 threadcreate(rmount3, m, SunStackSize);
147 static int
148 senderror(SunMsg *m, SunCall *rc, Nfs3Status status)
150 /* knows that status is first field in all replies */
151 ((Nfs3RGetattr*)rc)->status = status;
152 return sunmsgreply(m, rc);
155 static int
156 rnull0(SunMsg *m)
158 Nfs3RNull rx;
160 memset(&rx, 0, sizeof rx);
161 return sunmsgreply(m, &rx.call);
164 static int
165 rgetattr(SunMsg *m)
167 Nfs3TGetattr *tx = (Nfs3TGetattr*)m->call;
168 Nfs3RGetattr rx;
169 SunAuthUnix au;
170 int ok;
172 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
173 return sunmsgreplyerror(m, ok);
175 memset(&rx, 0, sizeof rx);
176 rx.status = fsgetattr(&au, &tx->handle, &rx.attr);
177 return sunmsgreply(m, &rx.call);
180 static int
181 rlookup(SunMsg *m)
183 Nfs3TLookup *tx = (Nfs3TLookup*)m->call;
184 Nfs3RLookup rx;
185 SunAuthUnix au;
186 int ok;
188 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
189 return sunmsgreplyerror(m, ok);
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);
206 static int
207 raccess(SunMsg *m)
209 Nfs3TAccess *tx = (Nfs3TAccess*)m->call;
210 Nfs3RAccess rx;
211 SunAuthUnix au;
212 int ok;
214 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
215 return sunmsgreplyerror(m, ok);
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);
223 static int
224 rreadlink(SunMsg *m)
226 Nfs3RReadlink rx;
227 Nfs3TReadlink *tx = (Nfs3TReadlink*)m->call;
228 SunAuthUnix au;
229 int ok;
231 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
232 return sunmsgreplyerror(m, ok);
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;
243 static int
244 rread(SunMsg *m)
246 Nfs3TRead *tx = (Nfs3TRead*)m->call;
247 Nfs3RRead rx;
248 SunAuthUnix au;
249 int ok;
251 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
252 return sunmsgreplyerror(m, ok);
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;
261 sunmsgreply(m, &rx.call);
262 free(rx.data);
263 return 0;
266 static int
267 rreaddir(SunMsg *m)
269 Nfs3TReadDir *tx = (Nfs3TReadDir*)m->call;
270 Nfs3RReadDir rx;
271 SunAuthUnix au;
272 int ok;
274 if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
275 return sunmsgreplyerror(m, ok);
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;
284 static int
285 rreaddirplus(SunMsg *m)
287 Nfs3RReadDirPlus rx;
289 memset(&rx, 0, sizeof rx);
290 rx.status = Nfs3ErrNotSupp;
291 sunmsgreply(m, &rx.call);
292 return 0;
295 static int
296 rfsstat(SunMsg *m)
298 Nfs3RFsStat rx;
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);
314 static int
315 rfsinfo(SunMsg *m)
317 Nfs3RFsInfo rx;
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);
337 static int
338 rpathconf(SunMsg *m)
340 Nfs3RPathconf rx;
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);
354 static int
355 rrofs(SunMsg *m)
357 uchar buf[512]; /* clumsy hack*/
359 memset(buf, 0, sizeof buf);
360 return senderror(m, (SunCall*)buf, Nfs3ErrRoFs);
364 static void
365 rnfs3(void *v)
367 SunMsg *m;
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;
421 void
422 nfs3proc(void *v)
424 Channel *c;
425 SunMsg *m;
427 c = v;
428 threadsetname("nfs3");
429 while((m = recvp(c)) != nil)
430 threadcreate(rnfs3, m, SunStackSize);