801cc9bd82ce514bbab227581b4cfae2ed39739f
[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 #include "../afs/stds.h"
16 #include "../afs/sysincludes.h" /* Standard vendor system headers */
17 #if defined(AFS_SUN55_ENV) && !defined(AFS_NONFSTRANS) 
18 #include "../rpc/types.h"
19 #include "../rpc/auth.h"
20 #include "../rpc/auth_unix.h"
21 #include "../rpc/auth_des.h"
22 #if !defined(AFS_SUN58_ENV)
23 #include "../rpc/auth_kerb.h"
24 #endif
25 #include "../sys/tiuser.h"
26 #include "../rpc/xdr.h"
27 #include "../rpc/svc.h"
28 #include "../nfs/nfs.h"
29 #include "../nfs/export.h"
30 #include "../nfs/nfs_clnt.h"
31 #include "../nfs/nfs_acl.h"
32 #include "../afs/afsincludes.h" 
33 #include "../afs/afs_stats.h"   
34 #include "../afs/exporter.h"
35
36 static int xlatorinit_v2_done=0;
37 static int xlatorinit_v3_done=0;
38
39 extern int afs_nobody;
40 extern int afs_NFSRootOnly;
41
42 /* It's bigger than this, but we don't care about anything else */
43 struct rfs_disp_tbl {
44         void  (*dis_proc)();    
45 };
46
47 struct afs_nfs_disp_tbl {
48     void (*afs_proc)();
49     void (*orig_proc)();
50 };
51
52 struct afs_nfs2_resp {
53     enum nfsstat status;
54 };
55
56 #ifndef ACL2_NPROC
57 #define ACL2_NPROC      5
58 #endif
59
60 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC];
61 struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC];
62
63 static int 
64 is_afs_fh(fhandle_t *fhp) {
65     if ((fhp->fh_fsid.val[0] == AFS_VFSMAGIC) &&
66         (fhp->fh_fsid.val[1] == AFS_VFSFSID)) 
67         return 1;
68     return 0;
69 }
70
71 afs_int32 
72 nfs2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp, fhandle_t **fh2pp)
73 {
74     struct vnode *vp;
75     fhandle_t *fhp1=0;
76     fhandle_t *fhp2=0;
77     int errorcode;
78
79     *fh2pp = (fhandle_t *)0;
80     switch (which) {
81         case RFS_GETATTR:
82         case RFS_READLINK:
83         case RFS_STATFS:
84             fhp1 = (fhandle_t *)args;
85             break;
86         case RFS_SETATTR: 
87         {
88             struct nfssaargs *sargs = (struct nfssaargs *)args; 
89             fhp1 = (fhandle_t *)&sargs->saa_fh;
90             break;
91         } 
92         case RFS_LOOKUP: 
93         {
94             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
95             fhp1 = (fhandle_t *)&sargs->da_fhandle;
96             break;
97         } 
98         case RFS_READ:
99         {
100             struct nfsreadargs *sargs = (struct nfsreadargs *)args;
101             fhp1 = (fhandle_t *)&sargs->ra_fhandle;
102             break;
103         } 
104         case RFS_WRITE: 
105         {
106             struct nfswriteargs *sargs = (struct nfswriteargs *)args;
107             fhp1 = (fhandle_t *)&sargs->wa_fhandle;
108             break;
109         } 
110         case RFS_CREATE: 
111         {
112             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
113             fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
114             break;
115         } 
116         case RFS_REMOVE: 
117         {
118             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
119             fhp1 = (fhandle_t *)&sargs->da_fhandle;
120             break;
121         }
122         case RFS_RENAME: 
123         {
124             struct nfsrnmargs *sargs = (struct nfsrnmargs *)args;
125             fhp1 = (fhandle_t *)&sargs->rna_from.da_fhandle;
126             fhp2 = (fhandle_t *)&sargs->rna_to.da_fhandle;
127             break;
128         } 
129         case RFS_LINK: 
130         {
131             struct nfslinkargs *sargs = (struct nfslinkargs *)args;
132             fhp1 = (fhandle_t *)&sargs->la_from;
133             fhp2 = (fhandle_t *)&sargs->la_to.da_fhandle;
134             break;
135         } 
136         case RFS_SYMLINK: 
137         {
138             struct nfsslargs *sargs = (struct nfsslargs *)args;
139             fhp1 = (fhandle_t *)&sargs->sla_from.da_fhandle;
140             break;
141         } 
142         case RFS_MKDIR: 
143         {
144             struct nfscreatargs *sargs = (struct nfscreatargs *)args;
145             fhp1 = (fhandle_t *)&sargs->ca_da.da_fhandle;
146             break;
147         } 
148         case RFS_RMDIR: 
149         {
150             struct nfsdiropargs *sargs = (struct nfsdiropargs *)args;
151             fhp1 = (fhandle_t *)&sargs->da_fhandle;
152             break;
153         } 
154         case RFS_READDIR: 
155         {
156             struct nfsrddirargs *sargs = (struct nfsrddirargs *)args;
157             fhp1 = (fhandle_t *)&sargs->rda_fh;
158             break;
159         } 
160         default:
161             return NULL;
162     }
163
164     /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
165     if (is_afs_fh(fhp1)) {
166         *fhpp = fhp1;
167         if (fhp2) 
168             *fh2pp = fhp2;
169         return 1;           
170     }
171     if (is_afs_fh(fhp2)) {
172         *fhpp = fhp1;
173         *fh2pp = fhp2;
174         return 1;           
175     }
176     return NULL;
177 }
178
179 afs_int32 
180 acl2_to_afs_call(int which, caddr_t *args, fhandle_t **fhpp)
181 {
182     fhandle_t *fhp;
183
184     switch(which) {
185     case ACLPROC2_NULL:
186     {
187         return NULL;
188     }
189     case ACLPROC2_GETACL: 
190     {
191         struct GETACL2args *sargs = (struct GETACL2args *) args;
192         fhp = &sargs->fh;
193         break;
194     }
195     case ACLPROC2_SETACL: 
196     {
197         struct SETACL2args *sargs = (struct SETACL2args *) args;
198         fhp = &sargs->fh;
199         break;
200     }
201     case ACLPROC2_GETATTR: 
202     {
203         struct GETATTR2args *sargs = (struct GETATTR2args *) args;
204         fhp = &sargs->fh;
205         break;
206     }
207     case ACLPROC2_ACCESS: 
208     {
209         struct ACCESS2args *sargs = (struct ACCESS2args *) args;
210         fhp = &sargs->fh;
211         break;
212     }
213     default:
214         return NULL;
215     }
216
217     if (is_afs_fh(fhp)) {
218         *fhpp = fhp;
219         return 1;
220     }
221
222     return NULL;
223 }
224
225 int
226 afs_nfs2_dispatcher(int type, afs_int32 which, char *argp, 
227                     struct exportinfo **expp, 
228                     struct svc_req *rp, struct AFS_UCRED *crp)
229 {
230     afs_int32 call = 0;
231     afs_int32 code = 0;
232     afs_int32 client = 0;
233     struct sockaddr *sa;
234     fhandle_t *fh = (fhandle_t *)argp;
235     fhandle_t *fh2 = (fhandle_t *)0;
236
237     if (!xlatorinit_v2_done)
238         return 2;
239
240     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
241     client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
242
243     AFS_GLOCK();
244     code = 0;
245     switch (type) {
246     case 0:
247         code = nfs2_to_afs_call(which, argp, &fh, &fh2);
248         break;
249     case 1:
250         code = acl2_to_afs_call(which, argp, &fh);
251         break;
252     default:
253         break;
254     }
255
256     if (code) {
257         struct afs_exporter *out = 0;
258         afs_int32 dummy;
259         static int once = 0;
260         struct SmallFid Sfid;
261
262         memcpy((char *)&Sfid, fh->fh_data, SIZEOF_SMALLFID);
263
264         /* We ran */
265         call = 1;
266         if (!once && *expp) {
267             afs_nobody = (*expp)->exi_export.ex_anon;
268             once = 1;
269         }
270         code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
271                                         client, &dummy, &out);
272         /* Be careful to release this */
273         if (!code && out)
274             EXP_RELE(out);
275
276         /* We ran and failed */
277         if (code == EINVAL) 
278             call = 2;
279     }
280
281     AFS_GUNLOCK();
282     return call;
283 }
284
285 void 
286 afs_nfs2_smallfidder(struct nfsdiropres *dr)
287 {
288     register fhandle_t *fhp = (fhandle_t *)&dr->dr_fhandle;
289     afs_int32 addr[2];
290     struct vcache *vcp;
291
292 #if defined(AFS_SUN57_64BIT_ENV)
293     /* See also afs_fid() */    
294     memcpy((char *)addr, fhp->fh_data, 10);
295     addr[1] = (addr[1] >> 48) & 0xffff;
296 #else 
297     memcpy((char *)addr, fhp->fh_data, 2 * sizeof(long));
298 #endif
299
300     AFS_GLOCK();
301     vcp = VTOAFS((struct vnode*)addr[0]);
302
303     /* See also afs_osi_vget */
304     if (addr[1] == AFS_XLATOR_MAGIC)
305     {
306         if (dr->dr_status == NFS_OK) {
307             struct SmallFid Sfid;
308             struct cell *tcell;
309
310             /* Make up and copy out a SmallFid */
311             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
312             Sfid.Volume = vcp->fid.Fid.Volume;
313             Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
314                                   (vcp->fid.Fid.Unique & 0xffffff));
315             afs_PutCell(tcell, READ_LOCK);
316             Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
317             fhp->fh_len = SIZEOF_SMALLFID;
318             memcpy(dr->dr_fhandle.fh_data, (char*)&Sfid, fhp->fh_len);
319         }
320
321         /* If we have a ref, release it */
322         if (vcp->vrefCount >= 1) 
323             AFS_RELE(AFSTOV(vcp));
324     } 
325     AFS_GUNLOCK();
326 }
327
328 void
329 afs_nfs2_noaccess(struct afs_nfs2_resp *resp)
330 {
331     resp->status = NFSERR_ACCES;
332 }
333
334 void afs_nfs2_null(char *args, char *xp, char *exp, char *rp, char *crp)
335 {
336 }
337
338 void 
339 afs_nfs2_root(char *args, char *xp, char *exp, char *rp, char *crp)
340 {
341 }
342
343 void 
344 afs_nfs2_writecache(char *args, char *xp, char *exp, char *rp, char *crp)
345 {
346 }
347
348 #define NFS_V2_REQ(FUNCNAME, RFSOP, POST) \
349 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
350     u_int call; \
351     struct cred *svcred = curthread->t_cred; \
352     curthread->t_cred = (struct cred*)crp; \
353     call=afs_nfs2_dispatcher(0, RFSOP, (char *)args, &exp, rp, crp); \
354     if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
355     else { (*afs_rfs_disp_tbl[RFSOP].orig_proc)(args, xp, exp, rp, crp); \
356     if (POST && afs_NFSRootOnly && call) afs_nfs2_smallfidder(xp); } \
357     curthread->t_cred = svcred; \
358     return; \
359 }
360
361 NFS_V2_REQ(afs_nfs2_getattr, RFS_GETATTR, 0) 
362 NFS_V2_REQ(afs_nfs2_setattr, RFS_SETATTR, 0)
363 NFS_V2_REQ(afs_nfs2_lookup, RFS_LOOKUP, 1)
364 NFS_V2_REQ(afs_nfs2_readlink, RFS_READLINK, 0)
365 NFS_V2_REQ(afs_nfs2_read, RFS_READ, 0)
366 NFS_V2_REQ(afs_nfs2_write, RFS_WRITE, 0)
367 NFS_V2_REQ(afs_nfs2_create, RFS_CREATE, 1)
368 NFS_V2_REQ(afs_nfs2_remove, RFS_REMOVE, 0)
369 NFS_V2_REQ(afs_nfs2_rename, RFS_RENAME, 0)
370 NFS_V2_REQ(afs_nfs2_link, RFS_LINK, 0)
371 NFS_V2_REQ(afs_nfs2_symlink, RFS_SYMLINK, 0)
372 NFS_V2_REQ(afs_nfs2_mkdir, RFS_MKDIR, 1)
373 NFS_V2_REQ(afs_nfs2_rmdir, RFS_RMDIR, 0)
374 NFS_V2_REQ(afs_nfs2_readdir, RFS_READDIR, 0)
375 NFS_V2_REQ(afs_nfs2_statfs, RFS_STATFS, 0)
376
377 struct afs_nfs_disp_tbl afs_rfs_disp_tbl[RFS_NPROC] = {
378     { afs_nfs2_null },
379     { afs_nfs2_getattr },
380     { afs_nfs2_setattr },
381     { afs_nfs2_root },
382     { afs_nfs2_lookup },
383     { afs_nfs2_readlink },
384     { afs_nfs2_read },
385     { afs_nfs2_writecache },    
386     { afs_nfs2_write },
387     { afs_nfs2_create },
388     { afs_nfs2_remove },        
389     { afs_nfs2_rename },
390     { afs_nfs2_link },  
391     { afs_nfs2_symlink },
392     { afs_nfs2_mkdir },
393     { afs_nfs2_rmdir },
394     { afs_nfs2_readdir },
395     { afs_nfs2_statfs }
396 };
397
398 #define ACL_V2_REQ(FUNCNAME, ACLOP) \
399 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
400     u_int call; \
401     struct cred *svcred = curthread->t_cred; \
402     curthread->t_cred = (struct cred*)crp; \
403     call=afs_nfs2_dispatcher(1, ACLOP, (char *)args, &exp, rp, crp); \
404     if (call>1) afs_nfs2_noaccess((struct afs_nfs2_resp *)xp); \
405     else (*afs_rfs_disp_tbl[ACLOP].orig_proc)(args, xp, exp, rp, crp); \
406     curthread->t_cred = svcred; \
407     return; \
408 }
409
410 ACL_V2_REQ(afs_acl2_getacl, ACLPROC2_GETACL)
411 ACL_V2_REQ(afs_acl2_setacl, ACLPROC2_SETACL)
412 ACL_V2_REQ(afs_acl2_getattr, ACLPROC2_GETATTR)
413 ACL_V2_REQ(afs_acl2_access, ACLPROC2_ACCESS)
414
415 struct afs_nfs_disp_tbl afs_acl_disp_tbl[ACL2_NPROC] = {
416     { afs_nfs2_null }, 
417     { afs_acl2_getacl }, 
418     { afs_acl2_setacl },
419     { afs_acl2_getattr }, 
420     { afs_acl2_access } 
421 };
422
423 /* Munge the dispatch tables to link us in first */
424 void 
425 afs_xlatorinit_v2(struct rfs_disp_tbl *_rfs_tbl, 
426                   struct rfs_disp_tbl *_acl_tbl)
427 {
428     int i;
429
430     if (xlatorinit_v2_done++) return;
431
432     for (i=0; i < RFS_NPROC; i++) {
433         afs_rfs_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
434         _rfs_tbl[i].dis_proc = afs_rfs_disp_tbl[i].afs_proc;
435     }
436
437     for (i=0; i < ACL2_NPROC; i++) {
438         afs_acl_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
439         _acl_tbl[i].dis_proc = afs_acl_disp_tbl[i].afs_proc;
440     }
441 }
442
443 #ifndef RFS3_NPROC
444 #define RFS3_NPROC      22
445 #endif
446
447 #ifndef ACL3_NPROC
448 #define ACL3_NPROC      3
449 #endif
450
451 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC];
452 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC];
453
454 struct afs_nfs3_resp {
455     nfsstat3 status;
456     bool_t flags; 
457 };
458 typedef struct afs_nfs3_resp afs_nfs3_resp;
459
460 static int 
461 is_afs_fh3(nfs_fh3 *fhp) {
462     if ((fhp->fh3_fsid.val[0] == AFS_VFSMAGIC) &&
463         (fhp->fh3_fsid.val[1] == AFS_VFSFSID)) 
464         return 1;
465     return 0;
466 }
467
468 void
469 afs_nfs3_noaccess(struct afs_nfs3_resp *resp)
470 {
471     resp->status = NFS3ERR_ACCES;
472     resp->flags = FALSE;
473 }
474
475 afs_int32 
476 nfs3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp, nfs_fh3 **fh2pp)
477 {
478     struct vnode *vp;
479     nfs_fh3 *fhp1=0;
480     nfs_fh3 *fhp2=0;
481     int errorcode;
482
483     *fh2pp = (nfs_fh3 *)0;
484     switch (which) {
485         case NFSPROC3_GETATTR: 
486         {
487             GETATTR3args *arg = (GETATTR3args *)args;
488             fhp1 = (nfs_fh3 *) &arg->object;
489             break;
490         } 
491         case NFSPROC3_SETATTR: 
492         {
493             SETATTR3args *arg = (SETATTR3args *)args;
494             fhp1 = (nfs_fh3 *) &arg->object;
495             break;
496         } 
497         case NFSPROC3_LOOKUP: 
498         {
499             LOOKUP3args *arg = (LOOKUP3args *)args;
500             fhp1 = (nfs_fh3 *) &arg->what.dirp;
501             break;
502         } 
503         case NFSPROC3_ACCESS: 
504         {
505             ACCESS3args *arg = (ACCESS3args *)args;
506             fhp1 = (nfs_fh3 *) &arg->object;
507             break;
508         } 
509         case NFSPROC3_READLINK: 
510         {
511             READLINK3args *arg = (READLINK3args *)args;
512             fhp1 = (nfs_fh3 *) &arg->symlink;       
513             break;
514         } 
515         case NFSPROC3_READ: 
516         {
517             READ3args *arg = (READ3args *)args;
518             fhp1 = (nfs_fh3 *) &arg->file;
519             break;
520         } 
521         case NFSPROC3_WRITE: 
522         {
523             WRITE3args *arg = (WRITE3args *)args;
524             fhp1 = (nfs_fh3 *) &arg->file;
525             break;
526         } 
527         case NFSPROC3_CREATE: 
528         {
529             CREATE3args *arg = (CREATE3args *)args;
530             fhp1 = (nfs_fh3 *) &arg->where.dir;
531             break;
532         } 
533         case NFSPROC3_MKDIR: 
534         {
535             MKDIR3args *arg = (MKDIR3args *)args;
536             fhp1 = (nfs_fh3 *) &arg->where.dir;
537             break;
538         } 
539         case NFSPROC3_SYMLINK: 
540         {
541             SYMLINK3args *arg = (SYMLINK3args *)args;
542             fhp1 = (nfs_fh3 *) &arg->where.dir;
543             break;
544         } 
545         case NFSPROC3_MKNOD:
546         {
547             MKNOD3args *arg = (MKNOD3args *)args;
548             fhp1 = (nfs_fh3 *) &arg->where.dir;
549             break;
550         } 
551         case NFSPROC3_REMOVE: 
552         {
553             REMOVE3args *arg = (REMOVE3args *)args;
554             fhp1 = (nfs_fh3 *) &arg->object.dir;
555             break;
556         } 
557         case NFSPROC3_RMDIR: 
558         {
559             RMDIR3args *arg = (RMDIR3args *)args;
560             fhp1 = (nfs_fh3 *) &arg->object.dir;
561             break;
562         } 
563         case NFSPROC3_RENAME: 
564         {
565             RENAME3args *arg = (RENAME3args *)args;
566             fhp1 = (nfs_fh3 *) &arg->from.dir;
567             fhp2 = (nfs_fh3 *) &arg->to.dir;
568             break;
569         } 
570         case NFSPROC3_LINK: 
571         {
572             LINK3args *arg = (LINK3args *)args;
573             fhp1 = (nfs_fh3 *) &arg->file;
574             fhp2 = (nfs_fh3 *) &arg->link.dir;
575             break;
576         } 
577         case NFSPROC3_READDIR: 
578         {
579             READDIR3args *arg = (READDIR3args *)args;
580             fhp1 = (nfs_fh3 *) &arg->dir;
581             break;
582         } 
583         case NFSPROC3_READDIRPLUS: 
584         {
585             READDIRPLUS3args *arg = (READDIRPLUS3args *)args;
586             fhp1 = (nfs_fh3 *) &arg->dir;
587             break;
588         } 
589         case NFSPROC3_FSSTAT: 
590         {
591             FSSTAT3args *arg = (FSSTAT3args *)args;
592             fhp1 = (nfs_fh3 *) &arg->fsroot;
593             break;
594         } 
595         case NFSPROC3_FSINFO: 
596         {
597             FSINFO3args *arg = (FSINFO3args *)args;
598             fhp1 = (nfs_fh3 *) &arg->fsroot;
599             break;
600         } 
601         case NFSPROC3_PATHCONF: 
602         {
603             PATHCONF3args *arg = (PATHCONF3args *)args;
604             fhp1 = (nfs_fh3 *) &arg->object;
605             break;
606         } 
607         case NFSPROC3_COMMIT: 
608         {
609             COMMIT3args *arg = (COMMIT3args *)args;
610             fhp1 = (nfs_fh3 *) &arg->file;
611             break;
612         }
613         default:
614             return NULL;
615     }
616
617     /* Ok if arg 1 is in AFS or if 2 args and arg 2 is in AFS */
618     if (is_afs_fh3(fhp1)) {
619         *fhpp = fhp1;
620         if (fhp2) 
621             *fh2pp = fhp2;
622         return 1;           
623     }
624     if (is_afs_fh3(fhp2)) {
625         *fhpp = fhp1;
626         *fh2pp = fhp2;
627         return 1;           
628     }
629     return NULL;
630 }
631
632 afs_int32 
633 acl3_to_afs_call(int which, caddr_t *args, nfs_fh3 **fhpp)
634 {
635     nfs_fh3 *fhp;
636
637     switch(which) {
638     case ACLPROC3_GETACL: 
639     {
640         struct GETACL3args *sargs = (struct GETACL3args *) args;
641         fhp = &sargs->fh;
642         break;
643     }
644     case ACLPROC3_SETACL: 
645     {
646         struct SETACL3args *sargs = (struct SETACL3args *) args;
647         fhp = &sargs->fh;
648         break;
649     }
650     default:
651         return NULL;
652     }
653
654     if (is_afs_fh3(fhp)) {
655         *fhpp = fhp;
656         return 1;
657     }
658
659     return NULL;
660 }
661
662 int
663 afs_nfs3_dispatcher(int type, afs_int32 which, char *argp, 
664                     struct exportinfo **expp, 
665                     struct svc_req *rp, struct AFS_UCRED *crp)
666 {
667     afs_int32 call = 0;
668     afs_int32 code = 0;
669     afs_int32 client = 0;
670     struct sockaddr *sa;
671     nfs_fh3 *fh = (nfs_fh3 *)argp;
672     nfs_fh3 *fh2 = (nfs_fh3 *)0;
673
674     if (!xlatorinit_v3_done)
675         return 2;
676
677     sa = (struct sockaddr *)svc_getrpccaller(rp->rq_xprt)->buf;
678     client = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
679
680     AFS_GLOCK();
681     code = 0;
682     switch (type) {
683     case 0:
684         code = nfs3_to_afs_call(which, argp, &fh, &fh2);
685         break;
686     case 1:
687         code = acl3_to_afs_call(which, argp, &fh);
688         break;
689     default:
690         break;
691     }
692
693     if (code) {
694         struct afs_exporter *out = 0;
695         afs_int32 dummy;
696         static int once = 0;
697         struct SmallFid Sfid;
698
699         memcpy((char *)&Sfid, fh->fh3_data, SIZEOF_SMALLFID);
700
701         /* We ran */
702         call = 1;
703         if (!once && *expp) {
704             afs_nobody = (*expp)->exi_export.ex_anon;
705             once = 1;
706         }
707         code = afs_nfsclient_reqhandler((struct afs_exporter *)0, &crp,
708                                         client, &dummy, &out);
709         /* Be careful to release this */
710         if (!code && out)
711             EXP_RELE(out);
712
713         /* We ran and failed */
714         if (code == EINVAL) 
715             call = 2;
716     }
717
718     AFS_GUNLOCK();
719     return call;
720 }
721
722 void 
723 afs_nfs3_smallfidder(struct nfs_fh3 *fhp, int status)
724 {
725     afs_int32 addr[2];
726     struct vcache *vcp;
727
728 #if defined(AFS_SUN57_64BIT_ENV)
729     /* See also afs_fid() */    
730     memcpy((char *)addr, fhp->fh3_data, 10);
731     addr[1] = (addr[1] >> 48) & 0xffff;
732 #else 
733     memcpy((char *)addr, fhp->fh3_data, 2 * sizeof(long));
734 #endif
735
736     AFS_GLOCK();
737     vcp = VTOAFS((struct vnode*)addr[0]);
738
739     /* See also afs_osi_vget */
740     if (addr[1] == AFS_XLATOR_MAGIC)
741     {
742         if (status == NFS_OK) {
743             struct SmallFid Sfid;
744             struct cell *tcell;
745
746             /* Make up and copy out a SmallFid */
747             tcell = afs_GetCell(vcp->fid.Cell, READ_LOCK);
748             Sfid.Volume = vcp->fid.Fid.Volume;
749             Sfid.CellAndUnique = ((tcell->cellIndex << 24) |
750                                   (vcp->fid.Fid.Unique & 0xffffff));
751             afs_PutCell(tcell, READ_LOCK);
752             Sfid.Vnode = (u_short)(vcp->fid.Fid.Vnode & 0xffff);
753             fhp->fh3_len = SIZEOF_SMALLFID;
754             memcpy(fhp->fh3_data, (char*)&Sfid, fhp->fh3_len);
755         }
756
757         /* If we have a ref, release it */
758         if (vcp->vrefCount >= 1) 
759             AFS_RELE(AFSTOV(vcp));
760     } 
761     AFS_GUNLOCK();
762 }
763
764 #define NFS_V3_REQ(FUNCNAME, NFSOP, POST, RESP, RESPP) \
765 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
766     u_int call; \
767     afs_nfs3_resp dummy; \
768     struct cred *svcred = curthread->t_cred; \
769     curthread->t_cred = (struct cred*)crp; \
770     call=afs_nfs3_dispatcher(0, NFSOP, (char *)args, &exp, rp, crp); \
771     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
772     else { (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
773     if (POST && afs_NFSRootOnly && call) { \
774     RESP *resp = ( RESP *)xp; \
775     afs_nfs3_smallfidder( RESPP , resp->status); } } \
776     curthread->t_cred = svcred; \
777     return; \
778 }
779
780 NFS_V3_REQ(afs_nfs3_getattr, NFSPROC3_GETATTR, 0, afs_nfs3_resp, &dummy) 
781 NFS_V3_REQ(afs_nfs3_setattr, NFSPROC3_SETATTR, 0, afs_nfs3_resp, &dummy)
782 NFS_V3_REQ(afs_nfs3_lookup, NFSPROC3_LOOKUP, 1, LOOKUP3res, &resp->resok.object)
783 NFS_V3_REQ(afs_nfs3_access, NFSPROC3_ACCESS, 0, afs_nfs3_resp, &dummy)
784 NFS_V3_REQ(afs_nfs3_readlink, NFSPROC3_READLINK, 0, afs_nfs3_resp, &dummy)
785 NFS_V3_REQ(afs_nfs3_read, NFSPROC3_READ, 0, afs_nfs3_resp, &dummy)
786 NFS_V3_REQ(afs_nfs3_write, NFSPROC3_WRITE, 0, afs_nfs3_resp, &dummy)
787 NFS_V3_REQ(afs_nfs3_create, NFSPROC3_CREATE, 1, CREATE3res, &resp->resok.obj.handle)
788 NFS_V3_REQ(afs_nfs3_mkdir, NFSPROC3_MKDIR, 1, MKDIR3res, &resp->resok.obj.handle)
789 NFS_V3_REQ(afs_nfs3_symlink, NFSPROC3_SYMLINK, 0, afs_nfs3_resp, &dummy)
790 NFS_V3_REQ(afs_nfs3_mknod, NFSPROC3_MKNOD, 0, afs_nfs3_resp, &dummy)
791 NFS_V3_REQ(afs_nfs3_remove, NFSPROC3_REMOVE, 0, afs_nfs3_resp, &dummy)
792 NFS_V3_REQ(afs_nfs3_rmdir, NFSPROC3_RMDIR, 0, afs_nfs3_resp, &dummy)
793 NFS_V3_REQ(afs_nfs3_rename, NFSPROC3_RENAME, 0, afs_nfs3_resp, &dummy)
794 NFS_V3_REQ(afs_nfs3_link, NFSPROC3_LINK, 0, afs_nfs3_resp, &dummy)
795 NFS_V3_REQ(afs_nfs3_readdir, NFSPROC3_READDIR, 0, afs_nfs3_resp, &dummy)
796 NFS_V3_REQ(afs_nfs3_readdirplus, NFSPROC3_READDIRPLUS, 0, afs_nfs3_resp, &dummy)
797 NFS_V3_REQ(afs_nfs3_fsstat, NFSPROC3_FSSTAT, 0, afs_nfs3_resp, &dummy)
798 NFS_V3_REQ(afs_nfs3_fsinfo, NFSPROC3_FSINFO, 0, afs_nfs3_resp, &dummy)
799 NFS_V3_REQ(afs_nfs3_pathconf, NFSPROC3_PATHCONF, 0, afs_nfs3_resp, &dummy)
800 NFS_V3_REQ(afs_nfs3_commit, NFSPROC3_COMMIT, 0, afs_nfs3_resp, &dummy)
801
802 struct afs_nfs_disp_tbl afs_rfs3_disp_tbl[RFS3_NPROC] = {
803     { afs_nfs2_null },
804     { afs_nfs3_getattr },
805     { afs_nfs3_setattr },
806     { afs_nfs3_lookup },
807     { afs_nfs3_access },
808     { afs_nfs3_readlink },
809     { afs_nfs3_read },
810     { afs_nfs3_write },
811     { afs_nfs3_create },
812     { afs_nfs3_mkdir },
813     { afs_nfs3_symlink },
814     { afs_nfs3_mknod },
815     { afs_nfs3_remove },        
816     { afs_nfs3_rmdir },
817     { afs_nfs3_rename },
818     { afs_nfs3_link },  
819     { afs_nfs3_readdir },
820     { afs_nfs3_readdirplus },
821     { afs_nfs3_fsstat },
822     { afs_nfs3_fsinfo },
823     { afs_nfs3_pathconf },
824     { afs_nfs3_commit }
825 };
826
827 #define ACL_V3_REQ(FUNCNAME, NFSOP) \
828 void FUNCNAME(char *args, char *xp, char *exp, char *rp, char *crp) { \
829     u_int call; \
830     struct cred *svcred = curthread->t_cred; \
831     curthread->t_cred = (struct cred*)crp; \
832     call=afs_nfs3_dispatcher(1, NFSOP, (char *)args, &exp, rp, crp); \
833     if (call>1) afs_nfs3_noaccess((struct afs_nfs3_resp *)xp); \
834     else (*afs_rfs3_disp_tbl[NFSOP].orig_proc)(args, xp, exp, rp, crp); \
835     curthread->t_cred = svcred; \
836     return; \
837 }
838
839 ACL_V3_REQ(afs_acl3_getacl, ACLPROC3_GETACL)
840 ACL_V3_REQ(afs_acl3_setacl, ACLPROC3_SETACL)
841
842 struct afs_nfs_disp_tbl afs_acl3_disp_tbl[ACL3_NPROC] = {
843     { afs_nfs2_null }, 
844     { afs_acl3_getacl }, 
845     { afs_acl3_setacl },
846 };
847
848 /* Munge the dispatch tables to link us in first */
849 void 
850 afs_xlatorinit_v3(struct rfs_disp_tbl *_rfs_tbl, 
851                   struct rfs_disp_tbl *_acl_tbl)
852 {
853     int i;
854
855     if (xlatorinit_v3_done++) return;
856
857     for (i=0; i < RFS3_NPROC; i++) {
858         afs_rfs3_disp_tbl[i].orig_proc = _rfs_tbl[i].dis_proc;
859         _rfs_tbl[i].dis_proc = afs_rfs3_disp_tbl[i].afs_proc;
860     }
861
862     for (i=0; i < ACL3_NPROC; i++) {
863         afs_acl3_disp_tbl[i].orig_proc = _acl_tbl[i].dis_proc;
864         _acl_tbl[i].dis_proc = afs_acl3_disp_tbl[i].afs_proc;
865     }
866 }
867 #endif /* !defined(AFS_NONFSTRANS) */