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