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