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