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