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