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