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