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