nfs-translator-fix-lookup-20021110
[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 = (fhandle_t *)&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 = (fhandle_t *)&sargs->ca_da.da_fhandle;
122         break;
123     }
124     case RFS_REMOVE:
125     {
126         struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
127         fhp1 = (fhandle_t *)&sargs->da_fhandle;
128         break;
129     }
130     case RFS_RENAME:
131     {
132         struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
133         fhp1 = (fhandle_t *)&sargs->rna_from.da_fhandle;
134         fhp2 = (fhandle_t *)&sargs->rna_to.da_fhandle;
135         break;
136     }
137     case RFS_LINK:
138     {
139         struct nfslinkargs *sargs = (struct nfslinkargs *)args;
140         fhp1 = (fhandle_t *)&sargs->la_from;
141         fhp2 = (fhandle_t *)&sargs->la_to.da_fhandle;
142         break;
143     }
144     case RFS_SYMLINK:
145     {
146         struct nfsslargs *sargs = (struct nfsslargs *)args;
147         fhp1 = (fhandle_t *)&sargs->sla_from.da_fhandle;
148         break;
149     }
150     case RFS_MKDIR:
151     {
152         struct nfscreatargs *sargs = (struct nfscreatargs *)args;
153         fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
154         break;
155     }
156     case RFS_RMDIR:
157     {
158         struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
159         fhp1 = (fhandle_t *)&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         fhp1 = (nfs_fh3 *) arg->what.dirp;
682         break;
683     }
684     case NFSPROC3_ACCESS:
685     {
686         ACCESS3args *arg = (ACCESS3args *)args;
687         fhp1 = (nfs_fh3 *) &arg->object;
688         break;
689     }
690     case NFSPROC3_READLINK:
691     {
692         READLINK3args *arg = (READLINK3args *)args;
693         fhp1 = (nfs_fh3 *) &arg->symlink;
694         break;
695     }
696     case NFSPROC3_READ:
697     {
698         READ3args *arg = (READ3args *)args;
699         fhp1 = (nfs_fh3 *) &arg->file;
700         break;
701     }
702     case NFSPROC3_WRITE:
703     {
704         WRITE3args *arg = (WRITE3args *)args;
705         fhp1 = (nfs_fh3 *) &arg->file;
706         break;
707     }
708     case NFSPROC3_CREATE:
709     {
710         CREATE3args *arg = (CREATE3args *)args;
711         fhp1 = (nfs_fh3 *) &arg->where.dir;
712         break;
713     }
714     case NFSPROC3_MKDIR:
715     {
716         MKDIR3args *arg = (MKDIR3args *)args;
717         fhp1 = (nfs_fh3 *) &arg->where.dir;
718         break;
719     }
720     case NFSPROC3_SYMLINK:
721     {
722         SYMLINK3args *arg = (SYMLINK3args *)args;
723         fhp1 = (nfs_fh3 *) &arg->where.dir;
724         break;
725     }
726     case NFSPROC3_MKNOD:
727     {
728         MKNOD3args *arg = (MKNOD3args *)args;
729         fhp1 = (nfs_fh3 *) &arg->where.dir;
730         break;
731     }
732     case NFSPROC3_REMOVE:
733     {
734         REMOVE3args *arg = (REMOVE3args *)args;
735         fhp1 = (nfs_fh3 *) &arg->object.dir;
736         break;
737     }
738     case NFSPROC3_RMDIR:
739     {
740         RMDIR3args *arg = (RMDIR3args *)args;
741         fhp1 = (nfs_fh3 *) &arg->object.dir;
742         break;
743     }
744     case NFSPROC3_RENAME:
745     {
746         RENAME3args *arg = (RENAME3args *)args;
747         fhp1 = (nfs_fh3 *) &arg->from.dir;
748         fhp2 = (nfs_fh3 *) &arg->to.dir;
749         break;
750     }
751     case NFSPROC3_LINK:
752     {
753         LINK3args *arg = (LINK3args *)args;
754         fhp1 = (nfs_fh3 *) &arg->file;
755         fhp2 = (nfs_fh3 *) &arg->link.dir;
756         break;
757     }
758     case NFSPROC3_READDIR:
759     {
760         READDIR3args *arg = (READDIR3args *)args;
761         fhp1 = (nfs_fh3 *) &arg->dir;
762         break;
763     }
764     case NFSPROC3_READDIRPLUS:
765     {
766         READDIRPLUS3args *arg = (READDIRPLUS3args *)args;
767         fhp1 = (nfs_fh3 *) &arg->dir;
768         break;
769     }
770     case NFSPROC3_FSSTAT:
771     {
772         FSSTAT3args *arg = (FSSTAT3args *)args;
773         fhp1 = (nfs_fh3 *) &arg->fsroot;
774         break;
775     }
776     case NFSPROC3_FSINFO:
777     {
778         FSINFO3args *arg = (FSINFO3args *)args;
779         fhp1 = (nfs_fh3 *) &arg->fsroot;
780         break;
781     }
782     case NFSPROC3_PATHCONF:
783     {
784         PATHCONF3args *arg = (PATHCONF3args *)args;
785         fhp1 = (nfs_fh3 *) &arg->object;
786         break;
787     }
788     case NFSPROC3_COMMIT:
789     {
790         COMMIT3args *arg = (COMMIT3args *)args;
791         fhp1 = (nfs_fh3 *) &arg->file;
792         break;
793     }
794     default:
795         return NULL;
796     }
797     
798     if (is_afs_fh3(fhp1)) {
799         *fhpp = fhp1;
800         if (fhp2)
801             *fh2pp = fhp2;
802         return 1;
803     }
804     if (fhp2 && is_afs_fh3(fhp2)) {
805         *fhpp = fhp1;
806         *fh2pp = fhp2;
807         return 1;
808     }
809     return NULL;
810 }
811
812 afs_int32
813 acl3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp)
814 {
815     nfs_fh3 *fhp;
816     
817     switch(which) {
818     case ACLPROC3_GETACL:
819     {
820         struct GETACL3args *sargs = (struct GETACL3args *) args;
821         fhp = &sargs->fh;
822         break;
823     }
824     case ACLPROC3_SETACL:
825     {
826         struct SETACL3args *sargs = (struct SETACL3args *) args;
827         fhp = &sargs->fh;
828         break;
829     }
830     default:
831         return NULL;
832     }
833     
834     if (is_afs_fh3(fhp)) {
835         *fhpp = fhp;
836         return 1;
837     }
838     
839     return NULL;
840 }
841
842 int
843 afs_nfs3_dispatcher(int type, afs_int32 which, char *argp,
844                     struct exportinfo **expp,
845                     struct svc_req *rp, struct AFS_UCRED *crp)
846 {
847     afs_int32 call = 0;
848     afs_int32 code = 0;
849     afs_int32 client = 0;
850     struct sockaddr *sa;
851     nfs_fh3 *fh = (nfs_fh3 *)argp;
852     nfs_fh3 *fh2 = (nfs_fh3 *)0;
853     
854     if (!xlatorinit_v3_done)
855         return 2;
856     
857     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
858     if (sa->sa_family == AF_INET) 
859         client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
860     
861     AFS_GLOCK();
862     code = 0;
863     switch (type) {
864     case 0:
865         code = (client && nfs3_to_afs_call(which, argp, &fh, &fh2));
866         break;
867     case 1:
868         code = (client && acl3_to_afs_call(which, argp, &fh));
869         break;
870     default:
871         break;
872     }
873     
874     if (code) {
875         struct afs_exporter *out = 0;
876         afs_int32 dummy;
877         static int once = 0;
878         struct SmallFid Sfid;
879         
880         memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
881         
882         afs_Trace2(afs_iclSetp, CM_TRACE_NFS3IN1,
883                    ICL_TYPE_INT32, client,
884                    ICL_TYPE_FID, &Sfid);
885
886         call = 1;
887         if (!once && *expp) {
888             afs_nobody = (*expp)->exi_export.ex_anon;
889             once = 1;
890         }
891         code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
892                                         client, &dummy, &out);
893         
894         if (!code && out)
895             EXP_RELE(out);
896         
897         
898         if (code == EINVAL)
899             call = 2;
900     }
901     
902     AFS_GUNLOCK();
903     return call;
904 }
905
906 void
907 afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
908 {
909     afs_int32 addr[2];
910     struct vcache *vcp;
911     
912 #if defined(AFS_SUN57_64BIT_ENV)
913     /* See also afs_fid() */    
914     memcpy((char *)addr, fhp->fh3_data, 10);
915     addr[1] = (addr[1] >> 48) & 0xffff;
916 #else 
917     memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
918 #endif
919     
920     AFS_GLOCK();
921     vcp = VTOAFS((struct vnode*)addr[0]);
922     
923     /* See also afs_osi_vget */
924     if (addr[1] == AFS_XLATOR_MAGIC)
925     {
926         if (status == NFS_OK) {
927             struct SmallFid Sfid;
928             struct cell *tcell;
929             
930             /* Make up and copy out a SmallFid */       
931             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
932             Sfid.Volume = vcp->fid.Fid.Volume;
933             Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
934                                   (vcp->fid.Fid.Unique & 0xffffff));
935             afs_PutCell(tcell, READ_LOCK);
936             Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
937             fhp->fh3_len = SIZEOF_SMALLFID;
938             memcpy(fhp->fh3_data, (char*)&Sfid, fhp->fh3_len);
939
940             afs_Trace3(afs_iclSetp, CM_TRACE_NFS3OUT, ICL_TYPE_INT32, status,
941                        ICL_TYPE_POINTER, vcp, ICL_TYPE_FID, &Sfid);
942         }
943         
944         /* If we have a ref, release it */
945         if (vcp->vrefCount >= 1)
946             AFS_RELE(AFSTOV(vcp));
947     }
948     AFS_GUNLOCK();
949 }
950
951 void afs_nfs3_getattr(char *args, char *xp, char *exp, char *rp, char *crp) { 
952     u_int call; 
953     afs_nfs3_resp dummy; 
954     struct cred *svcred = curthread->t_cred; 
955     curthread->t_cred = (struct cred*)crp; 
956     call=afs_nfs3_dispatcher(0, NFSPROC3_GETATTR, (char *)args, &exp, rp, crp); 
957     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
958     else (*afs_rfs3_disp_tbl[NFSPROC3_GETATTR].orig_proc)(args, xp, exp, rp, crp); 
959     curthread->t_cred = svcred; 
960     return; 
961 }
962
963 void afs_nfs3_setattr(char *args, char *xp, char *exp, char *rp, char *crp) { 
964     u_int call; 
965     afs_nfs3_resp dummy; 
966     struct cred *svcred = curthread->t_cred; 
967     curthread->t_cred = (struct cred*)crp; 
968     call=afs_nfs3_dispatcher(0, NFSPROC3_SETATTR, (char *)args, &exp, rp, crp); 
969     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
970     else (*afs_rfs3_disp_tbl[NFSPROC3_SETATTR].orig_proc)(args, xp, exp, rp, crp); 
971     curthread->t_cred = svcred; 
972     return; 
973 }
974
975 void afs_nfs3_lookup(char *args, char *xp, char *exp, char *rp, char *crp) { 
976     u_int call; 
977     afs_nfs3_resp dummy; 
978     struct cred *svcred = curthread->t_cred; 
979     curthread->t_cred = (struct cred*)crp; 
980     call=afs_nfs3_dispatcher(0, NFSPROC3_LOOKUP, (char *)args, &exp, rp, crp); 
981     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
982     else { (*afs_rfs3_disp_tbl[NFSPROC3_LOOKUP].orig_proc)(args, xp, exp, rp, crp); 
983     if (afs_NFSRootOnly && call) { 
984         LOOKUP3res *resp = ( LOOKUP3res *)xp; 
985         afs_nfs3_smallfidder( &resp->resok.object , resp->status); } } 
986     curthread->t_cred = svcred; 
987     return; 
988 }
989
990 void afs_nfs3_access(char *args, char *xp, char *exp, char *rp, char *crp) { 
991     u_int call; 
992     afs_nfs3_resp dummy; 
993     struct cred *svcred = curthread->t_cred; 
994     curthread->t_cred = (struct cred*)crp; 
995     call=afs_nfs3_dispatcher(0, NFSPROC3_ACCESS, (char *)args, &exp, rp, crp); 
996     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
997     else (*afs_rfs3_disp_tbl[NFSPROC3_ACCESS].orig_proc)(args, xp, exp, rp, crp); 
998     curthread->t_cred = svcred; 
999     return; 
1000 }
1001
1002 void afs_nfs3_readlink(char *args, char *xp, char *exp, char *rp, char *crp) { 
1003     u_int call; 
1004     afs_nfs3_resp dummy; 
1005     struct cred *svcred = curthread->t_cred; 
1006     curthread->t_cred = (struct cred*)crp; 
1007     call=afs_nfs3_dispatcher(0, NFSPROC3_READLINK, (char *)args, &exp, rp, crp); 
1008     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1009     else (*afs_rfs3_disp_tbl[NFSPROC3_READLINK].orig_proc)(args, xp, exp, rp, crp); 
1010     curthread->t_cred = svcred; 
1011     return; 
1012 }
1013
1014 void afs_nfs3_read(char *args, char *xp, char *exp, char *rp, char *crp) { 
1015     u_int call; 
1016     afs_nfs3_resp dummy; 
1017     struct cred *svcred = curthread->t_cred; 
1018     curthread->t_cred = (struct cred*)crp; 
1019     call=afs_nfs3_dispatcher(0, NFSPROC3_READ, (char *)args, &exp, rp, crp); 
1020     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1021     else (*afs_rfs3_disp_tbl[NFSPROC3_READ].orig_proc)(args, xp, exp, rp, crp); 
1022     curthread->t_cred = svcred; 
1023     return; 
1024 }
1025
1026 void afs_nfs3_write(char *args, char *xp, char *exp, char *rp, char *crp) { 
1027     u_int call; 
1028     afs_nfs3_resp dummy; 
1029     struct cred *svcred = curthread->t_cred; 
1030     curthread->t_cred = (struct cred*)crp; 
1031     call=afs_nfs3_dispatcher(0, NFSPROC3_WRITE, (char *)args, &exp, rp, crp); 
1032     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1033     else (*afs_rfs3_disp_tbl[NFSPROC3_WRITE].orig_proc)(args, xp, exp, rp, crp); 
1034     curthread->t_cred = svcred; 
1035     return; 
1036 }
1037 void afs_nfs3_create(char *args, char *xp, char *exp, char *rp, char *crp) { 
1038     u_int call; 
1039     afs_nfs3_resp dummy; 
1040     struct cred *svcred = curthread->t_cred; 
1041     curthread->t_cred = (struct cred*)crp; 
1042     call=afs_nfs3_dispatcher(0, NFSPROC3_CREATE, (char *)args, &exp, rp, crp); 
1043     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1044     else { (*afs_rfs3_disp_tbl[NFSPROC3_CREATE].orig_proc)(args, xp, exp, rp, crp); 
1045     if (afs_NFSRootOnly && call) { 
1046         CREATE3res *resp = ( CREATE3res *)xp; 
1047         afs_nfs3_smallfidder( &resp->resok.obj.handle , resp->status); } } 
1048     curthread->t_cred = svcred; 
1049     return; 
1050 }
1051
1052 void afs_nfs3_mkdir(char *args, char *xp, char *exp, char *rp, char *crp) { 
1053     u_int call; 
1054     afs_nfs3_resp dummy; 
1055     struct cred *svcred = curthread->t_cred; 
1056     curthread->t_cred = (struct cred*)crp; 
1057     call=afs_nfs3_dispatcher(0, NFSPROC3_MKDIR, (char *)args, &exp, rp, crp); 
1058     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1059     else { (*afs_rfs3_disp_tbl[NFSPROC3_MKDIR].orig_proc)(args, xp, exp, rp, crp); 
1060     if (afs_NFSRootOnly && call) { 
1061         MKDIR3res *resp = ( MKDIR3res *)xp; 
1062         afs_nfs3_smallfidder( &resp->resok.obj.handle , resp->status); } } 
1063     curthread->t_cred = svcred; 
1064     return; 
1065 }
1066
1067 void afs_nfs3_symlink(char *args, char *xp, char *exp, char *rp, char *crp) { 
1068     u_int call; 
1069     afs_nfs3_resp dummy; 
1070     struct cred *svcred = curthread->t_cred; 
1071     curthread->t_cred = (struct cred*)crp; 
1072     call=afs_nfs3_dispatcher(0, NFSPROC3_SYMLINK, (char *)args, &exp, rp, crp); 
1073     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1074     else { (*afs_rfs3_disp_tbl[NFSPROC3_SYMLINK].orig_proc)(args, xp, exp, rp, crp); 
1075     if (afs_NFSRootOnly && call) {
1076         SYMLINK3res *resp = ( SYMLINK3res *)xp;
1077         afs_nfs3_smallfidder( &resp->resok.obj.handle , resp->status); } }
1078     curthread->t_cred = svcred; 
1079     return; 
1080 }
1081
1082 void afs_nfs3_mknod(char *args, char *xp, char *exp, char *rp, char *crp) { 
1083     u_int call; 
1084     afs_nfs3_resp dummy; 
1085     struct cred *svcred = curthread->t_cred; 
1086     curthread->t_cred = (struct cred*)crp; 
1087     call=afs_nfs3_dispatcher(0, NFSPROC3_MKNOD, (char *)args, &exp, rp, crp); 
1088     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1089     else { (*afs_rfs3_disp_tbl[NFSPROC3_MKNOD].orig_proc)(args, xp, exp, rp, crp); 
1090     if (afs_NFSRootOnly && call) {
1091         MKNOD3res *resp = ( MKNOD3res *)xp;
1092         afs_nfs3_smallfidder( &resp->resok.obj.handle , resp->status); } }
1093     curthread->t_cred = svcred; 
1094     return; 
1095 }
1096
1097 void afs_nfs3_remove(char *args, char *xp, char *exp, char *rp, char *crp) { 
1098     u_int call; 
1099     afs_nfs3_resp dummy; 
1100     struct cred *svcred = curthread->t_cred; 
1101     curthread->t_cred = (struct cred*)crp; 
1102     call=afs_nfs3_dispatcher(0, NFSPROC3_REMOVE, (char *)args, &exp, rp, crp); 
1103     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1104     else (*afs_rfs3_disp_tbl[NFSPROC3_REMOVE].orig_proc)(args, xp, exp, rp, crp); 
1105     curthread->t_cred = svcred; 
1106     return; 
1107 }
1108
1109 void afs_nfs3_rmdir(char *args, char *xp, char *exp, char *rp, char *crp) { 
1110     u_int call; 
1111     afs_nfs3_resp dummy; 
1112     struct cred *svcred = curthread->t_cred; 
1113     curthread->t_cred = (struct cred*)crp; 
1114     call=afs_nfs3_dispatcher(0, NFSPROC3_RMDIR, (char *)args, &exp, rp, crp); 
1115     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1116     else (*afs_rfs3_disp_tbl[NFSPROC3_RMDIR].orig_proc)(args, xp, exp, rp, crp); 
1117     curthread->t_cred = svcred; 
1118     return; 
1119 }
1120
1121 void afs_nfs3_rename(char *args, char *xp, char *exp, char *rp, char *crp) { 
1122     u_int call; 
1123     afs_nfs3_resp dummy; 
1124     struct cred *svcred = curthread->t_cred; 
1125     curthread->t_cred = (struct cred*)crp; 
1126     call=afs_nfs3_dispatcher(0, NFSPROC3_RENAME, (char *)args, &exp, rp, crp); 
1127     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1128     else (*afs_rfs3_disp_tbl[NFSPROC3_RENAME].orig_proc)(args, xp, exp, rp, crp); 
1129     curthread->t_cred = svcred; 
1130     return; 
1131 }
1132
1133 void afs_nfs3_link(char *args, char *xp, char *exp, char *rp, char *crp) { 
1134     u_int call; 
1135     afs_nfs3_resp dummy; 
1136     struct cred *svcred = curthread->t_cred; 
1137     curthread->t_cred = (struct cred*)crp; 
1138     call=afs_nfs3_dispatcher(0, NFSPROC3_LINK, (char *)args, &exp, rp, crp); 
1139     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1140     else (*afs_rfs3_disp_tbl[NFSPROC3_LINK].orig_proc)(args, xp, exp, rp, crp); 
1141     curthread->t_cred = svcred; 
1142     return; 
1143 }
1144
1145 void afs_nfs3_readdir(char *args, char *xp, char *exp, char *rp, char *crp) { 
1146     u_int call; 
1147     afs_nfs3_resp dummy; 
1148     struct cred *svcred = curthread->t_cred; 
1149     curthread->t_cred = (struct cred*)crp; 
1150     call=afs_nfs3_dispatcher(0, NFSPROC3_READDIR, (char *)args, &exp, rp, crp); 
1151     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1152     else (*afs_rfs3_disp_tbl[NFSPROC3_READDIR].orig_proc)(args, xp, exp, rp, crp); 
1153     curthread->t_cred = svcred; 
1154     return; 
1155 }
1156
1157 void afs_nfs3_readdirplus(char *args, char *xp, char *exp, char *rp, char *crp) { 
1158     u_int call; 
1159     afs_nfs3_resp dummy; 
1160     struct cred *svcred = curthread->t_cred; 
1161     curthread->t_cred = (struct cred*)crp; 
1162     call=afs_nfs3_dispatcher(0, NFSPROC3_READDIRPLUS, (char *)args, &exp, rp, crp); 
1163     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1164     else (*afs_rfs3_disp_tbl[NFSPROC3_READDIRPLUS].orig_proc)(args, xp, exp, rp, crp); 
1165     curthread->t_cred = svcred; 
1166     return; 
1167 }
1168
1169 void afs_nfs3_fsstat(char *args, char *xp, char *exp, char *rp, char *crp) { 
1170     u_int call; 
1171     afs_nfs3_resp dummy; 
1172     struct cred *svcred = curthread->t_cred; 
1173     curthread->t_cred = (struct cred*)crp; 
1174     call=afs_nfs3_dispatcher(0, NFSPROC3_FSSTAT, (char *)args, &exp, rp, crp); 
1175     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1176     else (*afs_rfs3_disp_tbl[NFSPROC3_FSSTAT].orig_proc)(args, xp, exp, rp, crp); 
1177     curthread->t_cred = svcred; 
1178     return; 
1179 }
1180
1181 void afs_nfs3_fsinfo(char *args, char *xp, char *exp, char *rp, char *crp) { 
1182     u_int call; 
1183     afs_nfs3_resp dummy; 
1184     struct cred *svcred = curthread->t_cred; 
1185     curthread->t_cred = (struct cred*)crp; 
1186     call=afs_nfs3_dispatcher(0, NFSPROC3_FSINFO, (char *)args, &exp, rp, crp); 
1187     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1188     else (*afs_rfs3_disp_tbl[NFSPROC3_FSINFO].orig_proc)(args, xp, exp, rp, crp); 
1189     curthread->t_cred = svcred; 
1190     return; 
1191 }
1192
1193 void afs_nfs3_pathconf(char *args, char *xp, char *exp, char *rp, char *crp) { 
1194     u_int call; 
1195     afs_nfs3_resp dummy; 
1196     struct cred *svcred = curthread->t_cred; 
1197     curthread->t_cred = (struct cred*)crp; 
1198     call=afs_nfs3_dispatcher(0, NFSPROC3_PATHCONF, (char *)args, &exp, rp, crp); 
1199     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1200     else (*afs_rfs3_disp_tbl[NFSPROC3_PATHCONF].orig_proc)(args, xp, exp, rp, crp); 
1201     curthread->t_cred = svcred; 
1202     return; 
1203 }
1204
1205 void afs_nfs3_commit(char *args, char *xp, char *exp, char *rp, char *crp) { 
1206     u_int call; 
1207     afs_nfs3_resp dummy; 
1208     struct cred *svcred = curthread->t_cred; 
1209     curthread->t_cred = (struct cred*)crp; 
1210     call=afs_nfs3_dispatcher(0, NFSPROC3_COMMIT, (char *)args, &exp, rp, crp); 
1211     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1212     else (*afs_rfs3_disp_tbl[NFSPROC3_COMMIT].orig_proc)(args, xp, exp, rp, crp); 
1213     curthread->t_cred = svcred; 
1214     return; 
1215 }
1216
1217 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[22] = {
1218     { afs_nfs2_null },
1219     { afs_nfs3_getattr },
1220     { afs_nfs3_setattr },
1221     { afs_nfs3_lookup },
1222     { afs_nfs3_access },
1223     { afs_nfs3_readlink },
1224     { afs_nfs3_read },
1225     { afs_nfs3_write },
1226     { afs_nfs3_create },
1227     { afs_nfs3_mkdir },
1228     { afs_nfs3_symlink },
1229     { afs_nfs3_mknod },
1230     { afs_nfs3_remove },
1231     { afs_nfs3_rmdir },
1232     { afs_nfs3_rename },
1233     { afs_nfs3_link },
1234     { afs_nfs3_readdir },
1235     { afs_nfs3_readdirplus },
1236     { afs_nfs3_fsstat },
1237     { afs_nfs3_fsinfo },
1238     { afs_nfs3_pathconf },
1239     { afs_nfs3_commit }
1240 };
1241
1242 void afs_acl3_getacl(char *args, char *xp, char *exp, char *rp, char *crp) { 
1243     u_int call; 
1244     struct cred *svcred = curthread->t_cred; 
1245     curthread->t_cred = (struct cred*)crp; 
1246     call=afs_nfs3_dispatcher(1, ACLPROC3_GETACL, (char *)args, &exp, rp, crp); 
1247     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1248     else (*afs_acl3_disp_tbl[ACLPROC3_GETACL].orig_proc)(args, xp, exp, rp, crp); 
1249     curthread->t_cred = svcred; 
1250     return; 
1251 }
1252
1253 void afs_acl3_setacl(char *args, char *xp, char *exp, char *rp, char *crp) { 
1254     u_int call; 
1255     struct cred *svcred = curthread->t_cred; 
1256     curthread->t_cred = (struct cred*)crp; 
1257     call=afs_nfs3_dispatcher(1, ACLPROC3_SETACL, (char *)args, &exp, rp, crp); 
1258     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); 
1259     else (*afs_acl3_disp_tbl[ACLPROC3_SETACL].orig_proc)(args, xp, exp, rp, crp); 
1260     curthread->t_cred = svcred; 
1261     return; 
1262 }
1263
1264 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[3] = {
1265     { afs_nfs2_null },
1266     { afs_acl3_getacl },
1267     { afs_acl3_setacl },
1268 };
1269
1270 /* Munge the dispatch tables to link us in first */
1271 void
1272 afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl,
1273                   struct rfs_disp_tbl *_acl_tbl)
1274 {
1275     int i;
1276     
1277     if (xlatorinit_v3_done++) return;
1278     
1279     for (i=0; i < 22; i++) {
1280         afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
1281         _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
1282     }
1283     
1284     for (i=0; i < 3; i++) {
1285         afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
1286         _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
1287     }
1288 }
1289 #endif /* !defined(AFS_NONFSTRANS) */