solaris10-nfs-trans-update-20051007
[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
14     ("$Header$");
15
16 /* Ugly Ugly Ugly  but precludes conflicting XDR macros; We want kernel xdr */
17 #define __XDR_INCLUDE__
18 #include "afs/stds.h"
19 #include "afs/sysincludes.h"    /* Standard vendor system headers */
20 #if defined(AFS_SUN55_ENV) && !defined(AFS_NONFSTRANS)
21 #include "rpc/types.h"
22 #include "rpc/auth.h"
23 #include "rpc/auth_unix.h"
24 #include "rpc/auth_des.h"
25 #if !defined(AFS_SUN58_ENV)
26 #include "rpc/auth_kerb.h"
27 #endif
28 #include "sys/tiuser.h"
29 #include "rpc/xdr.h"
30 #include "rpc/svc.h"
31 #include "nfs/nfs.h"
32 #include "nfs/export.h"
33 #include "nfs/nfs_clnt.h"
34 #include "nfs/nfs_acl.h"
35 #include "afs/afsincludes.h"
36 #include "afs/afs_stats.h"
37 #include "afs/exporter.h"
38
39 static int xlatorinit_v2_done = 0;
40 static int xlatorinit_v3_done = 0;
41 extern int afs_nobody;
42 extern int afs_NFSRootOnly;
43
44 struct rfs_disp_tbl {
45     void (*dis_proc) ();
46     xdrproc_t dis_xdrargs;
47     xdrproc_t dis_fastxdrargs;
48     int dis_argsz;
49     xdrproc_t dis_xdrres;
50     xdrproc_t dis_fastxdrres;
51     int dis_ressz;
52     void (*dis_resfree) ();
53     int dis_flags;
54       fhandle_t(*dis_getfh) ();
55 };
56
57 struct afs_nfs_disp_tbl {
58     void (*afs_proc) ();
59     void (*orig_proc) ();
60 };
61 struct afs_nfs2_resp {
62     enum nfsstat status;
63 };
64
65 #ifndef ACL2_NPROC
66 #define ACL2_NPROC      5
67 #endif
68 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC];
69 struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC];
70
71 static int
72 is_afs_fh(fhandle_t * fhp)
73 {
74     if ((fhp->fh_fsid.val[0] == AFS_VFSMAGIC)
75         && (fhp->fh_fsid.val[1] == AFS_VFSFSID))
76         return 1;
77     return 0;
78 }
79
80 afs_int32
81 nfs2_to_afs_call(int which, caddr_t * args, fhandle_t ** fhpp,
82                  fhandle_t ** fh2pp)
83 {
84     struct vnode *vp;
85     fhandle_t *fhp1 = 0;
86     fhandle_t *fhp2 = 0;
87     int errorcode;
88
89     afs_Trace1(afs_iclSetp, CM_TRACE_NFSIN, ICL_TYPE_INT32, which);
90     *fh2pp = (fhandle_t *) 0;
91     switch (which) {
92     case RFS_GETATTR:
93     case RFS_READLINK:
94     case RFS_STATFS:
95         fhp1 = (fhandle_t *) args;
96         break;
97     case RFS_SETATTR:
98         {
99             struct nfssaargs *sargs = (struct nfssaargs *)args;
100             fhp1 = (fhandle_t *) & sargs->saa_fh;
101             break;
102         }
103     case RFS_LOOKUP:
104         {
105             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
106             fhp1 = sargs->da_fhandle;
107             break;
108         }
109     case RFS_READ:
110         {
111             struct nfsreadargs *sargs = (struct nfsreadargs *)args;
112             fhp1 = (fhandle_t *) & sargs->ra_fhandle;
113             break;
114         }
115     case RFS_WRITE:
116         {
117             struct nfswriteargs *sargs = (struct nfswriteargs *)args;
118             fhp1 = (fhandle_t *) & sargs->wa_fhandle;
119             break;
120         }
121     case RFS_CREATE:
122         {
123             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
124             fhp1 = sargs->ca_da.da_fhandle;
125             break;
126         }
127     case RFS_REMOVE:
128         {
129             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
130             fhp1 = sargs->da_fhandle;
131             break;
132         }
133     case RFS_RENAME:
134         {
135             struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
136             fhp1 = sargs->rna_from.da_fhandle;
137             fhp2 = sargs->rna_to.da_fhandle;
138             break;
139         }
140     case RFS_LINK:
141         {
142             struct nfslinkargs *sargs = (struct nfslinkargs *)args;
143             fhp1 = sargs->la_from;
144             fhp2 = sargs->la_to.da_fhandle;
145             break;
146         }
147     case RFS_SYMLINK:
148         {
149             struct nfsslargs *sargs = (struct nfsslargs *)args;
150             fhp1 = sargs->sla_from.da_fhandle;
151             break;
152         }
153     case RFS_MKDIR:
154         {
155             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
156             fhp1 = sargs->ca_da.da_fhandle;
157             break;
158         }
159     case RFS_RMDIR:
160         {
161             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
162             fhp1 = sargs->da_fhandle;
163             break;
164         }
165     case RFS_READDIR:
166         {
167             struct nfsrddirargs *sargs = (struct nfsrddirargs *)args;
168             fhp1 = (fhandle_t *) & sargs->rda_fh;
169             break;
170         }
171     default:
172         return NULL;
173     }
174
175     /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
176     if (is_afs_fh(fhp1)) {
177         *fhpp = fhp1;
178         if (fhp2)
179             *fh2pp = fhp2;
180         return 1;
181     }
182     if (fhp2 && is_afs_fh(fhp2)) {
183         *fhpp = fhp1;
184         *fh2pp = fhp2;
185         return 1;
186     }
187     return NULL;
188 }
189
190 afs_int32
191 acl2_to_afs_call(int which, caddr_t * args, fhandle_t ** fhpp)
192 {
193     fhandle_t *fhp;
194
195     switch (which) {
196     case ACLPROC2_NULL:
197         {
198             return NULL;
199         }
200     case ACLPROC2_GETACL:
201         {
202             struct GETACL2args *sargs = (struct GETACL2args *)args;
203             fhp = &sargs->fh;
204             break;
205         }
206     case ACLPROC2_SETACL:
207         {
208             struct SETACL2args *sargs = (struct SETACL2args *)args;
209             fhp = &sargs->fh;
210             break;
211         }
212     case ACLPROC2_GETATTR:
213         {
214             struct GETATTR2args *sargs = (struct GETATTR2args *)args;
215             fhp = &sargs->fh;
216             break;
217         }
218     case ACLPROC2_ACCESS:
219         {
220             struct ACCESS2args *sargs = (struct ACCESS2args *)args;
221             fhp = &sargs->fh;
222             break;
223         }
224 #if defined(AFS_SUN510_ENV) 
225     case ACLPROC2_GETXATTRDIR:
226         {
227             struct GETXATTRDIR2args *sargs = (struct GETXATTRDIR2args *)args;
228             fhp = &sargs->fh;
229             break;
230         }
231 #endif
232     default:
233         return NULL;
234     }
235
236     if (is_afs_fh(fhp)) {
237         *fhpp = fhp;
238         return 1;
239     }
240
241     return NULL;
242 }
243
244 int
245 afs_nfs2_dispatcher(int type, afs_int32 which, char *argp,
246                     struct exportinfo **expp, struct svc_req *rp,
247                     struct AFS_UCRED *crp)
248 {
249     afs_int32 call = 0;
250     afs_int32 code = 0;
251     afs_int32 client = 0;
252     struct sockaddr *sa;
253     fhandle_t *fh = (fhandle_t *) argp;
254     fhandle_t *fh2 = (fhandle_t *) 0;
255
256     if (!xlatorinit_v2_done)
257         return 2;
258
259     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
260     if (sa->sa_family == AF_INET)
261         client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
262
263     AFS_GLOCK();
264     code = 0;
265     switch (type) {
266     case 0:
267         code = (client && nfs2_to_afs_call(which, argp, &fh, &fh2));
268         break;
269     case 1:
270         code = (client && acl2_to_afs_call(which, argp, &fh));
271         break;
272     default:
273         break;
274     }
275
276     if (code) {
277         struct afs_exporter *out = 0;
278         afs_int32 dummy;
279         static int once = 0;
280         struct SmallFid Sfid;
281
282         memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
283
284         afs_Trace2(afs_iclSetp, CM_TRACE_NFSIN1, ICL_TYPE_POINTER, client,
285                    ICL_TYPE_FID, &Sfid);
286
287         /* We ran */
288         call = 1;
289         if (!once && *expp) {
290             afs_nobody = (*expp)->exi_export.ex_anon;
291             once = 1;
292         }
293         code =
294             afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
295                                      &dummy, &out);
296
297         if (!code && out)
298             EXP_RELE(out);
299
300         if (code == EINVAL)
301             call = 2;
302     }
303
304     AFS_GUNLOCK();
305     return call;
306 }
307
308 void
309 afs_nfs2_smallfidder(struct nfsdiropres *dr)
310 {
311     register fhandle_t *fhp = (fhandle_t *) & dr->dr_fhandle;
312     afs_int32 addr[2];
313     struct vcache *vcp;
314
315 #if defined(AFS_SUN57_64BIT_ENV)
316     /* See also afs_fid() */
317     memcpy((char *)addr, fhp->fh_data, SIZEOF_SMALLFID);
318     addr[1] = (addr[1] >> 48) & 0xffff;
319 #else
320     memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
321 #endif
322
323     AFS_GLOCK();
324     vcp = VTOAFS((struct vnode *)addr[0]);
325
326     if (addr[1] == AFS_XLATOR_MAGIC) {
327         if (dr->dr_status == NFS_OK) {
328             struct SmallFid Sfid;
329             struct cell *tcell;
330
331             /* Make up and copy out a SmallFid */
332             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
333             Sfid.Volume = vcp->fid.Fid.Volume;
334             Sfid.CellAndUnique =
335                 ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
336             afs_PutCell(tcell, READ_LOCK);
337             Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
338             fhp->fh_len = SIZEOF_SMALLFID;
339             memcpy(dr->dr_fhandle.fh_data, (char *)&Sfid, fhp->fh_len);
340
341             afs_Trace3(afs_iclSetp, CM_TRACE_NFSOUT, ICL_TYPE_INT32, 0,
342                        ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
343         }
344
345         /* If we have a ref, release it */
346         if (vcp->vrefCount >= 1)
347             AFS_RELE(AFSTOV(vcp));
348     }
349     AFS_GUNLOCK();
350 }
351
352 void
353 afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
354 {
355     resp->status = NFSERR_ACCES;
356 }
357
358 void
359 afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
360 {
361 }
362
363 void
364 afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
365 {
366 }
367
368 void
369 afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
370 {
371 }
372
373 void
374 afs_nfs2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
375 {
376     u_int call;
377     struct cred *svcred = curthread->t_cred;
378     curthread->t_cred = (struct cred *)crp;
379     call = afs_nfs2_dispatcher(0, RFS_GETATTR, (char *)args, &exp, rp, crp);
380     if (call > 1)
381         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
382     else
383         (*afs_rfs_disp_tbl[RFS_GETATTR].orig_proc) (args, xp, exp, rp, crp);
384     curthread->t_cred = svcred;
385     return;
386 }
387
388 void
389 afs_nfs2_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
390 {
391     u_int call;
392     struct cred *svcred = curthread->t_cred;
393     curthread->t_cred = (struct cred *)crp;
394     call = afs_nfs2_dispatcher(0, RFS_SETATTR, (char *)args, &exp, rp, crp);
395     if (call > 1)
396         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
397     else
398         (*afs_rfs_disp_tbl[RFS_SETATTR].orig_proc) (args, xp, exp, rp, crp);
399     curthread->t_cred = svcred;
400     return;
401 }
402
403 void
404 afs_nfs2_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
405 {
406     u_int call;
407     struct cred *svcred = curthread->t_cred;
408     curthread->t_cred = (struct cred *)crp;
409     call = afs_nfs2_dispatcher(0, RFS_LOOKUP, (char *)args, &exp, rp, crp);
410     if (call > 1)
411         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
412     else {
413         (*afs_rfs_disp_tbl[RFS_LOOKUP].orig_proc) (args, xp, exp, rp, crp);
414         if (afs_NFSRootOnly && call)
415             afs_nfs2_smallfidder(xp);
416     }
417     curthread->t_cred = svcred;
418     return;
419 }
420
421 void
422 afs_nfs2_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
423 {
424     u_int call;
425     struct cred *svcred = curthread->t_cred;
426     curthread->t_cred = (struct cred *)crp;
427     call = afs_nfs2_dispatcher(0, RFS_READLINK, (char *)args, &exp, rp, crp);
428     if (call > 1)
429         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
430     else
431         (*afs_rfs_disp_tbl[RFS_READLINK].orig_proc) (args, xp, exp, rp, crp);
432     curthread->t_cred = svcred;
433     return;
434 }
435
436 void
437 afs_nfs2_read(char *args, char *xp, char *exp, char *rp, char *crp)
438 {
439     u_int call;
440     struct cred *svcred = curthread->t_cred;
441     curthread->t_cred = (struct cred *)crp;
442     call = afs_nfs2_dispatcher(0, RFS_READ, (char *)args, &exp, rp, crp);
443     if (call > 1)
444         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
445     else
446         (*afs_rfs_disp_tbl[RFS_READ].orig_proc) (args, xp, exp, rp, crp);
447     curthread->t_cred = svcred;
448     return;
449 }
450
451 void
452 afs_nfs2_write(char *args, char *xp, char *exp, char *rp, char *crp)
453 {
454     u_int call;
455     struct cred *svcred = curthread->t_cred;
456     curthread->t_cred = (struct cred *)crp;
457     call = afs_nfs2_dispatcher(0, RFS_WRITE, (char *)args, &exp, rp, crp);
458     if (call > 1)
459         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
460     else
461         (*afs_rfs_disp_tbl[RFS_WRITE].orig_proc) (args, xp, exp, rp, crp);
462     curthread->t_cred = svcred;
463     return;
464 }
465
466 void
467 afs_nfs2_create(char *args, char *xp, char *exp, char *rp, char *crp)
468 {
469     u_int call;
470     struct cred *svcred = curthread->t_cred;
471     curthread->t_cred = (struct cred *)crp;
472     call = afs_nfs2_dispatcher(0, RFS_CREATE, (char *)args, &exp, rp, crp);
473     if (call > 1)
474         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
475     else {
476         (*afs_rfs_disp_tbl[RFS_CREATE].orig_proc) (args, xp, exp, rp, crp);
477         if (afs_NFSRootOnly && call)
478             afs_nfs2_smallfidder(xp);
479     }
480     curthread->t_cred = svcred;
481     return;
482 }
483
484 void
485 afs_nfs2_remove(char *args, char *xp, char *exp, char *rp, char *crp)
486 {
487     u_int call;
488     struct cred *svcred = curthread->t_cred;
489     curthread->t_cred = (struct cred *)crp;
490     call = afs_nfs2_dispatcher(0, RFS_REMOVE, (char *)args, &exp, rp, crp);
491     if (call > 1)
492         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
493     else
494         (*afs_rfs_disp_tbl[RFS_REMOVE].orig_proc) (args, xp, exp, rp, crp);
495     curthread->t_cred = svcred;
496     return;
497 }
498
499 void
500 afs_nfs2_rename(char *args, char *xp, char *exp, char *rp, char *crp)
501 {
502     u_int call;
503     struct cred *svcred = curthread->t_cred;
504     curthread->t_cred = (struct cred *)crp;
505     call = afs_nfs2_dispatcher(0, RFS_RENAME, (char *)args, &exp, rp, crp);
506     if (call > 1)
507         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
508     else
509         (*afs_rfs_disp_tbl[RFS_RENAME].orig_proc) (args, xp, exp, rp, crp);
510     curthread->t_cred = svcred;
511     return;
512 }
513
514 void
515 afs_nfs2_link(char *args, char *xp, char *exp, char *rp, char *crp)
516 {
517     u_int call;
518     struct cred *svcred = curthread->t_cred;
519     curthread->t_cred = (struct cred *)crp;
520     call = afs_nfs2_dispatcher(0, RFS_LINK, (char *)args, &exp, rp, crp);
521     if (call > 1)
522         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
523     else
524         (*afs_rfs_disp_tbl[RFS_LINK].orig_proc) (args, xp, exp, rp, crp);
525     curthread->t_cred = svcred;
526     return;
527 }
528
529 void
530 afs_nfs2_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
531 {
532     u_int call;
533     struct cred *svcred = curthread->t_cred;
534     curthread->t_cred = (struct cred *)crp;
535     call = afs_nfs2_dispatcher(0, RFS_SYMLINK, (char *)args, &exp, rp, crp);
536     if (call > 1)
537         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
538     else
539         (*afs_rfs_disp_tbl[RFS_SYMLINK].orig_proc) (args, xp, exp, rp, crp);
540     curthread->t_cred = svcred;
541     return;
542 }
543
544 void
545 afs_nfs2_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
546 {
547     u_int call;
548     struct cred *svcred = curthread->t_cred;
549     curthread->t_cred = (struct cred *)crp;
550     call = afs_nfs2_dispatcher(0, RFS_MKDIR, (char *)args, &exp, rp, crp);
551     if (call > 1)
552         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
553     else {
554         (*afs_rfs_disp_tbl[RFS_MKDIR].orig_proc) (args, xp, exp, rp, crp);
555         if (afs_NFSRootOnly && call)
556             afs_nfs2_smallfidder(xp);
557     }
558     curthread->t_cred = svcred;
559     return;
560 }
561
562 void
563 afs_nfs2_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
564 {
565     u_int call;
566     struct cred *svcred = curthread->t_cred;
567     curthread->t_cred = (struct cred *)crp;
568     call = afs_nfs2_dispatcher(0, RFS_RMDIR, (char *)args, &exp, rp, crp);
569     if (call > 1)
570         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
571     else
572         (*afs_rfs_disp_tbl[RFS_RMDIR].orig_proc) (args, xp, exp, rp, crp);
573     curthread->t_cred = svcred;
574     return;
575 }
576
577 void
578 afs_nfs2_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
579 {
580     u_int call;
581     struct cred *svcred = curthread->t_cred;
582     curthread->t_cred = (struct cred *)crp;
583     call = afs_nfs2_dispatcher(0, RFS_READDIR, (char *)args, &exp, rp, crp);
584     if (call > 1)
585         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
586     else
587         (*afs_rfs_disp_tbl[RFS_READDIR].orig_proc) (args, xp, exp, rp, crp);
588     curthread->t_cred = svcred;
589     return;
590 }
591
592 void
593 afs_nfs2_statfs(char *args, char *xp, char *exp, char *rp, char *crp)
594 {
595     u_int call;
596     struct cred *svcred = curthread->t_cred;
597     curthread->t_cred = (struct cred *)crp;
598     call = afs_nfs2_dispatcher(0, RFS_STATFS, (char *)args, &exp, rp, crp);
599     if (call > 1)
600         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
601     else
602         (*afs_rfs_disp_tbl[RFS_STATFS].orig_proc) (args, xp, exp, rp, crp);
603     curthread->t_cred = svcred;
604     return;
605 }
606
607 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
608     {afs_nfs2_null},
609     {afs_nfs2_getattr},
610     {afs_nfs2_setattr},
611     {afs_nfs2_root},
612     {afs_nfs2_lookup},
613     {afs_nfs2_readlink},
614     {afs_nfs2_read},
615     {afs_nfs2_writecache},
616     {afs_nfs2_write},
617     {afs_nfs2_create},
618     {afs_nfs2_remove},
619     {afs_nfs2_rename},
620     {afs_nfs2_link},
621     {afs_nfs2_symlink},
622     {afs_nfs2_mkdir},
623     {afs_nfs2_rmdir},
624     {afs_nfs2_readdir},
625     {afs_nfs2_statfs}
626 };
627
628 void
629 afs_acl2_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
630 {
631     u_int call;
632     struct cred *svcred = curthread->t_cred;
633     curthread->t_cred = (struct cred *)crp;
634     call =
635         afs_nfs2_dispatcher(1, ACLPROC2_GETACL, (char *)args, &exp, rp, crp);
636     if (call > 1)
637         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
638     else
639         (*afs_acl_disp_tbl[ACLPROC2_GETACL].orig_proc) (args, xp, exp, rp,
640                                                         crp);
641     curthread->t_cred = svcred;
642     return;
643 }
644
645 void
646 afs_acl2_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
647 {
648     u_int call;
649     struct cred *svcred = curthread->t_cred;
650     curthread->t_cred = (struct cred *)crp;
651     call =
652         afs_nfs2_dispatcher(1, ACLPROC2_SETACL, (char *)args, &exp, rp, crp);
653     if (call > 1)
654         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
655     else
656         (*afs_acl_disp_tbl[ACLPROC2_SETACL].orig_proc) (args, xp, exp, rp,
657                                                         crp);
658     curthread->t_cred = svcred;
659     return;
660 }
661
662 void
663 afs_acl2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
664 {
665     u_int call;
666     struct cred *svcred = curthread->t_cred;
667     curthread->t_cred = (struct cred *)crp;
668     call =
669         afs_nfs2_dispatcher(1, ACLPROC2_GETATTR, (char *)args, &exp, rp, crp);
670     if (call > 1)
671         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
672     else
673         (*afs_acl_disp_tbl[ACLPROC2_GETATTR].orig_proc) (args, xp, exp, rp,
674                                                          crp);
675     curthread->t_cred = svcred;
676     return;
677 }
678
679 void
680 afs_acl2_access(char *args, char *xp, char *exp, char *rp, char *crp)
681 {
682     u_int call;
683     struct cred *svcred = curthread->t_cred;
684     curthread->t_cred = (struct cred *)crp;
685     call =
686         afs_nfs2_dispatcher(1, ACLPROC2_ACCESS, (char *)args, &exp, rp, crp);
687     if (call > 1)
688         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
689     else
690         (*afs_acl_disp_tbl[ACLPROC2_ACCESS].orig_proc) (args, xp, exp, rp,
691                                                         crp);
692     curthread->t_cred = svcred;
693     return;
694 }
695
696 #if defined(AFS_SUN510_ENV) 
697 void
698 afs_acl2_getxattrdir(char *args, char *xp, char *exp, char *rp, char *crp)
699 {
700     u_int call;
701     struct cred *svcred = curthread->t_cred;
702     curthread->t_cred = (struct cred *)crp;
703     call =
704         afs_nfs2_dispatcher(1, ACLPROC2_GETXATTRDIR, (char *)args, &exp, rp, crp);
705     if (call > 1)
706         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
707     else
708         (*afs_acl_disp_tbl[ACLPROC2_GETXATTRDIR].orig_proc) (args, xp, exp, rp,
709                                                         crp);
710     curthread->t_cred = svcred;
711     return;
712 }
713 #endif
714
715 struct afs_nfs_disp_tbl afs_acl_disp_tbl[5] = {
716     {afs_nfs2_null},
717     {afs_acl2_getacl},
718     {afs_acl2_setacl},
719     {afs_acl2_getattr},
720     {afs_acl2_access},
721 #if defined(AFS_SUN510_ENV) 
722     {afs_acl2_getxattrdir}
723 #endif
724 };
725
726 /* Munge the dispatch tables to link us in first */
727 void
728 afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl,
729                   struct rfs_disp_tbl *_acl_tbl)
730 {
731     int i;
732
733     if (xlatorinit_v2_done++)
734         return;
735
736     for (i = 0; i < RFS_NPROC; i++) {
737         afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
738         _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
739     }
740
741     for (i = 0; i < 5; i++) {
742         afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
743         _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
744     }
745 }
746
747 #ifndef RFS3_NPROC
748 #define RFS3_NPROC      22
749 #endif
750
751 #ifndef ACL3_NPROC
752 #define ACL3_NPROC      3
753 #endif
754
755 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
756 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
757
758 struct afs_nfs3_resp {
759     nfsstat3 status;
760     bool_t flags;
761 };
762 typedef struct afs_nfs3_resp afs_nfs3_resp;
763
764 static int
765 is_afs_fh3(nfs_fh3 * fhp)
766 {
767     if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC)
768         && (fhp->fh3_fsid.val[1] == AFS_VFSFSID))
769         return 1;
770     return 0;
771 }
772
773 void
774 afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
775 {
776     resp->status = NFS3ERR_ACCES;
777     resp->flags = FALSE;
778 }
779
780 void
781 afs_nfs3_notsupp(struct afs_nfs3_resp *resp)
782 {
783     resp->status = NFS3ERR_NOTSUPP;
784     resp->flags = FALSE;
785 }
786
787 afs_int32
788 nfs3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp, nfs_fh3 ** fh2pp)
789 {
790     struct vnode *vp;
791     nfs_fh3 *fhp1 = 0;
792     nfs_fh3 *fhp2 = 0;
793     int errorcode;
794
795     afs_Trace1(afs_iclSetp, CM_TRACE_NFS3IN, ICL_TYPE_INT32, which);
796     *fh2pp = (nfs_fh3 *) 0;
797     switch (which) {
798     case NFSPROC3_GETATTR:
799         {
800             GETATTR3args *arg = (GETATTR3args *) args;
801             fhp1 = (nfs_fh3 *) & arg->object;
802             break;
803         }
804     case NFSPROC3_SETATTR:
805         {
806             SETATTR3args *arg = (SETATTR3args *) args;
807             fhp1 = (nfs_fh3 *) & arg->object;
808             break;
809         }
810     case NFSPROC3_LOOKUP:
811         {
812             LOOKUP3args *arg = (LOOKUP3args *) args;
813 #ifdef AFS_SUN58_ENV
814             fhp1 = (nfs_fh3 *) arg->what.dirp;
815 #else
816             fhp1 = (nfs_fh3 *) & arg->what.dir;
817 #endif
818             break;
819         }
820     case NFSPROC3_ACCESS:
821         {
822             ACCESS3args *arg = (ACCESS3args *) args;
823             fhp1 = (nfs_fh3 *) & arg->object;
824             break;
825         }
826     case NFSPROC3_READLINK:
827         {
828             READLINK3args *arg = (READLINK3args *) args;
829             fhp1 = (nfs_fh3 *) & arg->symlink;
830             break;
831         }
832     case NFSPROC3_READ:
833         {
834             READ3args *arg = (READ3args *) args;
835             fhp1 = (nfs_fh3 *) & arg->file;
836             break;
837         }
838     case NFSPROC3_WRITE:
839         {
840             WRITE3args *arg = (WRITE3args *) args;
841             fhp1 = (nfs_fh3 *) & arg->file;
842             break;
843         }
844     case NFSPROC3_CREATE:
845         {
846             CREATE3args *arg = (CREATE3args *) args;
847 #ifdef AFS_SUN58_ENV
848             fhp1 = (nfs_fh3 *) arg->where.dirp;
849 #else
850             fhp1 = (nfs_fh3 *) & arg->where.dir;
851 #endif
852             break;
853         }
854     case NFSPROC3_MKDIR:
855         {
856             MKDIR3args *arg = (MKDIR3args *) args;
857 #ifdef AFS_SUN58_ENV
858             fhp1 = (nfs_fh3 *) arg->where.dirp;
859 #else
860             fhp1 = (nfs_fh3 *) & arg->where.dir;
861 #endif
862             break;
863         }
864     case NFSPROC3_SYMLINK:
865         {
866             SYMLINK3args *arg = (SYMLINK3args *) args;
867 #ifdef AFS_SUN58_ENV
868             fhp1 = (nfs_fh3 *) arg->where.dirp;
869 #else
870             fhp1 = (nfs_fh3 *) & arg->where.dir;
871 #endif
872             break;
873         }
874     case NFSPROC3_MKNOD:
875         {
876             MKNOD3args *arg = (MKNOD3args *) args;
877 #ifdef AFS_SUN58_ENV
878             fhp1 = (nfs_fh3 *) arg->where.dirp;
879 #else
880             fhp1 = (nfs_fh3 *) & arg->where.dir;
881 #endif
882             break;
883         }
884     case NFSPROC3_REMOVE:
885         {
886             REMOVE3args *arg = (REMOVE3args *) args;
887 #ifdef AFS_SUN58_ENV
888             fhp1 = (nfs_fh3 *) arg->object.dirp;
889 #else
890             fhp1 = (nfs_fh3 *) & arg->object.dir;
891 #endif
892             break;
893         }
894     case NFSPROC3_RMDIR:
895         {
896             RMDIR3args *arg = (RMDIR3args *) args;
897 #ifdef AFS_SUN58_ENV
898             fhp1 = (nfs_fh3 *) arg->object.dirp;
899 #else
900             fhp1 = (nfs_fh3 *) & arg->object.dir;
901 #endif
902             break;
903         }
904     case NFSPROC3_RENAME:
905         {
906             RENAME3args *arg = (RENAME3args *) args;
907 #ifdef AFS_SUN58_ENV
908             fhp1 = (nfs_fh3 *) arg->from.dirp;
909             fhp2 = (nfs_fh3 *) arg->to.dirp;
910 #else
911             fhp1 = (nfs_fh3 *) & arg->from.dir;
912             fhp2 = (nfs_fh3 *) & arg->to.dir;
913 #endif
914             break;
915         }
916     case NFSPROC3_LINK:
917         {
918             LINK3args *arg = (LINK3args *) args;
919             fhp1 = (nfs_fh3 *) & arg->file;
920 #ifdef AFS_SUN58_ENV
921             fhp2 = (nfs_fh3 *) arg->link.dirp;
922 #else
923             fhp2 = (nfs_fh3 *) & arg->link.dir;
924 #endif
925             break;
926         }
927     case NFSPROC3_READDIR:
928         {
929             READDIR3args *arg = (READDIR3args *) args;
930             fhp1 = (nfs_fh3 *) & arg->dir;
931             break;
932         }
933     case NFSPROC3_READDIRPLUS:
934         {
935             READDIRPLUS3args *arg = (READDIRPLUS3args *) args;
936             fhp1 = (nfs_fh3 *) & arg->dir;
937             break;
938         }
939     case NFSPROC3_FSSTAT:
940         {
941             FSSTAT3args *arg = (FSSTAT3args *) args;
942             fhp1 = (nfs_fh3 *) & arg->fsroot;
943             break;
944         }
945     case NFSPROC3_FSINFO:
946         {
947             FSINFO3args *arg = (FSINFO3args *) args;
948             fhp1 = (nfs_fh3 *) & arg->fsroot;
949             break;
950         }
951     case NFSPROC3_PATHCONF:
952         {
953             PATHCONF3args *arg = (PATHCONF3args *) args;
954             fhp1 = (nfs_fh3 *) & arg->object;
955             break;
956         }
957     case NFSPROC3_COMMIT:
958         {
959             COMMIT3args *arg = (COMMIT3args *) args;
960             fhp1 = (nfs_fh3 *) & arg->file;
961             break;
962         }
963     default:
964         return NULL;
965     }
966
967     if (is_afs_fh3(fhp1)) {
968         *fhpp = fhp1;
969         if (fhp2)
970             *fh2pp = fhp2;
971         return 1;
972     }
973     if (fhp2 && is_afs_fh3(fhp2)) {
974         *fhpp = fhp1;
975         *fh2pp = fhp2;
976         return 1;
977     }
978     return NULL;
979 }
980
981 afs_int32
982 acl3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp)
983 {
984     nfs_fh3 *fhp;
985
986     switch (which) {
987     case ACLPROC3_GETACL:
988         {
989             struct GETACL3args *sargs = (struct GETACL3args *)args;
990             fhp = &sargs->fh;
991             break;
992         }
993     case ACLPROC3_SETACL:
994         {
995             struct SETACL3args *sargs = (struct SETACL3args *)args;
996             fhp = &sargs->fh;
997             break;
998         }
999 #if defined(AFS_SUN510_ENV) 
1000     case ACLPROC3_GETXATTRDIR:
1001         {
1002             struct GETXATTRDIR3args *sargs = (struct GETXATTRDIR3args *)args;
1003             fhp = &sargs->fh;
1004             break;
1005         }
1006 #endif
1007     default:
1008         return NULL;
1009     }
1010
1011     if (is_afs_fh3(fhp)) {
1012         *fhpp = fhp;
1013         return 1;
1014     }
1015
1016     return NULL;
1017 }
1018
1019 int
1020 afs_nfs3_dispatcher(int type, afs_int32 which, char *argp,
1021                     struct exportinfo **expp, struct svc_req *rp,
1022                     struct AFS_UCRED *crp)
1023 {
1024     afs_int32 call = 0;
1025     afs_int32 code = 0;
1026     afs_int32 client = 0;
1027     struct sockaddr *sa;
1028     nfs_fh3 *fh = (nfs_fh3 *) argp;
1029     nfs_fh3 *fh2 = (nfs_fh3 *) 0;
1030
1031     if (!xlatorinit_v3_done)
1032         return 2;
1033
1034     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
1035     if (sa == NULL) 
1036         return;
1037
1038     if (sa->sa_family == AF_INET)
1039         client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
1040
1041     AFS_GLOCK();
1042     code = 0;
1043     switch (type) {
1044     case 0:
1045         code = (client && nfs3_to_afs_call(which, argp, &fh, &fh2));
1046         break;
1047     case 1:
1048         code = (client && acl3_to_afs_call(which, argp, &fh));
1049         break;
1050     default:
1051         break;
1052     }
1053
1054     if (code) {
1055         struct afs_exporter *out = 0;
1056         afs_int32 dummy;
1057         static int once = 0;
1058         struct SmallFid Sfid;
1059
1060         memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
1061
1062         afs_Trace2(afs_iclSetp, CM_TRACE_NFS3IN1, ICL_TYPE_INT32, client,
1063                    ICL_TYPE_FID, &Sfid);
1064
1065         call = 1;
1066         if (!once && *expp) {
1067             afs_nobody = (*expp)->exi_export.ex_anon;
1068             once = 1;
1069         }
1070         code =
1071             afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
1072                                      &dummy, &out);
1073
1074         if (!code && out)
1075             EXP_RELE(out);
1076
1077
1078         if (code == EINVAL)
1079             call = 2;
1080     }
1081
1082     AFS_GUNLOCK();
1083     return call;
1084 }
1085
1086 void
1087 afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
1088 {
1089     afs_int32 addr[2];
1090     struct vcache *vcp;
1091
1092 #if defined(AFS_SUN57_64BIT_ENV)
1093     /* See also afs_fid() */
1094     memcpy((char *)addr, fhp->fh3_data, 10);
1095     addr[1] = (addr[1] >> 48) & 0xffff;
1096 #else
1097     memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
1098 #endif
1099
1100     AFS_GLOCK();
1101     vcp = VTOAFS((struct vnode *)addr[0]);
1102
1103     /* See also afs_osi_vget */
1104     if (addr[1] == AFS_XLATOR_MAGIC) {
1105         if (status == NFS_OK) {
1106             struct SmallFid Sfid;
1107             struct cell *tcell;
1108
1109             /* Make up and copy out a SmallFid */
1110             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
1111             Sfid.Volume = vcp->fid.Fid.Volume;
1112             Sfid.CellAndUnique =
1113                 ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
1114             afs_PutCell(tcell, READ_LOCK);
1115             Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
1116             fhp->fh3_len = SIZEOF_SMALLFID;
1117             memcpy(fhp->fh3_data, (char *)&Sfid, fhp->fh3_len);
1118
1119             afs_Trace3(afs_iclSetp, CM_TRACE_NFS3OUT, ICL_TYPE_INT32, status,
1120                        ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
1121         }
1122
1123         /* If we have a ref, release it */
1124         if (vcp->vrefCount >= 1)
1125             AFS_RELE(AFSTOV(vcp));
1126     }
1127     AFS_GUNLOCK();
1128 }
1129
1130 void
1131 afs_nfs3_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
1132 {
1133     u_int call;
1134     afs_nfs3_resp dummy;
1135     struct cred *svcred = curthread->t_cred;
1136     curthread->t_cred = (struct cred *)crp;
1137     call =
1138         afs_nfs3_dispatcher(0, NFSPROC3_GETATTR, (char *)args, &exp, rp, crp);
1139     if (call > 1)
1140         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1141     else
1142         (*afs_rfs3_disp_tbl[NFSPROC3_GETATTR].orig_proc) (args, xp, exp, rp,
1143                                                           crp);
1144     curthread->t_cred = svcred;
1145     return;
1146 }
1147
1148 void
1149 afs_nfs3_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
1150 {
1151     u_int call;
1152     afs_nfs3_resp dummy;
1153     struct cred *svcred = curthread->t_cred;
1154     curthread->t_cred = (struct cred *)crp;
1155     call =
1156         afs_nfs3_dispatcher(0, NFSPROC3_SETATTR, (char *)args, &exp, rp, crp);
1157     if (call > 1)
1158         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1159     else
1160         (*afs_rfs3_disp_tbl[NFSPROC3_SETATTR].orig_proc) (args, xp, exp, rp,
1161                                                           crp);
1162     curthread->t_cred = svcred;
1163     return;
1164 }
1165
1166 void
1167 afs_nfs3_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
1168 {
1169     u_int call;
1170     afs_nfs3_resp dummy;
1171     struct cred *svcred = curthread->t_cred;
1172     curthread->t_cred = (struct cred *)crp;
1173     call =
1174         afs_nfs3_dispatcher(0, NFSPROC3_LOOKUP, (char *)args, &exp, rp, crp);
1175     if (call > 1)
1176         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1177     else {
1178         (*afs_rfs3_disp_tbl[NFSPROC3_LOOKUP].orig_proc) (args, xp, exp, rp,
1179                                                          crp);
1180         if (afs_NFSRootOnly && call) {
1181             LOOKUP3res *resp = (LOOKUP3res *) xp;
1182             afs_nfs3_smallfidder(&resp->resok.object, resp->status);
1183         }
1184     }
1185     curthread->t_cred = svcred;
1186     return;
1187 }
1188
1189 void
1190 afs_nfs3_access(char *args, char *xp, char *exp, char *rp, char *crp)
1191 {
1192     u_int call;
1193     afs_nfs3_resp dummy;
1194     struct cred *svcred = curthread->t_cred;
1195     curthread->t_cred = (struct cred *)crp;
1196     call =
1197         afs_nfs3_dispatcher(0, NFSPROC3_ACCESS, (char *)args, &exp, rp, crp);
1198     if (call > 1)
1199         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1200     else
1201         (*afs_rfs3_disp_tbl[NFSPROC3_ACCESS].orig_proc) (args, xp, exp, rp,
1202                                                          crp);
1203     curthread->t_cred = svcred;
1204     return;
1205 }
1206
1207 void
1208 afs_nfs3_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
1209 {
1210     u_int call;
1211     afs_nfs3_resp dummy;
1212     struct cred *svcred = curthread->t_cred;
1213     curthread->t_cred = (struct cred *)crp;
1214     call =
1215         afs_nfs3_dispatcher(0, NFSPROC3_READLINK, (char *)args, &exp, rp,
1216                             crp);
1217     if (call > 1)
1218         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1219     else
1220         (*afs_rfs3_disp_tbl[NFSPROC3_READLINK].orig_proc) (args, xp, exp, rp,
1221                                                            crp);
1222     curthread->t_cred = svcred;
1223     return;
1224 }
1225
1226 void
1227 afs_nfs3_read(char *args, char *xp, char *exp, char *rp, char *crp)
1228 {
1229     u_int call;
1230     afs_nfs3_resp dummy;
1231     struct cred *svcred = curthread->t_cred;
1232     curthread->t_cred = (struct cred *)crp;
1233     call = afs_nfs3_dispatcher(0, NFSPROC3_READ, (char *)args, &exp, rp, crp);
1234     if (call > 1)
1235         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1236     else
1237         (*afs_rfs3_disp_tbl[NFSPROC3_READ].orig_proc) (args, xp, exp, rp,
1238                                                        crp);
1239     curthread->t_cred = svcred;
1240     return;
1241 }
1242
1243 void
1244 afs_nfs3_write(char *args, char *xp, char *exp, char *rp, char *crp)
1245 {
1246     u_int call;
1247     afs_nfs3_resp dummy;
1248     struct cred *svcred = curthread->t_cred;
1249     curthread->t_cred = (struct cred *)crp;
1250     call =
1251         afs_nfs3_dispatcher(0, NFSPROC3_WRITE, (char *)args, &exp, rp, crp);
1252     if (call > 1)
1253         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1254     else
1255         (*afs_rfs3_disp_tbl[NFSPROC3_WRITE].orig_proc) (args, xp, exp, rp,
1256                                                         crp);
1257     curthread->t_cred = svcred;
1258     return;
1259 }
1260
1261 void
1262 afs_nfs3_create(char *args, char *xp, char *exp, char *rp, char *crp)
1263 {
1264     u_int call;
1265     afs_nfs3_resp dummy;
1266     struct cred *svcred = curthread->t_cred;
1267     curthread->t_cred = (struct cred *)crp;
1268     call =
1269         afs_nfs3_dispatcher(0, NFSPROC3_CREATE, (char *)args, &exp, rp, crp);
1270     if (call > 1)
1271         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1272     else {
1273         (*afs_rfs3_disp_tbl[NFSPROC3_CREATE].orig_proc) (args, xp, exp, rp,
1274                                                          crp);
1275         if (afs_NFSRootOnly && call) {
1276             CREATE3res *resp = (CREATE3res *) xp;
1277             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1278         }
1279     }
1280     curthread->t_cred = svcred;
1281     return;
1282 }
1283
1284 void
1285 afs_nfs3_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
1286 {
1287     u_int call;
1288     afs_nfs3_resp dummy;
1289     struct cred *svcred = curthread->t_cred;
1290     curthread->t_cred = (struct cred *)crp;
1291     call =
1292         afs_nfs3_dispatcher(0, NFSPROC3_MKDIR, (char *)args, &exp, rp, crp);
1293     if (call > 1)
1294         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1295     else {
1296         (*afs_rfs3_disp_tbl[NFSPROC3_MKDIR].orig_proc) (args, xp, exp, rp,
1297                                                         crp);
1298         if (afs_NFSRootOnly && call) {
1299             MKDIR3res *resp = (MKDIR3res *) xp;
1300             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1301         }
1302     }
1303     curthread->t_cred = svcred;
1304     return;
1305 }
1306
1307 void
1308 afs_nfs3_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
1309 {
1310     u_int call;
1311     afs_nfs3_resp dummy;
1312     struct cred *svcred = curthread->t_cred;
1313     curthread->t_cred = (struct cred *)crp;
1314     call =
1315         afs_nfs3_dispatcher(0, NFSPROC3_SYMLINK, (char *)args, &exp, rp, crp);
1316     if (call > 1)
1317         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1318     else {
1319         (*afs_rfs3_disp_tbl[NFSPROC3_SYMLINK].orig_proc) (args, xp, exp, rp,
1320                                                           crp);
1321         if (afs_NFSRootOnly && call) {
1322             SYMLINK3res *resp = (SYMLINK3res *) xp;
1323             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1324         }
1325     }
1326     curthread->t_cred = svcred;
1327     return;
1328 }
1329
1330 void
1331 afs_nfs3_mknod(char *args, char *xp, char *exp, char *rp, char *crp)
1332 {
1333     u_int call;
1334     afs_nfs3_resp dummy;
1335     struct cred *svcred = curthread->t_cred;
1336     curthread->t_cred = (struct cred *)crp;
1337     call =
1338         afs_nfs3_dispatcher(0, NFSPROC3_MKNOD, (char *)args, &exp, rp, crp);
1339     if (call > 1)
1340         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1341     else {
1342         (*afs_rfs3_disp_tbl[NFSPROC3_MKNOD].orig_proc) (args, xp, exp, rp,
1343                                                         crp);
1344         if (afs_NFSRootOnly && call) {
1345             MKNOD3res *resp = (MKNOD3res *) xp;
1346             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1347         }
1348     }
1349     curthread->t_cred = svcred;
1350     return;
1351 }
1352
1353 void
1354 afs_nfs3_remove(char *args, char *xp, char *exp, char *rp, char *crp)
1355 {
1356     u_int call;
1357     afs_nfs3_resp dummy;
1358     struct cred *svcred = curthread->t_cred;
1359     curthread->t_cred = (struct cred *)crp;
1360     call =
1361         afs_nfs3_dispatcher(0, NFSPROC3_REMOVE, (char *)args, &exp, rp, crp);
1362     if (call > 1)
1363         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1364     else
1365         (*afs_rfs3_disp_tbl[NFSPROC3_REMOVE].orig_proc) (args, xp, exp, rp,
1366                                                          crp);
1367     curthread->t_cred = svcred;
1368     return;
1369 }
1370
1371 void
1372 afs_nfs3_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
1373 {
1374     u_int call;
1375     afs_nfs3_resp dummy;
1376     struct cred *svcred = curthread->t_cred;
1377     curthread->t_cred = (struct cred *)crp;
1378     call =
1379         afs_nfs3_dispatcher(0, NFSPROC3_RMDIR, (char *)args, &exp, rp, crp);
1380     if (call > 1)
1381         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1382     else
1383         (*afs_rfs3_disp_tbl[NFSPROC3_RMDIR].orig_proc) (args, xp, exp, rp,
1384                                                         crp);
1385     curthread->t_cred = svcred;
1386     return;
1387 }
1388
1389 void
1390 afs_nfs3_rename(char *args, char *xp, char *exp, char *rp, char *crp)
1391 {
1392     u_int call;
1393     afs_nfs3_resp dummy;
1394     struct cred *svcred = curthread->t_cred;
1395     curthread->t_cred = (struct cred *)crp;
1396     call =
1397         afs_nfs3_dispatcher(0, NFSPROC3_RENAME, (char *)args, &exp, rp, crp);
1398     if (call > 1)
1399         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1400     else
1401         (*afs_rfs3_disp_tbl[NFSPROC3_RENAME].orig_proc) (args, xp, exp, rp,
1402                                                          crp);
1403     curthread->t_cred = svcred;
1404     return;
1405 }
1406
1407 void
1408 afs_nfs3_link(char *args, char *xp, char *exp, char *rp, char *crp)
1409 {
1410     u_int call;
1411     afs_nfs3_resp dummy;
1412     struct cred *svcred = curthread->t_cred;
1413     curthread->t_cred = (struct cred *)crp;
1414     call = afs_nfs3_dispatcher(0, NFSPROC3_LINK, (char *)args, &exp, rp, crp);
1415     if (call > 1)
1416         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1417     else
1418         (*afs_rfs3_disp_tbl[NFSPROC3_LINK].orig_proc) (args, xp, exp, rp,
1419                                                        crp);
1420     curthread->t_cred = svcred;
1421     return;
1422 }
1423
1424 void
1425 afs_nfs3_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
1426 {
1427     u_int call;
1428     afs_nfs3_resp dummy;
1429     struct cred *svcred = curthread->t_cred;
1430     curthread->t_cred = (struct cred *)crp;
1431     call =
1432         afs_nfs3_dispatcher(0, NFSPROC3_READDIR, (char *)args, &exp, rp, crp);
1433     if (call > 1)
1434         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1435     else
1436         (*afs_rfs3_disp_tbl[NFSPROC3_READDIR].orig_proc) (args, xp, exp, rp,
1437                                                           crp);
1438     curthread->t_cred = svcred;
1439     return;
1440 }
1441
1442 void
1443 afs_nfs3_readdirplus(char *args, char *xp, char *exp, char *rp, char *crp)
1444 {
1445     u_int call;
1446     afs_nfs3_resp dummy;
1447     struct cred *svcred = curthread->t_cred;
1448     curthread->t_cred = (struct cred *)crp;
1449     call =
1450         afs_nfs3_dispatcher(0, NFSPROC3_READDIRPLUS, (char *)args, &exp, rp,
1451                             crp);
1452     if (call > 1)
1453         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1454     else if (call == 1)
1455         afs_nfs3_notsupp((struct afs_nfs3_resp *)xp);
1456     else
1457         (*afs_rfs3_disp_tbl[NFSPROC3_READDIRPLUS].orig_proc) (args, xp, exp,
1458                                                               rp, crp);
1459     curthread->t_cred = svcred;
1460     return;
1461 }
1462
1463 void
1464 afs_nfs3_fsstat(char *args, char *xp, char *exp, char *rp, char *crp)
1465 {
1466     u_int call;
1467     afs_nfs3_resp dummy;
1468     struct cred *svcred = curthread->t_cred;
1469     curthread->t_cred = (struct cred *)crp;
1470     call =
1471         afs_nfs3_dispatcher(0, NFSPROC3_FSSTAT, (char *)args, &exp, rp, crp);
1472     if (call > 1)
1473         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1474     else
1475         (*afs_rfs3_disp_tbl[NFSPROC3_FSSTAT].orig_proc) (args, xp, exp, rp,
1476                                                          crp);
1477     curthread->t_cred = svcred;
1478     return;
1479 }
1480
1481 void
1482 afs_nfs3_fsinfo(char *args, char *xp, char *exp, char *rp, char *crp)
1483 {
1484     u_int call;
1485     afs_nfs3_resp dummy;
1486     struct cred *svcred = curthread->t_cred;
1487     curthread->t_cred = (struct cred *)crp;
1488     call =
1489         afs_nfs3_dispatcher(0, NFSPROC3_FSINFO, (char *)args, &exp, rp, crp);
1490     if (call > 1)
1491         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1492     else
1493         (*afs_rfs3_disp_tbl[NFSPROC3_FSINFO].orig_proc) (args, xp, exp, rp,
1494                                                          crp);
1495     curthread->t_cred = svcred;
1496     return;
1497 }
1498
1499 void
1500 afs_nfs3_pathconf(char *args, char *xp, char *exp, char *rp, char *crp)
1501 {
1502     u_int call;
1503     afs_nfs3_resp dummy;
1504     struct cred *svcred = curthread->t_cred;
1505     curthread->t_cred = (struct cred *)crp;
1506     call =
1507         afs_nfs3_dispatcher(0, NFSPROC3_PATHCONF, (char *)args, &exp, rp,
1508                             crp);
1509     if (call > 1)
1510         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1511     else
1512         (*afs_rfs3_disp_tbl[NFSPROC3_PATHCONF].orig_proc) (args, xp, exp, rp,
1513                                                            crp);
1514     curthread->t_cred = svcred;
1515     return;
1516 }
1517
1518 void
1519 afs_nfs3_commit(char *args, char *xp, char *exp, char *rp, char *crp)
1520 {
1521     u_int call;
1522     afs_nfs3_resp dummy;
1523     struct cred *svcred = curthread->t_cred;
1524     curthread->t_cred = (struct cred *)crp;
1525     call =
1526         afs_nfs3_dispatcher(0, NFSPROC3_COMMIT, (char *)args, &exp, rp, crp);
1527     if (call > 1)
1528         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1529     else
1530         (*afs_rfs3_disp_tbl[NFSPROC3_COMMIT].orig_proc) (args, xp, exp, rp,
1531                                                          crp);
1532     curthread->t_cred = svcred;
1533     return;
1534 }
1535
1536 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[22] = {
1537     {afs_nfs2_null},
1538     {afs_nfs3_getattr},
1539     {afs_nfs3_setattr},
1540     {afs_nfs3_lookup},
1541     {afs_nfs3_access},
1542     {afs_nfs3_readlink},
1543     {afs_nfs3_read},
1544     {afs_nfs3_write},
1545     {afs_nfs3_create},
1546     {afs_nfs3_mkdir},
1547     {afs_nfs3_symlink},
1548     {afs_nfs3_mknod},
1549     {afs_nfs3_remove},
1550     {afs_nfs3_rmdir},
1551     {afs_nfs3_rename},
1552     {afs_nfs3_link},
1553     {afs_nfs3_readdir},
1554     {afs_nfs3_readdirplus},
1555     {afs_nfs3_fsstat},
1556     {afs_nfs3_fsinfo},
1557     {afs_nfs3_pathconf},
1558     {afs_nfs3_commit}
1559 };
1560
1561 void
1562 afs_acl3_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
1563 {
1564     u_int call;
1565     struct cred *svcred = curthread->t_cred;
1566     curthread->t_cred = (struct cred *)crp;
1567     call =
1568         afs_nfs3_dispatcher(1, ACLPROC3_GETACL, (char *)args, &exp, rp, crp);
1569     if (call > 1)
1570         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1571     else
1572         (*afs_acl3_disp_tbl[ACLPROC3_GETACL].orig_proc) (args, xp, exp, rp,
1573                                                          crp);
1574     curthread->t_cred = svcred;
1575     return;
1576 }
1577
1578 void
1579 afs_acl3_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
1580 {
1581     u_int call;
1582     struct cred *svcred = curthread->t_cred;
1583     curthread->t_cred = (struct cred *)crp;
1584     call =
1585         afs_nfs3_dispatcher(1, ACLPROC3_SETACL, (char *)args, &exp, rp, crp);
1586     if (call > 1)
1587         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1588     else
1589         (*afs_acl3_disp_tbl[ACLPROC3_SETACL].orig_proc) (args, xp, exp, rp,
1590                                                          crp);
1591     curthread->t_cred = svcred;
1592     return;
1593 }
1594
1595 #if defined(AFS_SUN510_ENV) 
1596 void
1597 afs_acl3_getxattrdir(char *args, char *xp, char *exp, char *rp, char *crp)
1598 {
1599     u_int call;
1600     struct cred *svcred = curthread->t_cred;
1601     curthread->t_cred = (struct cred *)crp;
1602     call =
1603         afs_nfs3_dispatcher(1, ACLPROC3_GETXATTRDIR, (char *)args, &exp, rp, crp);
1604     if (call > 1)
1605         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1606     else
1607         (*afs_acl3_disp_tbl[ACLPROC3_GETXATTRDIR].orig_proc) (args, xp, exp, rp,
1608                                                          crp);
1609     curthread->t_cred = svcred;
1610     return;
1611 }
1612 #endif
1613
1614 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[3] = {
1615     {afs_nfs2_null},
1616     {afs_acl3_getacl},
1617     {afs_acl3_setacl},
1618 #if defined(AFS_SUN510_ENV) 
1619     {afs_acl3_getxattrdir},
1620 #endif
1621 };
1622
1623 /* Munge the dispatch tables to link us in first */
1624 void
1625 afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl,
1626                   struct rfs_disp_tbl *_acl_tbl)
1627 {
1628     int i;
1629
1630     if (xlatorinit_v3_done++)
1631         return;
1632
1633     for (i = 0; i < 22; i++) {
1634         afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
1635         _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
1636     }
1637
1638     for (i = 0; i < 3; i++) {
1639         afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
1640         _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
1641     }
1642 }
1643 #endif /* !defined(AFS_NONFSTRANS) */