nfs3-no-readdirplus-20041108
[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     default:
225         return NULL;
226     }
227
228     if (is_afs_fh(fhp)) {
229         *fhpp = fhp;
230         return 1;
231     }
232
233     return NULL;
234 }
235
236 int
237 afs_nfs2_dispatcher(int type, afs_int32 which, char *argp,
238                     struct exportinfo **expp, struct svc_req *rp,
239                     struct AFS_UCRED *crp)
240 {
241     afs_int32 call = 0;
242     afs_int32 code = 0;
243     afs_int32 client = 0;
244     struct sockaddr *sa;
245     fhandle_t *fh = (fhandle_t *) argp;
246     fhandle_t *fh2 = (fhandle_t *) 0;
247
248     if (!xlatorinit_v2_done)
249         return 2;
250
251     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
252     if (sa->sa_family == AF_INET)
253         client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
254
255     AFS_GLOCK();
256     code = 0;
257     switch (type) {
258     case 0:
259         code = (client && nfs2_to_afs_call(which, argp, &fh, &fh2));
260         break;
261     case 1:
262         code = (client && acl2_to_afs_call(which, argp, &fh));
263         break;
264     default:
265         break;
266     }
267
268     if (code) {
269         struct afs_exporter *out = 0;
270         afs_int32 dummy;
271         static int once = 0;
272         struct SmallFid Sfid;
273
274         memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
275
276         afs_Trace2(afs_iclSetp, CM_TRACE_NFSIN1, ICL_TYPE_POINTER, client,
277                    ICL_TYPE_FID, &Sfid);
278
279         /* We ran */
280         call = 1;
281         if (!once && *expp) {
282             afs_nobody = (*expp)->exi_export.ex_anon;
283             once = 1;
284         }
285         code =
286             afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
287                                      &dummy, &out);
288
289         if (!code && out)
290             EXP_RELE(out);
291
292         if (code == EINVAL)
293             call = 2;
294     }
295
296     AFS_GUNLOCK();
297     return call;
298 }
299
300 void
301 afs_nfs2_smallfidder(struct nfsdiropres *dr)
302 {
303     register fhandle_t *fhp = (fhandle_t *) & dr->dr_fhandle;
304     afs_int32 addr[2];
305     struct vcache *vcp;
306
307 #if defined(AFS_SUN57_64BIT_ENV)
308     /* See also afs_fid() */
309     memcpy((char *)addr, fhp->fh_data, SIZEOF_SMALLFID);
310     addr[1] = (addr[1] >> 48) & 0xffff;
311 #else
312     memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
313 #endif
314
315     AFS_GLOCK();
316     vcp = VTOAFS((struct vnode *)addr[0]);
317
318     if (addr[1] == AFS_XLATOR_MAGIC) {
319         if (dr->dr_status == NFS_OK) {
320             struct SmallFid Sfid;
321             struct cell *tcell;
322
323             /* Make up and copy out a SmallFid */
324             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
325             Sfid.Volume = vcp->fid.Fid.Volume;
326             Sfid.CellAndUnique =
327                 ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
328             afs_PutCell(tcell, READ_LOCK);
329             Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
330             fhp->fh_len = SIZEOF_SMALLFID;
331             memcpy(dr->dr_fhandle.fh_data, (char *)&Sfid, fhp->fh_len);
332
333             afs_Trace3(afs_iclSetp, CM_TRACE_NFSOUT, ICL_TYPE_INT32, 0,
334                        ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
335         }
336
337         /* If we have a ref, release it */
338         if (vcp->vrefCount >= 1)
339             AFS_RELE(AFSTOV(vcp));
340     }
341     AFS_GUNLOCK();
342 }
343
344 void
345 afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
346 {
347     resp->status = NFSERR_ACCES;
348 }
349
350 void
351 afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
352 {
353 }
354
355 void
356 afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
357 {
358 }
359
360 void
361 afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
362 {
363 }
364
365 void
366 afs_nfs2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
367 {
368     u_int call;
369     struct cred *svcred = curthread->t_cred;
370     curthread->t_cred = (struct cred *)crp;
371     call = afs_nfs2_dispatcher(0, RFS_GETATTR, (char *)args, &exp, rp, crp);
372     if (call > 1)
373         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
374     else
375         (*afs_rfs_disp_tbl[RFS_GETATTR].orig_proc) (args, xp, exp, rp, crp);
376     curthread->t_cred = svcred;
377     return;
378 }
379
380 void
381 afs_nfs2_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
382 {
383     u_int call;
384     struct cred *svcred = curthread->t_cred;
385     curthread->t_cred = (struct cred *)crp;
386     call = afs_nfs2_dispatcher(0, RFS_SETATTR, (char *)args, &exp, rp, crp);
387     if (call > 1)
388         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
389     else
390         (*afs_rfs_disp_tbl[RFS_SETATTR].orig_proc) (args, xp, exp, rp, crp);
391     curthread->t_cred = svcred;
392     return;
393 }
394
395 void
396 afs_nfs2_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
397 {
398     u_int call;
399     struct cred *svcred = curthread->t_cred;
400     curthread->t_cred = (struct cred *)crp;
401     call = afs_nfs2_dispatcher(0, RFS_LOOKUP, (char *)args, &exp, rp, crp);
402     if (call > 1)
403         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
404     else {
405         (*afs_rfs_disp_tbl[RFS_LOOKUP].orig_proc) (args, xp, exp, rp, crp);
406         if (afs_NFSRootOnly && call)
407             afs_nfs2_smallfidder(xp);
408     }
409     curthread->t_cred = svcred;
410     return;
411 }
412
413 void
414 afs_nfs2_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
415 {
416     u_int call;
417     struct cred *svcred = curthread->t_cred;
418     curthread->t_cred = (struct cred *)crp;
419     call = afs_nfs2_dispatcher(0, RFS_READLINK, (char *)args, &exp, rp, crp);
420     if (call > 1)
421         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
422     else
423         (*afs_rfs_disp_tbl[RFS_READLINK].orig_proc) (args, xp, exp, rp, crp);
424     curthread->t_cred = svcred;
425     return;
426 }
427
428 void
429 afs_nfs2_read(char *args, char *xp, char *exp, char *rp, char *crp)
430 {
431     u_int call;
432     struct cred *svcred = curthread->t_cred;
433     curthread->t_cred = (struct cred *)crp;
434     call = afs_nfs2_dispatcher(0, RFS_READ, (char *)args, &exp, rp, crp);
435     if (call > 1)
436         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
437     else
438         (*afs_rfs_disp_tbl[RFS_READ].orig_proc) (args, xp, exp, rp, crp);
439     curthread->t_cred = svcred;
440     return;
441 }
442
443 void
444 afs_nfs2_write(char *args, char *xp, char *exp, char *rp, char *crp)
445 {
446     u_int call;
447     struct cred *svcred = curthread->t_cred;
448     curthread->t_cred = (struct cred *)crp;
449     call = afs_nfs2_dispatcher(0, RFS_WRITE, (char *)args, &exp, rp, crp);
450     if (call > 1)
451         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
452     else
453         (*afs_rfs_disp_tbl[RFS_WRITE].orig_proc) (args, xp, exp, rp, crp);
454     curthread->t_cred = svcred;
455     return;
456 }
457
458 void
459 afs_nfs2_create(char *args, char *xp, char *exp, char *rp, char *crp)
460 {
461     u_int call;
462     struct cred *svcred = curthread->t_cred;
463     curthread->t_cred = (struct cred *)crp;
464     call = afs_nfs2_dispatcher(0, RFS_CREATE, (char *)args, &exp, rp, crp);
465     if (call > 1)
466         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
467     else {
468         (*afs_rfs_disp_tbl[RFS_CREATE].orig_proc) (args, xp, exp, rp, crp);
469         if (afs_NFSRootOnly && call)
470             afs_nfs2_smallfidder(xp);
471     }
472     curthread->t_cred = svcred;
473     return;
474 }
475
476 void
477 afs_nfs2_remove(char *args, char *xp, char *exp, char *rp, char *crp)
478 {
479     u_int call;
480     struct cred *svcred = curthread->t_cred;
481     curthread->t_cred = (struct cred *)crp;
482     call = afs_nfs2_dispatcher(0, RFS_REMOVE, (char *)args, &exp, rp, crp);
483     if (call > 1)
484         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
485     else
486         (*afs_rfs_disp_tbl[RFS_REMOVE].orig_proc) (args, xp, exp, rp, crp);
487     curthread->t_cred = svcred;
488     return;
489 }
490
491 void
492 afs_nfs2_rename(char *args, char *xp, char *exp, char *rp, char *crp)
493 {
494     u_int call;
495     struct cred *svcred = curthread->t_cred;
496     curthread->t_cred = (struct cred *)crp;
497     call = afs_nfs2_dispatcher(0, RFS_RENAME, (char *)args, &exp, rp, crp);
498     if (call > 1)
499         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
500     else
501         (*afs_rfs_disp_tbl[RFS_RENAME].orig_proc) (args, xp, exp, rp, crp);
502     curthread->t_cred = svcred;
503     return;
504 }
505
506 void
507 afs_nfs2_link(char *args, char *xp, char *exp, char *rp, char *crp)
508 {
509     u_int call;
510     struct cred *svcred = curthread->t_cred;
511     curthread->t_cred = (struct cred *)crp;
512     call = afs_nfs2_dispatcher(0, RFS_LINK, (char *)args, &exp, rp, crp);
513     if (call > 1)
514         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
515     else
516         (*afs_rfs_disp_tbl[RFS_LINK].orig_proc) (args, xp, exp, rp, crp);
517     curthread->t_cred = svcred;
518     return;
519 }
520
521 void
522 afs_nfs2_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
523 {
524     u_int call;
525     struct cred *svcred = curthread->t_cred;
526     curthread->t_cred = (struct cred *)crp;
527     call = afs_nfs2_dispatcher(0, RFS_SYMLINK, (char *)args, &exp, rp, crp);
528     if (call > 1)
529         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
530     else
531         (*afs_rfs_disp_tbl[RFS_SYMLINK].orig_proc) (args, xp, exp, rp, crp);
532     curthread->t_cred = svcred;
533     return;
534 }
535
536 void
537 afs_nfs2_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
538 {
539     u_int call;
540     struct cred *svcred = curthread->t_cred;
541     curthread->t_cred = (struct cred *)crp;
542     call = afs_nfs2_dispatcher(0, RFS_MKDIR, (char *)args, &exp, rp, crp);
543     if (call > 1)
544         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
545     else {
546         (*afs_rfs_disp_tbl[RFS_MKDIR].orig_proc) (args, xp, exp, rp, crp);
547         if (afs_NFSRootOnly && call)
548             afs_nfs2_smallfidder(xp);
549     }
550     curthread->t_cred = svcred;
551     return;
552 }
553
554 void
555 afs_nfs2_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
556 {
557     u_int call;
558     struct cred *svcred = curthread->t_cred;
559     curthread->t_cred = (struct cred *)crp;
560     call = afs_nfs2_dispatcher(0, RFS_RMDIR, (char *)args, &exp, rp, crp);
561     if (call > 1)
562         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
563     else
564         (*afs_rfs_disp_tbl[RFS_RMDIR].orig_proc) (args, xp, exp, rp, crp);
565     curthread->t_cred = svcred;
566     return;
567 }
568
569 void
570 afs_nfs2_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
571 {
572     u_int call;
573     struct cred *svcred = curthread->t_cred;
574     curthread->t_cred = (struct cred *)crp;
575     call = afs_nfs2_dispatcher(0, RFS_READDIR, (char *)args, &exp, rp, crp);
576     if (call > 1)
577         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
578     else
579         (*afs_rfs_disp_tbl[RFS_READDIR].orig_proc) (args, xp, exp, rp, crp);
580     curthread->t_cred = svcred;
581     return;
582 }
583
584 void
585 afs_nfs2_statfs(char *args, char *xp, char *exp, char *rp, char *crp)
586 {
587     u_int call;
588     struct cred *svcred = curthread->t_cred;
589     curthread->t_cred = (struct cred *)crp;
590     call = afs_nfs2_dispatcher(0, RFS_STATFS, (char *)args, &exp, rp, crp);
591     if (call > 1)
592         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
593     else
594         (*afs_rfs_disp_tbl[RFS_STATFS].orig_proc) (args, xp, exp, rp, crp);
595     curthread->t_cred = svcred;
596     return;
597 }
598
599 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
600     {afs_nfs2_null},
601     {afs_nfs2_getattr},
602     {afs_nfs2_setattr},
603     {afs_nfs2_root},
604     {afs_nfs2_lookup},
605     {afs_nfs2_readlink},
606     {afs_nfs2_read},
607     {afs_nfs2_writecache},
608     {afs_nfs2_write},
609     {afs_nfs2_create},
610     {afs_nfs2_remove},
611     {afs_nfs2_rename},
612     {afs_nfs2_link},
613     {afs_nfs2_symlink},
614     {afs_nfs2_mkdir},
615     {afs_nfs2_rmdir},
616     {afs_nfs2_readdir},
617     {afs_nfs2_statfs}
618 };
619
620 void
621 afs_acl2_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
622 {
623     u_int call;
624     struct cred *svcred = curthread->t_cred;
625     curthread->t_cred = (struct cred *)crp;
626     call =
627         afs_nfs2_dispatcher(1, ACLPROC2_GETACL, (char *)args, &exp, rp, crp);
628     if (call > 1)
629         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
630     else
631         (*afs_acl_disp_tbl[ACLPROC2_GETACL].orig_proc) (args, xp, exp, rp,
632                                                         crp);
633     curthread->t_cred = svcred;
634     return;
635 }
636
637 void
638 afs_acl2_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
639 {
640     u_int call;
641     struct cred *svcred = curthread->t_cred;
642     curthread->t_cred = (struct cred *)crp;
643     call =
644         afs_nfs2_dispatcher(1, ACLPROC2_SETACL, (char *)args, &exp, rp, crp);
645     if (call > 1)
646         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
647     else
648         (*afs_acl_disp_tbl[ACLPROC2_SETACL].orig_proc) (args, xp, exp, rp,
649                                                         crp);
650     curthread->t_cred = svcred;
651     return;
652 }
653
654 void
655 afs_acl2_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
656 {
657     u_int call;
658     struct cred *svcred = curthread->t_cred;
659     curthread->t_cred = (struct cred *)crp;
660     call =
661         afs_nfs2_dispatcher(1, ACLPROC2_GETATTR, (char *)args, &exp, rp, crp);
662     if (call > 1)
663         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
664     else
665         (*afs_acl_disp_tbl[ACLPROC2_GETATTR].orig_proc) (args, xp, exp, rp,
666                                                          crp);
667     curthread->t_cred = svcred;
668     return;
669 }
670
671 void
672 afs_acl2_access(char *args, char *xp, char *exp, char *rp, char *crp)
673 {
674     u_int call;
675     struct cred *svcred = curthread->t_cred;
676     curthread->t_cred = (struct cred *)crp;
677     call =
678         afs_nfs2_dispatcher(1, ACLPROC2_ACCESS, (char *)args, &exp, rp, crp);
679     if (call > 1)
680         afs_nfs2_noaccess((struct afs_nfs2_resp *)xp);
681     else
682         (*afs_acl_disp_tbl[ACLPROC2_ACCESS].orig_proc) (args, xp, exp, rp,
683                                                         crp);
684     curthread->t_cred = svcred;
685     return;
686 }
687
688 struct afs_nfs_disp_tbl afs_acl_disp_tbl[5] = {
689     {afs_nfs2_null},
690     {afs_acl2_getacl},
691     {afs_acl2_setacl},
692     {afs_acl2_getattr},
693     {afs_acl2_access}
694 };
695
696 /* Munge the dispatch tables to link us in first */
697 void
698 afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl,
699                   struct rfs_disp_tbl *_acl_tbl)
700 {
701     int i;
702
703     if (xlatorinit_v2_done++)
704         return;
705
706     for (i = 0; i < RFS_NPROC; i++) {
707         afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
708         _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
709     }
710
711     for (i = 0; i < 5; i++) {
712         afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
713         _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
714     }
715 }
716
717 #ifndef RFS3_NPROC
718 #define RFS3_NPROC      22
719 #endif
720
721 #ifndef ACL3_NPROC
722 #define ACL3_NPROC      3
723 #endif
724
725 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
726 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
727
728 struct afs_nfs3_resp {
729     nfsstat3 status;
730     bool_t flags;
731 };
732 typedef struct afs_nfs3_resp afs_nfs3_resp;
733
734 static int
735 is_afs_fh3(nfs_fh3 * fhp)
736 {
737     if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC)
738         && (fhp->fh3_fsid.val[1] == AFS_VFSFSID))
739         return 1;
740     return 0;
741 }
742
743 void
744 afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
745 {
746     resp->status = NFS3ERR_ACCES;
747     resp->flags = FALSE;
748 }
749
750 void
751 afs_nfs3_notsupp(struct afs_nfs3_resp *resp)
752 {
753     resp->status = NFS3ERR_NOTSUPP;
754     resp->flags = FALSE;
755 }
756
757 afs_int32
758 nfs3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp, nfs_fh3 ** fh2pp)
759 {
760     struct vnode *vp;
761     nfs_fh3 *fhp1 = 0;
762     nfs_fh3 *fhp2 = 0;
763     int errorcode;
764
765     afs_Trace1(afs_iclSetp, CM_TRACE_NFS3IN, ICL_TYPE_INT32, which);
766     *fh2pp = (nfs_fh3 *) 0;
767     switch (which) {
768     case NFSPROC3_GETATTR:
769         {
770             GETATTR3args *arg = (GETATTR3args *) args;
771             fhp1 = (nfs_fh3 *) & arg->object;
772             break;
773         }
774     case NFSPROC3_SETATTR:
775         {
776             SETATTR3args *arg = (SETATTR3args *) args;
777             fhp1 = (nfs_fh3 *) & arg->object;
778             break;
779         }
780     case NFSPROC3_LOOKUP:
781         {
782             LOOKUP3args *arg = (LOOKUP3args *) args;
783 #ifdef AFS_SUN58_ENV
784             fhp1 = (nfs_fh3 *) arg->what.dirp;
785 #else
786             fhp1 = (nfs_fh3 *) & arg->what.dir;
787 #endif
788             break;
789         }
790     case NFSPROC3_ACCESS:
791         {
792             ACCESS3args *arg = (ACCESS3args *) args;
793             fhp1 = (nfs_fh3 *) & arg->object;
794             break;
795         }
796     case NFSPROC3_READLINK:
797         {
798             READLINK3args *arg = (READLINK3args *) args;
799             fhp1 = (nfs_fh3 *) & arg->symlink;
800             break;
801         }
802     case NFSPROC3_READ:
803         {
804             READ3args *arg = (READ3args *) args;
805             fhp1 = (nfs_fh3 *) & arg->file;
806             break;
807         }
808     case NFSPROC3_WRITE:
809         {
810             WRITE3args *arg = (WRITE3args *) args;
811             fhp1 = (nfs_fh3 *) & arg->file;
812             break;
813         }
814     case NFSPROC3_CREATE:
815         {
816             CREATE3args *arg = (CREATE3args *) args;
817             fhp1 = (nfs_fh3 *) & arg->where.dir;
818             break;
819         }
820     case NFSPROC3_MKDIR:
821         {
822             MKDIR3args *arg = (MKDIR3args *) args;
823             fhp1 = (nfs_fh3 *) & arg->where.dir;
824             break;
825         }
826     case NFSPROC3_SYMLINK:
827         {
828             SYMLINK3args *arg = (SYMLINK3args *) args;
829             fhp1 = (nfs_fh3 *) & arg->where.dir;
830             break;
831         }
832     case NFSPROC3_MKNOD:
833         {
834             MKNOD3args *arg = (MKNOD3args *) args;
835             fhp1 = (nfs_fh3 *) & arg->where.dir;
836             break;
837         }
838     case NFSPROC3_REMOVE:
839         {
840             REMOVE3args *arg = (REMOVE3args *) args;
841             fhp1 = (nfs_fh3 *) & arg->object.dir;
842             break;
843         }
844     case NFSPROC3_RMDIR:
845         {
846             RMDIR3args *arg = (RMDIR3args *) args;
847             fhp1 = (nfs_fh3 *) & arg->object.dir;
848             break;
849         }
850     case NFSPROC3_RENAME:
851         {
852             RENAME3args *arg = (RENAME3args *) args;
853             fhp1 = (nfs_fh3 *) & arg->from.dir;
854             fhp2 = (nfs_fh3 *) & arg->to.dir;
855             break;
856         }
857     case NFSPROC3_LINK:
858         {
859             LINK3args *arg = (LINK3args *) args;
860             fhp1 = (nfs_fh3 *) & arg->file;
861             fhp2 = (nfs_fh3 *) & arg->link.dir;
862             break;
863         }
864     case NFSPROC3_READDIR:
865         {
866             READDIR3args *arg = (READDIR3args *) args;
867             fhp1 = (nfs_fh3 *) & arg->dir;
868             break;
869         }
870     case NFSPROC3_READDIRPLUS:
871         {
872             READDIRPLUS3args *arg = (READDIRPLUS3args *) args;
873             fhp1 = (nfs_fh3 *) & arg->dir;
874             break;
875         }
876     case NFSPROC3_FSSTAT:
877         {
878             FSSTAT3args *arg = (FSSTAT3args *) args;
879             fhp1 = (nfs_fh3 *) & arg->fsroot;
880             break;
881         }
882     case NFSPROC3_FSINFO:
883         {
884             FSINFO3args *arg = (FSINFO3args *) args;
885             fhp1 = (nfs_fh3 *) & arg->fsroot;
886             break;
887         }
888     case NFSPROC3_PATHCONF:
889         {
890             PATHCONF3args *arg = (PATHCONF3args *) args;
891             fhp1 = (nfs_fh3 *) & arg->object;
892             break;
893         }
894     case NFSPROC3_COMMIT:
895         {
896             COMMIT3args *arg = (COMMIT3args *) args;
897             fhp1 = (nfs_fh3 *) & arg->file;
898             break;
899         }
900     default:
901         return NULL;
902     }
903
904     if (is_afs_fh3(fhp1)) {
905         *fhpp = fhp1;
906         if (fhp2)
907             *fh2pp = fhp2;
908         return 1;
909     }
910     if (fhp2 && is_afs_fh3(fhp2)) {
911         *fhpp = fhp1;
912         *fh2pp = fhp2;
913         return 1;
914     }
915     return NULL;
916 }
917
918 afs_int32
919 acl3_to_afs_call(int which, caddr_t * args, nfs_fh3 ** fhpp)
920 {
921     nfs_fh3 *fhp;
922
923     switch (which) {
924     case ACLPROC3_GETACL:
925         {
926             struct GETACL3args *sargs = (struct GETACL3args *)args;
927             fhp = &sargs->fh;
928             break;
929         }
930     case ACLPROC3_SETACL:
931         {
932             struct SETACL3args *sargs = (struct SETACL3args *)args;
933             fhp = &sargs->fh;
934             break;
935         }
936     default:
937         return NULL;
938     }
939
940     if (is_afs_fh3(fhp)) {
941         *fhpp = fhp;
942         return 1;
943     }
944
945     return NULL;
946 }
947
948 int
949 afs_nfs3_dispatcher(int type, afs_int32 which, char *argp,
950                     struct exportinfo **expp, struct svc_req *rp,
951                     struct AFS_UCRED *crp)
952 {
953     afs_int32 call = 0;
954     afs_int32 code = 0;
955     afs_int32 client = 0;
956     struct sockaddr *sa;
957     nfs_fh3 *fh = (nfs_fh3 *) argp;
958     nfs_fh3 *fh2 = (nfs_fh3 *) 0;
959
960     if (!xlatorinit_v3_done)
961         return 2;
962
963     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
964     if (sa->sa_family == AF_INET)
965         client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
966
967     AFS_GLOCK();
968     code = 0;
969     switch (type) {
970     case 0:
971         code = (client && nfs3_to_afs_call(which, argp, &fh, &fh2));
972         break;
973     case 1:
974         code = (client && acl3_to_afs_call(which, argp, &fh));
975         break;
976     default:
977         break;
978     }
979
980     if (code) {
981         struct afs_exporter *out = 0;
982         afs_int32 dummy;
983         static int once = 0;
984         struct SmallFid Sfid;
985
986         memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
987
988         afs_Trace2(afs_iclSetp, CM_TRACE_NFS3IN1, ICL_TYPE_INT32, client,
989                    ICL_TYPE_FID, &Sfid);
990
991         call = 1;
992         if (!once && *expp) {
993             afs_nobody = (*expp)->exi_export.ex_anon;
994             once = 1;
995         }
996         code =
997             afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp, client,
998                                      &dummy, &out);
999
1000         if (!code && out)
1001             EXP_RELE(out);
1002
1003
1004         if (code == EINVAL)
1005             call = 2;
1006     }
1007
1008     AFS_GUNLOCK();
1009     return call;
1010 }
1011
1012 void
1013 afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
1014 {
1015     afs_int32 addr[2];
1016     struct vcache *vcp;
1017
1018 #if defined(AFS_SUN57_64BIT_ENV)
1019     /* See also afs_fid() */
1020     memcpy((char *)addr, fhp->fh3_data, 10);
1021     addr[1] = (addr[1] >> 48) & 0xffff;
1022 #else
1023     memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
1024 #endif
1025
1026     AFS_GLOCK();
1027     vcp = VTOAFS((struct vnode *)addr[0]);
1028
1029     /* See also afs_osi_vget */
1030     if (addr[1] == AFS_XLATOR_MAGIC) {
1031         if (status == NFS_OK) {
1032             struct SmallFid Sfid;
1033             struct cell *tcell;
1034
1035             /* Make up and copy out a SmallFid */
1036             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
1037             Sfid.Volume = vcp->fid.Fid.Volume;
1038             Sfid.CellAndUnique =
1039                 ((tcell->cellIndex << 24) | (vcp->fid.Fid.Unique & 0xffffff));
1040             afs_PutCell(tcell, READ_LOCK);
1041             Sfid.Vnode = (u_short) (vcp->fid.Fid.Vnode & 0xffff);
1042             fhp->fh3_len = SIZEOF_SMALLFID;
1043             memcpy(fhp->fh3_data, (char *)&Sfid, fhp->fh3_len);
1044
1045             afs_Trace3(afs_iclSetp, CM_TRACE_NFS3OUT, ICL_TYPE_INT32, status,
1046                        ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
1047         }
1048
1049         /* If we have a ref, release it */
1050         if (vcp->vrefCount >= 1)
1051             AFS_RELE(AFSTOV(vcp));
1052     }
1053     AFS_GUNLOCK();
1054 }
1055
1056 void
1057 afs_nfs3_getattr(char *args, char *xp, char *exp, char *rp, char *crp)
1058 {
1059     u_int call;
1060     afs_nfs3_resp dummy;
1061     struct cred *svcred = curthread->t_cred;
1062     curthread->t_cred = (struct cred *)crp;
1063     call =
1064         afs_nfs3_dispatcher(0, NFSPROC3_GETATTR, (char *)args, &exp, rp, crp);
1065     if (call > 1)
1066         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1067     else
1068         (*afs_rfs3_disp_tbl[NFSPROC3_GETATTR].orig_proc) (args, xp, exp, rp,
1069                                                           crp);
1070     curthread->t_cred = svcred;
1071     return;
1072 }
1073
1074 void
1075 afs_nfs3_setattr(char *args, char *xp, char *exp, char *rp, char *crp)
1076 {
1077     u_int call;
1078     afs_nfs3_resp dummy;
1079     struct cred *svcred = curthread->t_cred;
1080     curthread->t_cred = (struct cred *)crp;
1081     call =
1082         afs_nfs3_dispatcher(0, NFSPROC3_SETATTR, (char *)args, &exp, rp, crp);
1083     if (call > 1)
1084         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1085     else
1086         (*afs_rfs3_disp_tbl[NFSPROC3_SETATTR].orig_proc) (args, xp, exp, rp,
1087                                                           crp);
1088     curthread->t_cred = svcred;
1089     return;
1090 }
1091
1092 void
1093 afs_nfs3_lookup(char *args, char *xp, char *exp, char *rp, char *crp)
1094 {
1095     u_int call;
1096     afs_nfs3_resp dummy;
1097     struct cred *svcred = curthread->t_cred;
1098     curthread->t_cred = (struct cred *)crp;
1099     call =
1100         afs_nfs3_dispatcher(0, NFSPROC3_LOOKUP, (char *)args, &exp, rp, crp);
1101     if (call > 1)
1102         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1103     else {
1104         (*afs_rfs3_disp_tbl[NFSPROC3_LOOKUP].orig_proc) (args, xp, exp, rp,
1105                                                          crp);
1106         if (afs_NFSRootOnly && call) {
1107             LOOKUP3res *resp = (LOOKUP3res *) xp;
1108             afs_nfs3_smallfidder(&resp->resok.object, resp->status);
1109         }
1110     }
1111     curthread->t_cred = svcred;
1112     return;
1113 }
1114
1115 void
1116 afs_nfs3_access(char *args, char *xp, char *exp, char *rp, char *crp)
1117 {
1118     u_int call;
1119     afs_nfs3_resp dummy;
1120     struct cred *svcred = curthread->t_cred;
1121     curthread->t_cred = (struct cred *)crp;
1122     call =
1123         afs_nfs3_dispatcher(0, NFSPROC3_ACCESS, (char *)args, &exp, rp, crp);
1124     if (call > 1)
1125         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1126     else
1127         (*afs_rfs3_disp_tbl[NFSPROC3_ACCESS].orig_proc) (args, xp, exp, rp,
1128                                                          crp);
1129     curthread->t_cred = svcred;
1130     return;
1131 }
1132
1133 void
1134 afs_nfs3_readlink(char *args, char *xp, char *exp, char *rp, char *crp)
1135 {
1136     u_int call;
1137     afs_nfs3_resp dummy;
1138     struct cred *svcred = curthread->t_cred;
1139     curthread->t_cred = (struct cred *)crp;
1140     call =
1141         afs_nfs3_dispatcher(0, NFSPROC3_READLINK, (char *)args, &exp, rp,
1142                             crp);
1143     if (call > 1)
1144         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1145     else
1146         (*afs_rfs3_disp_tbl[NFSPROC3_READLINK].orig_proc) (args, xp, exp, rp,
1147                                                            crp);
1148     curthread->t_cred = svcred;
1149     return;
1150 }
1151
1152 void
1153 afs_nfs3_read(char *args, char *xp, char *exp, char *rp, char *crp)
1154 {
1155     u_int call;
1156     afs_nfs3_resp dummy;
1157     struct cred *svcred = curthread->t_cred;
1158     curthread->t_cred = (struct cred *)crp;
1159     call = afs_nfs3_dispatcher(0, NFSPROC3_READ, (char *)args, &exp, rp, crp);
1160     if (call > 1)
1161         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1162     else
1163         (*afs_rfs3_disp_tbl[NFSPROC3_READ].orig_proc) (args, xp, exp, rp,
1164                                                        crp);
1165     curthread->t_cred = svcred;
1166     return;
1167 }
1168
1169 void
1170 afs_nfs3_write(char *args, char *xp, char *exp, char *rp, char *crp)
1171 {
1172     u_int call;
1173     afs_nfs3_resp dummy;
1174     struct cred *svcred = curthread->t_cred;
1175     curthread->t_cred = (struct cred *)crp;
1176     call =
1177         afs_nfs3_dispatcher(0, NFSPROC3_WRITE, (char *)args, &exp, rp, crp);
1178     if (call > 1)
1179         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1180     else
1181         (*afs_rfs3_disp_tbl[NFSPROC3_WRITE].orig_proc) (args, xp, exp, rp,
1182                                                         crp);
1183     curthread->t_cred = svcred;
1184     return;
1185 }
1186
1187 void
1188 afs_nfs3_create(char *args, char *xp, char *exp, char *rp, char *crp)
1189 {
1190     u_int call;
1191     afs_nfs3_resp dummy;
1192     struct cred *svcred = curthread->t_cred;
1193     curthread->t_cred = (struct cred *)crp;
1194     call =
1195         afs_nfs3_dispatcher(0, NFSPROC3_CREATE, (char *)args, &exp, rp, crp);
1196     if (call > 1)
1197         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1198     else {
1199         (*afs_rfs3_disp_tbl[NFSPROC3_CREATE].orig_proc) (args, xp, exp, rp,
1200                                                          crp);
1201         if (afs_NFSRootOnly && call) {
1202             CREATE3res *resp = (CREATE3res *) xp;
1203             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1204         }
1205     }
1206     curthread->t_cred = svcred;
1207     return;
1208 }
1209
1210 void
1211 afs_nfs3_mkdir(char *args, char *xp, char *exp, char *rp, char *crp)
1212 {
1213     u_int call;
1214     afs_nfs3_resp dummy;
1215     struct cred *svcred = curthread->t_cred;
1216     curthread->t_cred = (struct cred *)crp;
1217     call =
1218         afs_nfs3_dispatcher(0, NFSPROC3_MKDIR, (char *)args, &exp, rp, crp);
1219     if (call > 1)
1220         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1221     else {
1222         (*afs_rfs3_disp_tbl[NFSPROC3_MKDIR].orig_proc) (args, xp, exp, rp,
1223                                                         crp);
1224         if (afs_NFSRootOnly && call) {
1225             MKDIR3res *resp = (MKDIR3res *) xp;
1226             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1227         }
1228     }
1229     curthread->t_cred = svcred;
1230     return;
1231 }
1232
1233 void
1234 afs_nfs3_symlink(char *args, char *xp, char *exp, char *rp, char *crp)
1235 {
1236     u_int call;
1237     afs_nfs3_resp dummy;
1238     struct cred *svcred = curthread->t_cred;
1239     curthread->t_cred = (struct cred *)crp;
1240     call =
1241         afs_nfs3_dispatcher(0, NFSPROC3_SYMLINK, (char *)args, &exp, rp, crp);
1242     if (call > 1)
1243         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1244     else {
1245         (*afs_rfs3_disp_tbl[NFSPROC3_SYMLINK].orig_proc) (args, xp, exp, rp,
1246                                                           crp);
1247         if (afs_NFSRootOnly && call) {
1248             SYMLINK3res *resp = (SYMLINK3res *) xp;
1249             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1250         }
1251     }
1252     curthread->t_cred = svcred;
1253     return;
1254 }
1255
1256 void
1257 afs_nfs3_mknod(char *args, char *xp, char *exp, char *rp, char *crp)
1258 {
1259     u_int call;
1260     afs_nfs3_resp dummy;
1261     struct cred *svcred = curthread->t_cred;
1262     curthread->t_cred = (struct cred *)crp;
1263     call =
1264         afs_nfs3_dispatcher(0, NFSPROC3_MKNOD, (char *)args, &exp, rp, crp);
1265     if (call > 1)
1266         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1267     else {
1268         (*afs_rfs3_disp_tbl[NFSPROC3_MKNOD].orig_proc) (args, xp, exp, rp,
1269                                                         crp);
1270         if (afs_NFSRootOnly && call) {
1271             MKNOD3res *resp = (MKNOD3res *) xp;
1272             afs_nfs3_smallfidder(&resp->resok.obj.handle, resp->status);
1273         }
1274     }
1275     curthread->t_cred = svcred;
1276     return;
1277 }
1278
1279 void
1280 afs_nfs3_remove(char *args, char *xp, char *exp, char *rp, char *crp)
1281 {
1282     u_int call;
1283     afs_nfs3_resp dummy;
1284     struct cred *svcred = curthread->t_cred;
1285     curthread->t_cred = (struct cred *)crp;
1286     call =
1287         afs_nfs3_dispatcher(0, NFSPROC3_REMOVE, (char *)args, &exp, rp, crp);
1288     if (call > 1)
1289         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1290     else
1291         (*afs_rfs3_disp_tbl[NFSPROC3_REMOVE].orig_proc) (args, xp, exp, rp,
1292                                                          crp);
1293     curthread->t_cred = svcred;
1294     return;
1295 }
1296
1297 void
1298 afs_nfs3_rmdir(char *args, char *xp, char *exp, char *rp, char *crp)
1299 {
1300     u_int call;
1301     afs_nfs3_resp dummy;
1302     struct cred *svcred = curthread->t_cred;
1303     curthread->t_cred = (struct cred *)crp;
1304     call =
1305         afs_nfs3_dispatcher(0, NFSPROC3_RMDIR, (char *)args, &exp, rp, crp);
1306     if (call > 1)
1307         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1308     else
1309         (*afs_rfs3_disp_tbl[NFSPROC3_RMDIR].orig_proc) (args, xp, exp, rp,
1310                                                         crp);
1311     curthread->t_cred = svcred;
1312     return;
1313 }
1314
1315 void
1316 afs_nfs3_rename(char *args, char *xp, char *exp, char *rp, char *crp)
1317 {
1318     u_int call;
1319     afs_nfs3_resp dummy;
1320     struct cred *svcred = curthread->t_cred;
1321     curthread->t_cred = (struct cred *)crp;
1322     call =
1323         afs_nfs3_dispatcher(0, NFSPROC3_RENAME, (char *)args, &exp, rp, crp);
1324     if (call > 1)
1325         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1326     else
1327         (*afs_rfs3_disp_tbl[NFSPROC3_RENAME].orig_proc) (args, xp, exp, rp,
1328                                                          crp);
1329     curthread->t_cred = svcred;
1330     return;
1331 }
1332
1333 void
1334 afs_nfs3_link(char *args, char *xp, char *exp, char *rp, char *crp)
1335 {
1336     u_int call;
1337     afs_nfs3_resp dummy;
1338     struct cred *svcred = curthread->t_cred;
1339     curthread->t_cred = (struct cred *)crp;
1340     call = afs_nfs3_dispatcher(0, NFSPROC3_LINK, (char *)args, &exp, rp, crp);
1341     if (call > 1)
1342         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1343     else
1344         (*afs_rfs3_disp_tbl[NFSPROC3_LINK].orig_proc) (args, xp, exp, rp,
1345                                                        crp);
1346     curthread->t_cred = svcred;
1347     return;
1348 }
1349
1350 void
1351 afs_nfs3_readdir(char *args, char *xp, char *exp, char *rp, char *crp)
1352 {
1353     u_int call;
1354     afs_nfs3_resp dummy;
1355     struct cred *svcred = curthread->t_cred;
1356     curthread->t_cred = (struct cred *)crp;
1357     call =
1358         afs_nfs3_dispatcher(0, NFSPROC3_READDIR, (char *)args, &exp, rp, crp);
1359     if (call > 1)
1360         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1361     else
1362         (*afs_rfs3_disp_tbl[NFSPROC3_READDIR].orig_proc) (args, xp, exp, rp,
1363                                                           crp);
1364     curthread->t_cred = svcred;
1365     return;
1366 }
1367
1368 void
1369 afs_nfs3_readdirplus(char *args, char *xp, char *exp, char *rp, char *crp)
1370 {
1371     u_int call;
1372     afs_nfs3_resp dummy;
1373     struct cred *svcred = curthread->t_cred;
1374     curthread->t_cred = (struct cred *)crp;
1375     call =
1376         afs_nfs3_dispatcher(0, NFSPROC3_READDIRPLUS, (char *)args, &exp, rp,
1377                             crp);
1378     if (call > 1)
1379         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1380     else if (call == 1)
1381         afs_nfs3_notsupp((struct afs_nfs3_resp *)xp);
1382     else
1383         (*afs_rfs3_disp_tbl[NFSPROC3_READDIRPLUS].orig_proc) (args, xp, exp,
1384                                                               rp, crp);
1385     curthread->t_cred = svcred;
1386     return;
1387 }
1388
1389 void
1390 afs_nfs3_fsstat(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_FSSTAT, (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_FSSTAT].orig_proc) (args, xp, exp, rp,
1402                                                          crp);
1403     curthread->t_cred = svcred;
1404     return;
1405 }
1406
1407 void
1408 afs_nfs3_fsinfo(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 =
1415         afs_nfs3_dispatcher(0, NFSPROC3_FSINFO, (char *)args, &exp, rp, crp);
1416     if (call > 1)
1417         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1418     else
1419         (*afs_rfs3_disp_tbl[NFSPROC3_FSINFO].orig_proc) (args, xp, exp, rp,
1420                                                          crp);
1421     curthread->t_cred = svcred;
1422     return;
1423 }
1424
1425 void
1426 afs_nfs3_pathconf(char *args, char *xp, char *exp, char *rp, char *crp)
1427 {
1428     u_int call;
1429     afs_nfs3_resp dummy;
1430     struct cred *svcred = curthread->t_cred;
1431     curthread->t_cred = (struct cred *)crp;
1432     call =
1433         afs_nfs3_dispatcher(0, NFSPROC3_PATHCONF, (char *)args, &exp, rp,
1434                             crp);
1435     if (call > 1)
1436         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1437     else
1438         (*afs_rfs3_disp_tbl[NFSPROC3_PATHCONF].orig_proc) (args, xp, exp, rp,
1439                                                            crp);
1440     curthread->t_cred = svcred;
1441     return;
1442 }
1443
1444 void
1445 afs_nfs3_commit(char *args, char *xp, char *exp, char *rp, char *crp)
1446 {
1447     u_int call;
1448     afs_nfs3_resp dummy;
1449     struct cred *svcred = curthread->t_cred;
1450     curthread->t_cred = (struct cred *)crp;
1451     call =
1452         afs_nfs3_dispatcher(0, NFSPROC3_COMMIT, (char *)args, &exp, rp, crp);
1453     if (call > 1)
1454         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1455     else
1456         (*afs_rfs3_disp_tbl[NFSPROC3_COMMIT].orig_proc) (args, xp, exp, rp,
1457                                                          crp);
1458     curthread->t_cred = svcred;
1459     return;
1460 }
1461
1462 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[22] = {
1463     {afs_nfs2_null},
1464     {afs_nfs3_getattr},
1465     {afs_nfs3_setattr},
1466     {afs_nfs3_lookup},
1467     {afs_nfs3_access},
1468     {afs_nfs3_readlink},
1469     {afs_nfs3_read},
1470     {afs_nfs3_write},
1471     {afs_nfs3_create},
1472     {afs_nfs3_mkdir},
1473     {afs_nfs3_symlink},
1474     {afs_nfs3_mknod},
1475     {afs_nfs3_remove},
1476     {afs_nfs3_rmdir},
1477     {afs_nfs3_rename},
1478     {afs_nfs3_link},
1479     {afs_nfs3_readdir},
1480     {afs_nfs3_readdirplus},
1481     {afs_nfs3_fsstat},
1482     {afs_nfs3_fsinfo},
1483     {afs_nfs3_pathconf},
1484     {afs_nfs3_commit}
1485 };
1486
1487 void
1488 afs_acl3_getacl(char *args, char *xp, char *exp, char *rp, char *crp)
1489 {
1490     u_int call;
1491     struct cred *svcred = curthread->t_cred;
1492     curthread->t_cred = (struct cred *)crp;
1493     call =
1494         afs_nfs3_dispatcher(1, ACLPROC3_GETACL, (char *)args, &exp, rp, crp);
1495     if (call > 1)
1496         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1497     else
1498         (*afs_acl3_disp_tbl[ACLPROC3_GETACL].orig_proc) (args, xp, exp, rp,
1499                                                          crp);
1500     curthread->t_cred = svcred;
1501     return;
1502 }
1503
1504 void
1505 afs_acl3_setacl(char *args, char *xp, char *exp, char *rp, char *crp)
1506 {
1507     u_int call;
1508     struct cred *svcred = curthread->t_cred;
1509     curthread->t_cred = (struct cred *)crp;
1510     call =
1511         afs_nfs3_dispatcher(1, ACLPROC3_SETACL, (char *)args, &exp, rp, crp);
1512     if (call > 1)
1513         afs_nfs3_noaccess((struct afs_nfs3_resp *)xp);
1514     else
1515         (*afs_acl3_disp_tbl[ACLPROC3_SETACL].orig_proc) (args, xp, exp, rp,
1516                                                          crp);
1517     curthread->t_cred = svcred;
1518     return;
1519 }
1520
1521 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[3] = {
1522     {afs_nfs2_null},
1523     {afs_acl3_getacl},
1524     {afs_acl3_setacl},
1525 };
1526
1527 /* Munge the dispatch tables to link us in first */
1528 void
1529 afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl,
1530                   struct rfs_disp_tbl *_acl_tbl)
1531 {
1532     int i;
1533
1534     if (xlatorinit_v3_done++)
1535         return;
1536
1537     for (i = 0; i < 22; i++) {
1538         afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
1539         _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
1540     }
1541
1542     for (i = 0; i < 3; i++) {
1543         afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
1544         _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
1545     }
1546 }
1547 #endif /* !defined(AFS_NONFSTRANS) */