cachemgr-setuerror-ifdef-cleanup-20020827
[openafs.git] / src / afs / afs_nfsdisp.c
1 /*
2  * This software has been released under the terms of the IBM Public
3  * License.  For details, see the LICENSE file in the top-level source
4  * directory or online at http://www.openafs.org/dl/license10.html
5  */
6
7 /*
8  * Implements:
9  */
10 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 /* Ugly Ugly Ugly  but precludes conflicting XDR macros; We want kernel xdr */
16 #define __XDR_INCLUDE__
17 #include "../afs/stds.h"
18 #include "../afs/sysincludes.h" /* Standard vendor system headers */
19 #if defined(AFS_SUN55_ENV) && !defined(AFS_NONFSTRANS) 
20 #include "../rpc/types.h"
21 #include "../rpc/auth.h"
22 #include "../rpc/auth_unix.h"
23 #include "../rpc/auth_des.h"
24 #if !defined(AFS_SUN58_ENV)
25 #include "../rpc/auth_kerb.h"
26 #endif
27 #include "../sys/tiuser.h"
28 #include "../rpc/xdr.h"
29 #include "../rpc/svc.h"
30 #include "../nfs/nfs.h"
31 #include "../nfs/export.h"
32 #include "../nfs/nfs_clnt.h"
33 #include "../nfs/nfs_acl.h"
34 #include "../afs/afsincludes.h" 
35 #include "../afs/afs_stats.h"   
36 #include "../afs/exporter.h"
37
38 static int xlatorinit_v2_done=0;
39 static int xlatorinit_v3_done=0;
40
41 extern int afs_nobody;
42 extern int afs_NFSRootOnly;
43
44 /* It's bigger than this, but we don't care about anything else */
45 struct rfs_disp_tbl {
46         void  (*dis_proc)();    
47 };
48
49 struct afs_nfs_disp_tbl {
50     void (*afs_proc)();
51     void (*orig_proc)();
52 };
53
54 struct afs_nfs2_resp {
55     enum nfsstat status;
56 };
57
58 #ifndef ACL2_NPROC
59 #define ACL2_NPROC      5
60 #endif
61
62 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC];
63 struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC];
64
65 static int 
66 is_afs_fh(fhandle_t *fhp) {
67     if ((fhp->fh_fsid.val[0] == AFS_VFSMAGIC) &&
68         (fhp->fh_fsid.val[1] == AFS_VFSFSID)) 
69         return 1;
70     return 0;
71 }
72
73 afs_int32 
74 nfs2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp, fhandle_t **fh2pp)
75 {
76     struct vnode *vp;
77     fhandle_t *fhp1=0;
78     fhandle_t *fhp2=0;
79     int errorcode;
80
81     *fh2pp = (fhandle_t *)0;
82     switch (which) {
83         case RFS_GETATTR:
84         case RFS_READLINK:
85         case RFS_STATFS:
86             fhp1 = (fhandle_t *)args;
87             break;
88         case RFS_SETATTR: 
89         {
90             struct nfssaargs *sargs = (struct nfssaargs *)args; 
91             fhp1 = (fhandle_t *)&sargs->saa_fh;
92             break;
93         } 
94         case RFS_LOOKUP: 
95         {
96             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
97             fhp1 = (fhandle_t *)&sargs->da_fhandle;
98             break;
99         } 
100         case RFS_READ:
101         {
102             struct nfsreadargs *sargs = (struct nfsreadargs *)args;
103             fhp1 = (fhandle_t *)&sargs->ra_fhandle;
104             break;
105         } 
106         case RFS_WRITE: 
107         {
108             struct nfswriteargs *sargs = (struct nfswriteargs *)args;
109             fhp1 = (fhandle_t *)&sargs->wa_fhandle;
110             break;
111         } 
112         case RFS_CREATE: 
113         {
114             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
115             fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
116             break;
117         } 
118         case RFS_REMOVE: 
119         {
120             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
121             fhp1 = (fhandle_t *)&sargs->da_fhandle;
122             break;
123         }
124         case RFS_RENAME: 
125         {
126             struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
127             fhp1 = (fhandle_t *)&sargs->rna_from.da_fhandle;
128             fhp2 = (fhandle_t *)&sargs->rna_to.da_fhandle;
129             break;
130         } 
131         case RFS_LINK: 
132         {
133             struct nfslinkargs *sargs = (struct nfslinkargs *)args;
134             fhp1 = (fhandle_t *)&sargs->la_from;
135             fhp2 = (fhandle_t *)&sargs->la_to.da_fhandle;
136             break;
137         } 
138         case RFS_SYMLINK: 
139         {
140             struct nfsslargs *sargs = (struct nfsslargs *)args;
141             fhp1 = (fhandle_t *)&sargs->sla_from.da_fhandle;
142             break;
143         } 
144         case RFS_MKDIR: 
145         {
146             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
147             fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
148             break;
149         } 
150         case RFS_RMDIR: 
151         {
152             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
153             fhp1 = (fhandle_t *)&sargs->da_fhandle;
154             break;
155         } 
156         case RFS_READDIR: 
157         {
158             struct nfsrddirargs *sargs = (struct nfsrddirargs *)args;
159             fhp1 = (fhandle_t *)&sargs->rda_fh;
160             break;
161         } 
162         default:
163             return NULL;
164     }
165
166     /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
167     if (is_afs_fh(fhp1)) {
168         *fhpp = fhp1;
169         if (fhp2) 
170             *fh2pp = fhp2;
171         return 1;           
172     }
173     if (is_afs_fh(fhp2)) {
174         *fhpp = fhp1;
175         *fh2pp = fhp2;
176         return 1;           
177     }
178     return NULL;
179 }
180
181 afs_int32 
182 acl2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp)
183 {
184     fhandle_t *fhp;
185
186     switch(which) {
187     case ACLPROC2_NULL:
188     {
189         return NULL;
190     }
191     case ACLPROC2_GETACL: 
192     {
193         struct GETACL2args *sargs = (struct GETACL2args *) args;
194         fhp = &sargs->fh;
195         break;
196     }
197     case ACLPROC2_SETACL: 
198     {
199         struct SETACL2args *sargs = (struct SETACL2args *) args;
200         fhp = &sargs->fh;
201         break;
202     }
203     case ACLPROC2_GETATTR: 
204     {
205         struct GETATTR2args *sargs = (struct GETATTR2args *) args;
206         fhp = &sargs->fh;
207         break;
208     }
209     case ACLPROC2_ACCESS: 
210     {
211         struct ACCESS2args *sargs = (struct ACCESS2args *) args;
212         fhp = &sargs->fh;
213         break;
214     }
215     default:
216         return NULL;
217     }
218
219     if (is_afs_fh(fhp)) {
220         *fhpp = fhp;
221         return 1;
222     }
223
224     return NULL;
225 }
226
227 int
228 afs_nfs2_dispatcher(int type, afs_int32 which, char *argp, 
229                     struct exportinfo **expp, 
230                     struct svc_req *rp, struct AFS_UCRED *crp)
231 {
232     afs_int32 call = 0;
233     afs_int32 code = 0;
234     afs_int32 client = 0;
235     struct sockaddr *sa;
236     fhandle_t *fh = (fhandle_t *)argp;
237     fhandle_t *fh2 = (fhandle_t *)0;
238
239     if (!xlatorinit_v2_done)
240         return 2;
241
242     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
243     client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
244
245     AFS_GLOCK();
246     code = 0;
247     switch (type) {
248     case 0:
249         code = nfs2_to_afs_call(which, argp, &fh, &fh2);
250         break;
251     case 1:
252         code = acl2_to_afs_call(which, argp, &fh);
253         break;
254     default:
255         break;
256     }
257
258     if (code) {
259         struct afs_exporter *out = 0;
260         afs_int32 dummy;
261         static int once = 0;
262         struct SmallFid Sfid;
263
264         memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
265
266         /* We ran */
267         call = 1;
268         if (!once && *expp) {
269             afs_nobody = (*expp)->exi_export.ex_anon;
270             once = 1;
271         }
272         code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
273                                         client, &dummy, &out);
274         /* Be careful to release this */
275         if (!code && out)
276             EXP_RELE(out);
277
278         /* We ran and failed */
279         if (code == EINVAL) 
280             call = 2;
281     }
282
283     AFS_GUNLOCK();
284     return call;
285 }
286
287 void 
288 afs_nfs2_smallfidder(struct nfsdiropres *dr)
289 {
290     register fhandle_t *fhp = (fhandle_t *)&dr->dr_fhandle;
291     afs_int32 addr[2];
292     struct vcache *vcp;
293
294 #if defined(AFS_SUN57_64BIT_ENV)
295     /* See also afs_fid() */    
296     memcpy((char *)addr, fhp->fh_data, 10);
297     addr[1] = (addr[1] >> 48) & 0xffff;
298 #else 
299     memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
300 #endif
301
302     AFS_GLOCK();
303     vcp = VTOAFS((struct vnode*)addr[0]);
304
305     /* See also afs_osi_vget */
306     if (addr[1] == AFS_XLATOR_MAGIC)
307     {
308         if (dr->dr_status == NFS_OK) {
309             struct SmallFid Sfid;
310             struct cell *tcell;
311
312             /* Make up and copy out a SmallFid */
313             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
314             Sfid.Volume = vcp->fid.Fid.Volume;
315             Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
316                                   (vcp->fid.Fid.Unique & 0xffffff));
317             afs_PutCell(tcell, READ_LOCK);
318             Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
319             fhp->fh_len = SIZEOF_SMALLFID;
320             memcpy(dr->dr_fhandle.fh_data, (char*)&Sfid, fhp->fh_len);
321         }
322
323         /* If we have a ref, release it */
324         if (vcp->vrefCount >= 1) 
325             AFS_RELE(AFSTOV(vcp));
326     } 
327     AFS_GUNLOCK();
328 }
329
330 void
331 afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
332 {
333     resp->status = NFSERR_ACCES;
334 }
335
336 void afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
337 {
338 }
339
340 void 
341 afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
342 {
343 }
344
345 void 
346 afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
347 {
348 }
349
350 #define NFS_V2_REQ(FUNCNAME, RFSOP, POST) \
351 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
352     u_int call; \
353     struct cred *svcred = curthread->t_cred; \
354     curthread->t_cred = (struct cred*)crp; \
355     call=afs_nfs2_dispatcher(0, RFSOP, (char *)args, &exp, rp, crp); \
356     if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
357     else { (*afs_rfs_disp_tbl[RFSOP].orig_proc)(args, xp, exp, rp, crp); \
358     if (POST && afs_NFSRootOnly && call) afs_nfs2_smallfidder(xp); } \
359     curthread->t_cred = svcred; \
360     return; \
361 }
362
363 NFS_V2_REQ(afs_nfs2_getattr, RFS_GETATTR, 0) 
364 NFS_V2_REQ(afs_nfs2_setattr, RFS_SETATTR, 0)
365 NFS_V2_REQ(afs_nfs2_lookup, RFS_LOOKUP, 1)
366 NFS_V2_REQ(afs_nfs2_readlink, RFS_READLINK, 0)
367 NFS_V2_REQ(afs_nfs2_read, RFS_READ, 0)
368 NFS_V2_REQ(afs_nfs2_write, RFS_WRITE, 0)
369 NFS_V2_REQ(afs_nfs2_create, RFS_CREATE, 1)
370 NFS_V2_REQ(afs_nfs2_remove, RFS_REMOVE, 0)
371 NFS_V2_REQ(afs_nfs2_rename, RFS_RENAME, 0)
372 NFS_V2_REQ(afs_nfs2_link, RFS_LINK, 0)
373 NFS_V2_REQ(afs_nfs2_symlink, RFS_SYMLINK, 0)
374 NFS_V2_REQ(afs_nfs2_mkdir, RFS_MKDIR, 1)
375 NFS_V2_REQ(afs_nfs2_rmdir, RFS_RMDIR, 0)
376 NFS_V2_REQ(afs_nfs2_readdir, RFS_READDIR, 0)
377 NFS_V2_REQ(afs_nfs2_statfs, RFS_STATFS, 0)
378
379 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
380     { afs_nfs2_null },
381     { afs_nfs2_getattr },
382     { afs_nfs2_setattr },
383     { afs_nfs2_root },
384     { afs_nfs2_lookup },
385     { afs_nfs2_readlink },
386     { afs_nfs2_read },
387     { afs_nfs2_writecache },    
388     { afs_nfs2_write },
389     { afs_nfs2_create },
390     { afs_nfs2_remove },        
391     { afs_nfs2_rename },
392     { afs_nfs2_link },  
393     { afs_nfs2_symlink },
394     { afs_nfs2_mkdir },
395     { afs_nfs2_rmdir },
396     { afs_nfs2_readdir },
397     { afs_nfs2_statfs }
398 };
399
400 #define ACL_V2_REQ(FUNCNAME, ACLOP) \
401 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
402     u_int call; \
403     struct cred *svcred = curthread->t_cred; \
404     curthread->t_cred = (struct cred*)crp; \
405     call=afs_nfs2_dispatcher(1, ACLOP, (char *)args, &exp, rp, crp); \
406     if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
407     else (*afs_rfs_disp_tbl[ACLOP].orig_proc)(args, xp, exp, rp, crp); \
408     curthread->t_cred = svcred; \
409     return; \
410 }
411
412 ACL_V2_REQ(afs_acl2_getacl, ACLPROC2_GETACL)
413 ACL_V2_REQ(afs_acl2_setacl, ACLPROC2_SETACL)
414 ACL_V2_REQ(afs_acl2_getattr, ACLPROC2_GETATTR)
415 ACL_V2_REQ(afs_acl2_access, ACLPROC2_ACCESS)
416
417 struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC] = {
418     { afs_nfs2_null }, 
419     { afs_acl2_getacl }, 
420     { afs_acl2_setacl },
421     { afs_acl2_getattr }, 
422     { afs_acl2_access } 
423 };
424
425 /* Munge the dispatch tables to link us in first */
426 void 
427 afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl, 
428                   struct rfs_disp_tbl *_acl_tbl)
429 {
430     int i;
431
432     if (xlatorinit_v2_done++) return;
433
434     for (i=0; i < RFS_NPROC; i++) {
435         afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
436         _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
437     }
438
439     for (i=0; i < ACL2_NPROC; i++) {
440         afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
441         _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
442     }
443 }
444
445 #ifndef RFS3_NPROC
446 #define RFS3_NPROC      22
447 #endif
448
449 #ifndef ACL3_NPROC
450 #define ACL3_NPROC      3
451 #endif
452
453 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
454 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
455
456 struct afs_nfs3_resp {
457     nfsstat3 status;
458     bool_t flags; 
459 };
460 typedef struct afs_nfs3_resp afs_nfs3_resp;
461
462 static int 
463 is_afs_fh3(nfs_fh3 *fhp) {
464     if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC) &&
465         (fhp->fh3_fsid.val[1] == AFS_VFSFSID)) 
466         return 1;
467     return 0;
468 }
469
470 void
471 afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
472 {
473     resp->status = NFS3ERR_ACCES;
474     resp->flags = FALSE;
475 }
476
477 afs_int32 
478 nfs3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp, nfs_fh3 **fh2pp)
479 {
480     struct vnode *vp;
481     nfs_fh3 *fhp1=0;
482     nfs_fh3 *fhp2=0;
483     int errorcode;
484
485     *fh2pp = (nfs_fh3 *)0;
486     switch (which) {
487         case NFSPROC3_GETATTR: 
488         {
489             GETATTR3args *arg = (GETATTR3args *)args;
490             fhp1 = (nfs_fh3 *) &arg->object;
491             break;
492         } 
493         case NFSPROC3_SETATTR: 
494         {
495             SETATTR3args *arg = (SETATTR3args *)args;
496             fhp1 = (nfs_fh3 *) &arg->object;
497             break;
498         } 
499         case NFSPROC3_LOOKUP: 
500         {
501             LOOKUP3args *arg = (LOOKUP3args *)args;
502             fhp1 = (nfs_fh3 *) &arg->what.dirp;
503             break;
504         } 
505         case NFSPROC3_ACCESS: 
506         {
507             ACCESS3args *arg = (ACCESS3args *)args;
508             fhp1 = (nfs_fh3 *) &arg->object;
509             break;
510         } 
511         case NFSPROC3_READLINK: 
512         {
513             READLINK3args *arg = (READLINK3args *)args;
514             fhp1 = (nfs_fh3 *) &arg->symlink;       
515             break;
516         } 
517         case NFSPROC3_READ: 
518         {
519             READ3args *arg = (READ3args *)args;
520             fhp1 = (nfs_fh3 *) &arg->file;
521             break;
522         } 
523         case NFSPROC3_WRITE: 
524         {
525             WRITE3args *arg = (WRITE3args *)args;
526             fhp1 = (nfs_fh3 *) &arg->file;
527             break;
528         } 
529         case NFSPROC3_CREATE: 
530         {
531             CREATE3args *arg = (CREATE3args *)args;
532             fhp1 = (nfs_fh3 *) &arg->where.dir;
533             break;
534         } 
535         case NFSPROC3_MKDIR: 
536         {
537             MKDIR3args *arg = (MKDIR3args *)args;
538             fhp1 = (nfs_fh3 *) &arg->where.dir;
539             break;
540         } 
541         case NFSPROC3_SYMLINK: 
542         {
543             SYMLINK3args *arg = (SYMLINK3args *)args;
544             fhp1 = (nfs_fh3 *) &arg->where.dir;
545             break;
546         } 
547         case NFSPROC3_MKNOD:
548         {
549             MKNOD3args *arg = (MKNOD3args *)args;
550             fhp1 = (nfs_fh3 *) &arg->where.dir;
551             break;
552         } 
553         case NFSPROC3_REMOVE: 
554         {
555             REMOVE3args *arg = (REMOVE3args *)args;
556             fhp1 = (nfs_fh3 *) &arg->object.dir;
557             break;
558         } 
559         case NFSPROC3_RMDIR: 
560         {
561             RMDIR3args *arg = (RMDIR3args *)args;
562             fhp1 = (nfs_fh3 *) &arg->object.dir;
563             break;
564         } 
565         case NFSPROC3_RENAME: 
566         {
567             RENAME3args *arg = (RENAME3args *)args;
568             fhp1 = (nfs_fh3 *) &arg->from.dir;
569             fhp2 = (nfs_fh3 *) &arg->to.dir;
570             break;
571         } 
572         case NFSPROC3_LINK: 
573         {
574             LINK3args *arg = (LINK3args *)args;
575             fhp1 = (nfs_fh3 *) &arg->file;
576             fhp2 = (nfs_fh3 *) &arg->link.dir;
577             break;
578         } 
579         case NFSPROC3_READDIR: 
580         {
581             READDIR3args *arg = (READDIR3args *)args;
582             fhp1 = (nfs_fh3 *) &arg->dir;
583             break;
584         } 
585         case NFSPROC3_READDIRPLUS: 
586         {
587             READDIRPLUS3args *arg = (READDIRPLUS3args *)args;
588             fhp1 = (nfs_fh3 *) &arg->dir;
589             break;
590         } 
591         case NFSPROC3_FSSTAT: 
592         {
593             FSSTAT3args *arg = (FSSTAT3args *)args;
594             fhp1 = (nfs_fh3 *) &arg->fsroot;
595             break;
596         } 
597         case NFSPROC3_FSINFO: 
598         {
599             FSINFO3args *arg = (FSINFO3args *)args;
600             fhp1 = (nfs_fh3 *) &arg->fsroot;
601             break;
602         } 
603         case NFSPROC3_PATHCONF: 
604         {
605             PATHCONF3args *arg = (PATHCONF3args *)args;
606             fhp1 = (nfs_fh3 *) &arg->object;
607             break;
608         } 
609         case NFSPROC3_COMMIT: 
610         {
611             COMMIT3args *arg = (COMMIT3args *)args;
612             fhp1 = (nfs_fh3 *) &arg->file;
613             break;
614         }
615         default:
616             return NULL;
617     }
618
619     /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
620     if (is_afs_fh3(fhp1)) {
621         *fhpp = fhp1;
622         if (fhp2) 
623             *fh2pp = fhp2;
624         return 1;           
625     }
626     if (is_afs_fh3(fhp2)) {
627         *fhpp = fhp1;
628         *fh2pp = fhp2;
629         return 1;           
630     }
631     return NULL;
632 }
633
634 afs_int32 
635 acl3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp)
636 {
637     nfs_fh3 *fhp;
638
639     switch(which) {
640     case ACLPROC3_GETACL: 
641     {
642         struct GETACL3args *sargs = (struct GETACL3args *) args;
643         fhp = &sargs->fh;
644         break;
645     }
646     case ACLPROC3_SETACL: 
647     {
648         struct SETACL3args *sargs = (struct SETACL3args *) args;
649         fhp = &sargs->fh;
650         break;
651     }
652     default:
653         return NULL;
654     }
655
656     if (is_afs_fh3(fhp)) {
657         *fhpp = fhp;
658         return 1;
659     }
660
661     return NULL;
662 }
663
664 int
665 afs_nfs3_dispatcher(int type, afs_int32 which, char *argp, 
666                     struct exportinfo **expp, 
667                     struct svc_req *rp, struct AFS_UCRED *crp)
668 {
669     afs_int32 call = 0;
670     afs_int32 code = 0;
671     afs_int32 client = 0;
672     struct sockaddr *sa;
673     nfs_fh3 *fh = (nfs_fh3 *)argp;
674     nfs_fh3 *fh2 = (nfs_fh3 *)0;
675
676     if (!xlatorinit_v3_done)
677         return 2;
678
679     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
680     client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
681
682     AFS_GLOCK();
683     code = 0;
684     switch (type) {
685     case 0:
686         code = nfs3_to_afs_call(which, argp, &fh, &fh2);
687         break;
688     case 1:
689         code = acl3_to_afs_call(which, argp, &fh);
690         break;
691     default:
692         break;
693     }
694
695     if (code) {
696         struct afs_exporter *out = 0;
697         afs_int32 dummy;
698         static int once = 0;
699         struct SmallFid Sfid;
700
701         memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
702
703         /* We ran */
704         call = 1;
705         if (!once && *expp) {
706             afs_nobody = (*expp)->exi_export.ex_anon;
707             once = 1;
708         }
709         code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
710                                         client, &dummy, &out);
711         /* Be careful to release this */
712         if (!code && out)
713             EXP_RELE(out);
714
715         /* We ran and failed */
716         if (code == EINVAL) 
717             call = 2;
718     }
719
720     AFS_GUNLOCK();
721     return call;
722 }
723
724 void 
725 afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
726 {
727     afs_int32 addr[2];
728     struct vcache *vcp;
729
730 #if defined(AFS_SUN57_64BIT_ENV)
731     /* See also afs_fid() */    
732     memcpy((char *)addr, fhp->fh3_data, 10);
733     addr[1] = (addr[1] >> 48) & 0xffff;
734 #else 
735     memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
736 #endif
737
738     AFS_GLOCK();
739     vcp = VTOAFS((struct vnode*)addr[0]);
740
741     /* See also afs_osi_vget */
742     if (addr[1] == AFS_XLATOR_MAGIC)
743     {
744         if (status == NFS_OK) {
745             struct SmallFid Sfid;
746             struct cell *tcell;
747
748             /* Make up and copy out a SmallFid */
749             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
750             Sfid.Volume = vcp->fid.Fid.Volume;
751             Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
752                                   (vcp->fid.Fid.Unique & 0xffffff));
753             afs_PutCell(tcell, READ_LOCK);
754             Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
755             fhp->fh3_len = SIZEOF_SMALLFID;
756             memcpy(fhp->fh3_data, (char*)&Sfid, fhp->fh3_len);
757         }
758
759         /* If we have a ref, release it */
760         if (vcp->vrefCount >= 1) 
761             AFS_RELE(AFSTOV(vcp));
762     } 
763     AFS_GUNLOCK();
764 }
765
766 #define NFS_V3_REQ(FUNCNAME, NFSOP, POST, RESP, RESPP) \
767 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
768     u_int call; \
769     afs_nfs3_resp dummy; \
770     struct cred *svcred = curthread->t_cred; \
771     curthread->t_cred = (struct cred*)crp; \
772     call=afs_nfs3_dispatcher(0, NFSOP, (char *)args, &exp, rp, crp); \
773     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
774     else { (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
775     if (POST && afs_NFSRootOnly && call) { \
776     RESP *resp = ( RESP *)xp; \
777     afs_nfs3_smallfidder( RESPP , resp->status); } } \
778     curthread->t_cred = svcred; \
779     return; \
780 }
781
782 NFS_V3_REQ(afs_nfs3_getattr, NFSPROC3_GETATTR, 0, afs_nfs3_resp, &dummy) 
783 NFS_V3_REQ(afs_nfs3_setattr, NFSPROC3_SETATTR, 0, afs_nfs3_resp, &dummy)
784 NFS_V3_REQ(afs_nfs3_lookup, NFSPROC3_LOOKUP, 1, LOOKUP3res, &resp->resok.object)
785 NFS_V3_REQ(afs_nfs3_access, NFSPROC3_ACCESS, 0, afs_nfs3_resp, &dummy)
786 NFS_V3_REQ(afs_nfs3_readlink, NFSPROC3_READLINK, 0, afs_nfs3_resp, &dummy)
787 NFS_V3_REQ(afs_nfs3_read, NFSPROC3_READ, 0, afs_nfs3_resp, &dummy)
788 NFS_V3_REQ(afs_nfs3_write, NFSPROC3_WRITE, 0, afs_nfs3_resp, &dummy)
789 NFS_V3_REQ(afs_nfs3_create, NFSPROC3_CREATE, 1, CREATE3res, &resp->resok.obj.handle)
790 NFS_V3_REQ(afs_nfs3_mkdir, NFSPROC3_MKDIR, 1, MKDIR3res, &resp->resok.obj.handle)
791 NFS_V3_REQ(afs_nfs3_symlink, NFSPROC3_SYMLINK, 0, afs_nfs3_resp, &dummy)
792 NFS_V3_REQ(afs_nfs3_mknod, NFSPROC3_MKNOD, 0, afs_nfs3_resp, &dummy)
793 NFS_V3_REQ(afs_nfs3_remove, NFSPROC3_REMOVE, 0, afs_nfs3_resp, &dummy)
794 NFS_V3_REQ(afs_nfs3_rmdir, NFSPROC3_RMDIR, 0, afs_nfs3_resp, &dummy)
795 NFS_V3_REQ(afs_nfs3_rename, NFSPROC3_RENAME, 0, afs_nfs3_resp, &dummy)
796 NFS_V3_REQ(afs_nfs3_link, NFSPROC3_LINK, 0, afs_nfs3_resp, &dummy)
797 NFS_V3_REQ(afs_nfs3_readdir, NFSPROC3_READDIR, 0, afs_nfs3_resp, &dummy)
798 NFS_V3_REQ(afs_nfs3_readdirplus, NFSPROC3_READDIRPLUS, 0, afs_nfs3_resp, &dummy)
799 NFS_V3_REQ(afs_nfs3_fsstat, NFSPROC3_FSSTAT, 0, afs_nfs3_resp, &dummy)
800 NFS_V3_REQ(afs_nfs3_fsinfo, NFSPROC3_FSINFO, 0, afs_nfs3_resp, &dummy)
801 NFS_V3_REQ(afs_nfs3_pathconf, NFSPROC3_PATHCONF, 0, afs_nfs3_resp, &dummy)
802 NFS_V3_REQ(afs_nfs3_commit, NFSPROC3_COMMIT, 0, afs_nfs3_resp, &dummy)
803
804 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC] = {
805     { afs_nfs2_null },
806     { afs_nfs3_getattr },
807     { afs_nfs3_setattr },
808     { afs_nfs3_lookup },
809     { afs_nfs3_access },
810     { afs_nfs3_readlink },
811     { afs_nfs3_read },
812     { afs_nfs3_write },
813     { afs_nfs3_create },
814     { afs_nfs3_mkdir },
815     { afs_nfs3_symlink },
816     { afs_nfs3_mknod },
817     { afs_nfs3_remove },        
818     { afs_nfs3_rmdir },
819     { afs_nfs3_rename },
820     { afs_nfs3_link },  
821     { afs_nfs3_readdir },
822     { afs_nfs3_readdirplus },
823     { afs_nfs3_fsstat },
824     { afs_nfs3_fsinfo },
825     { afs_nfs3_pathconf },
826     { afs_nfs3_commit }
827 };
828
829 #define ACL_V3_REQ(FUNCNAME, NFSOP) \
830 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
831     u_int call; \
832     struct cred *svcred = curthread->t_cred; \
833     curthread->t_cred = (struct cred*)crp; \
834     call=afs_nfs3_dispatcher(1, NFSOP, (char *)args, &exp, rp, crp); \
835     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
836     else (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
837     curthread->t_cred = svcred; \
838     return; \
839 }
840
841 ACL_V3_REQ(afs_acl3_getacl, ACLPROC3_GETACL)
842 ACL_V3_REQ(afs_acl3_setacl, ACLPROC3_SETACL)
843
844 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC] = {
845     { afs_nfs2_null }, 
846     { afs_acl3_getacl }, 
847     { afs_acl3_setacl },
848 };
849
850 /* Munge the dispatch tables to link us in first */
851 void 
852 afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl, 
853                   struct rfs_disp_tbl *_acl_tbl)
854 {
855     int i;
856
857     if (xlatorinit_v3_done++) return;
858
859     for (i=0; i < RFS3_NPROC; i++) {
860         afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
861         _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
862     }
863
864     for (i=0; i < ACL3_NPROC; i++) {
865         afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
866         _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
867     }
868 }
869 #endif /* !defined(AFS_NONFSTRANS) */