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