1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/param.h>
44#include <linux/smp.h>
45#include <linux/fs.h>
46#include <linux/namei.h>
47#include <linux/vfs.h>
48#include <linux/utsname.h>
49#include <linux/sunrpc/xdr.h>
50#include <linux/sunrpc/svc.h>
51#include <linux/sunrpc/clnt.h>
52#include <linux/nfsd/nfsd.h>
53#include <linux/nfsd/state.h>
54#include <linux/nfsd/xdr4.h>
55#include <linux/nfsd_idmap.h>
56#include <linux/nfs4.h>
57#include <linux/nfs4_acl.h>
58#include <linux/sunrpc/gss_api.h>
59#include <linux/sunrpc/svcauth_gss.h>
60
61#define NFSDDBG_FACILITY NFSDDBG_XDR
62
63
64
65
66
67
68#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
69#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
70
71static __be32
72check_filename(char *str, int len, __be32 err)
73{
74 int i;
75
76 if (len == 0)
77 return nfserr_inval;
78 if (isdotent(str, len))
79 return err;
80 for (i = 0; i < len; i++)
81 if (str[i] == '/')
82 return err;
83 return 0;
84}
85
86#define DECODE_HEAD \
87 __be32 *p; \
88 __be32 status
89#define DECODE_TAIL \
90 status = 0; \
91out: \
92 return status; \
93xdr_error: \
94 dprintk("NFSD: xdr error (%s:%d)\n", \
95 __FILE__, __LINE__); \
96 status = nfserr_bad_xdr; \
97 goto out
98
99#define READ32(x) (x) = ntohl(*p++)
100#define READ64(x) do { \
101 (x) = (u64)ntohl(*p++) << 32; \
102 (x) |= ntohl(*p++); \
103} while (0)
104#define READTIME(x) do { \
105 p++; \
106 (x) = ntohl(*p++); \
107 p++; \
108} while (0)
109#define READMEM(x,nbytes) do { \
110 x = (char *)p; \
111 p += XDR_QUADLEN(nbytes); \
112} while (0)
113#define SAVEMEM(x,nbytes) do { \
114 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
115 savemem(argp, p, nbytes) : \
116 (char *)p)) { \
117 dprintk("NFSD: xdr error (%s:%d)\n", \
118 __FILE__, __LINE__); \
119 goto xdr_error; \
120 } \
121 p += XDR_QUADLEN(nbytes); \
122} while (0)
123#define COPYMEM(x,nbytes) do { \
124 memcpy((x), p, nbytes); \
125 p += XDR_QUADLEN(nbytes); \
126} while (0)
127
128
129#define READ_BUF(nbytes) do { \
130 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
131 p = argp->p; \
132 argp->p += XDR_QUADLEN(nbytes); \
133 } else if (!(p = read_buf(argp, nbytes))) { \
134 dprintk("NFSD: xdr error (%s:%d)\n", \
135 __FILE__, __LINE__); \
136 goto xdr_error; \
137 } \
138} while (0)
139
140static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
141{
142
143
144
145 unsigned int avail = (char *)argp->end - (char *)argp->p;
146 __be32 *p;
147 if (avail + argp->pagelen < nbytes)
148 return NULL;
149 if (avail + PAGE_SIZE < nbytes)
150 return NULL;
151
152 if (nbytes <= sizeof(argp->tmp))
153 p = argp->tmp;
154 else {
155 kfree(argp->tmpp);
156 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
157 if (!p)
158 return NULL;
159
160 }
161
162
163
164
165
166 memcpy(p, argp->p, avail);
167
168 argp->p = page_address(argp->pagelist[0]);
169 argp->pagelist++;
170 if (argp->pagelen < PAGE_SIZE) {
171 argp->end = argp->p + (argp->pagelen>>2);
172 argp->pagelen = 0;
173 } else {
174 argp->end = argp->p + (PAGE_SIZE>>2);
175 argp->pagelen -= PAGE_SIZE;
176 }
177 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
178 argp->p += XDR_QUADLEN(nbytes - avail);
179 return p;
180}
181
182static int zero_clientid(clientid_t *clid)
183{
184 return (clid->cl_boot == 0) && (clid->cl_id == 0);
185}
186
187static int
188defer_free(struct nfsd4_compoundargs *argp,
189 void (*release)(const void *), void *p)
190{
191 struct tmpbuf *tb;
192
193 tb = kmalloc(sizeof(*tb), GFP_KERNEL);
194 if (!tb)
195 return -ENOMEM;
196 tb->buf = p;
197 tb->release = release;
198 tb->next = argp->to_free;
199 argp->to_free = tb;
200 return 0;
201}
202
203static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
204{
205 if (p == argp->tmp) {
206 p = kmalloc(nbytes, GFP_KERNEL);
207 if (!p)
208 return NULL;
209 memcpy(p, argp->tmp, nbytes);
210 } else {
211 BUG_ON(p != argp->tmpp);
212 argp->tmpp = NULL;
213 }
214 if (defer_free(argp, kfree, p)) {
215 kfree(p);
216 return NULL;
217 } else
218 return (char *)p;
219}
220
221static __be32
222nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
223{
224 u32 bmlen;
225 DECODE_HEAD;
226
227 bmval[0] = 0;
228 bmval[1] = 0;
229 bmval[2] = 0;
230
231 READ_BUF(4);
232 READ32(bmlen);
233 if (bmlen > 1000)
234 goto xdr_error;
235
236 READ_BUF(bmlen << 2);
237 if (bmlen > 0)
238 READ32(bmval[0]);
239 if (bmlen > 1)
240 READ32(bmval[1]);
241 if (bmlen > 2)
242 READ32(bmval[2]);
243
244 DECODE_TAIL;
245}
246
247static __be32
248nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
249 struct iattr *iattr, struct nfs4_acl **acl)
250{
251 int expected_len, len = 0;
252 u32 dummy32;
253 char *buf;
254 int host_err;
255
256 DECODE_HEAD;
257 iattr->ia_valid = 0;
258 if ((status = nfsd4_decode_bitmap(argp, bmval)))
259 return status;
260
261 READ_BUF(4);
262 READ32(expected_len);
263
264 if (bmval[0] & FATTR4_WORD0_SIZE) {
265 READ_BUF(8);
266 len += 8;
267 READ64(iattr->ia_size);
268 iattr->ia_valid |= ATTR_SIZE;
269 }
270 if (bmval[0] & FATTR4_WORD0_ACL) {
271 int nace;
272 struct nfs4_ace *ace;
273
274 READ_BUF(4); len += 4;
275 READ32(nace);
276
277 if (nace > NFS4_ACL_MAX)
278 return nfserr_resource;
279
280 *acl = nfs4_acl_new(nace);
281 if (*acl == NULL) {
282 host_err = -ENOMEM;
283 goto out_nfserr;
284 }
285 defer_free(argp, kfree, *acl);
286
287 (*acl)->naces = nace;
288 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
289 READ_BUF(16); len += 16;
290 READ32(ace->type);
291 READ32(ace->flag);
292 READ32(ace->access_mask);
293 READ32(dummy32);
294 READ_BUF(dummy32);
295 len += XDR_QUADLEN(dummy32) << 2;
296 READMEM(buf, dummy32);
297 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
298 host_err = 0;
299 if (ace->whotype != NFS4_ACL_WHO_NAMED)
300 ace->who = 0;
301 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
302 host_err = nfsd_map_name_to_gid(argp->rqstp,
303 buf, dummy32, &ace->who);
304 else
305 host_err = nfsd_map_name_to_uid(argp->rqstp,
306 buf, dummy32, &ace->who);
307 if (host_err)
308 goto out_nfserr;
309 }
310 } else
311 *acl = NULL;
312 if (bmval[1] & FATTR4_WORD1_MODE) {
313 READ_BUF(4);
314 len += 4;
315 READ32(iattr->ia_mode);
316 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
317 iattr->ia_valid |= ATTR_MODE;
318 }
319 if (bmval[1] & FATTR4_WORD1_OWNER) {
320 READ_BUF(4);
321 len += 4;
322 READ32(dummy32);
323 READ_BUF(dummy32);
324 len += (XDR_QUADLEN(dummy32) << 2);
325 READMEM(buf, dummy32);
326 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
327 return status;
328 iattr->ia_valid |= ATTR_UID;
329 }
330 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
331 READ_BUF(4);
332 len += 4;
333 READ32(dummy32);
334 READ_BUF(dummy32);
335 len += (XDR_QUADLEN(dummy32) << 2);
336 READMEM(buf, dummy32);
337 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
338 return status;
339 iattr->ia_valid |= ATTR_GID;
340 }
341 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
342 READ_BUF(4);
343 len += 4;
344 READ32(dummy32);
345 switch (dummy32) {
346 case NFS4_SET_TO_CLIENT_TIME:
347
348
349 READ_BUF(12);
350 len += 12;
351 READ32(dummy32);
352 if (dummy32)
353 return nfserr_inval;
354 READ32(iattr->ia_atime.tv_sec);
355 READ32(iattr->ia_atime.tv_nsec);
356 if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
357 return nfserr_inval;
358 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
359 break;
360 case NFS4_SET_TO_SERVER_TIME:
361 iattr->ia_valid |= ATTR_ATIME;
362 break;
363 default:
364 goto xdr_error;
365 }
366 }
367 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
368 READ_BUF(4);
369 len += 4;
370 READ32(dummy32);
371 switch (dummy32) {
372 case NFS4_SET_TO_CLIENT_TIME:
373
374
375 READ_BUF(12);
376 len += 12;
377 READ32(dummy32);
378 if (dummy32)
379 return nfserr_inval;
380 READ32(iattr->ia_mtime.tv_sec);
381 READ32(iattr->ia_mtime.tv_nsec);
382 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
383 return nfserr_inval;
384 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
385 break;
386 case NFS4_SET_TO_SERVER_TIME:
387 iattr->ia_valid |= ATTR_MTIME;
388 break;
389 default:
390 goto xdr_error;
391 }
392 }
393 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
394 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
395 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
396 READ_BUF(expected_len - len);
397 else if (len != expected_len)
398 goto xdr_error;
399
400 DECODE_TAIL;
401
402out_nfserr:
403 status = nfserrno(host_err);
404 goto out;
405}
406
407static __be32
408nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
409{
410 DECODE_HEAD;
411
412 READ_BUF(sizeof(stateid_t));
413 READ32(sid->si_generation);
414 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
415
416 DECODE_TAIL;
417}
418
419static __be32
420nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
421{
422 DECODE_HEAD;
423
424 READ_BUF(4);
425 READ32(access->ac_req_access);
426
427 DECODE_TAIL;
428}
429
430static __be32
431nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
432{
433 DECODE_HEAD;
434
435 close->cl_stateowner = NULL;
436 READ_BUF(4);
437 READ32(close->cl_seqid);
438 return nfsd4_decode_stateid(argp, &close->cl_stateid);
439
440 DECODE_TAIL;
441}
442
443
444static __be32
445nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
446{
447 DECODE_HEAD;
448
449 READ_BUF(12);
450 READ64(commit->co_offset);
451 READ32(commit->co_count);
452
453 DECODE_TAIL;
454}
455
456static __be32
457nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
458{
459 DECODE_HEAD;
460
461 READ_BUF(4);
462 READ32(create->cr_type);
463 switch (create->cr_type) {
464 case NF4LNK:
465 READ_BUF(4);
466 READ32(create->cr_linklen);
467 READ_BUF(create->cr_linklen);
468 SAVEMEM(create->cr_linkname, create->cr_linklen);
469 break;
470 case NF4BLK:
471 case NF4CHR:
472 READ_BUF(8);
473 READ32(create->cr_specdata1);
474 READ32(create->cr_specdata2);
475 break;
476 case NF4SOCK:
477 case NF4FIFO:
478 case NF4DIR:
479 default:
480 break;
481 }
482
483 READ_BUF(4);
484 READ32(create->cr_namelen);
485 READ_BUF(create->cr_namelen);
486 SAVEMEM(create->cr_name, create->cr_namelen);
487 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
488 return status;
489
490 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
491 &create->cr_acl);
492 if (status)
493 goto out;
494
495 DECODE_TAIL;
496}
497
498static inline __be32
499nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
500{
501 return nfsd4_decode_stateid(argp, &dr->dr_stateid);
502}
503
504static inline __be32
505nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
506{
507 return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
508}
509
510static __be32
511nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
512{
513 DECODE_HEAD;
514
515 READ_BUF(4);
516 READ32(link->li_namelen);
517 READ_BUF(link->li_namelen);
518 SAVEMEM(link->li_name, link->li_namelen);
519 if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
520 return status;
521
522 DECODE_TAIL;
523}
524
525static __be32
526nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
527{
528 DECODE_HEAD;
529
530 lock->lk_replay_owner = NULL;
531
532
533
534 READ_BUF(28);
535 READ32(lock->lk_type);
536 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
537 goto xdr_error;
538 READ32(lock->lk_reclaim);
539 READ64(lock->lk_offset);
540 READ64(lock->lk_length);
541 READ32(lock->lk_is_new);
542
543 if (lock->lk_is_new) {
544 READ_BUF(4);
545 READ32(lock->lk_new_open_seqid);
546 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
547 if (status)
548 return status;
549 READ_BUF(8 + sizeof(clientid_t));
550 READ32(lock->lk_new_lock_seqid);
551 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
552 READ32(lock->lk_new_owner.len);
553 READ_BUF(lock->lk_new_owner.len);
554 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
555 } else {
556 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
557 if (status)
558 return status;
559 READ_BUF(4);
560 READ32(lock->lk_old_lock_seqid);
561 }
562
563 DECODE_TAIL;
564}
565
566static __be32
567nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
568{
569 DECODE_HEAD;
570
571 READ_BUF(32);
572 READ32(lockt->lt_type);
573 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
574 goto xdr_error;
575 READ64(lockt->lt_offset);
576 READ64(lockt->lt_length);
577 COPYMEM(&lockt->lt_clientid, 8);
578 READ32(lockt->lt_owner.len);
579 READ_BUF(lockt->lt_owner.len);
580 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
581
582 if (argp->minorversion && !zero_clientid(&lockt->lt_clientid))
583 return nfserr_inval;
584 DECODE_TAIL;
585}
586
587static __be32
588nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
589{
590 DECODE_HEAD;
591
592 locku->lu_stateowner = NULL;
593 READ_BUF(8);
594 READ32(locku->lu_type);
595 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
596 goto xdr_error;
597 READ32(locku->lu_seqid);
598 status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
599 if (status)
600 return status;
601 READ_BUF(16);
602 READ64(locku->lu_offset);
603 READ64(locku->lu_length);
604
605 DECODE_TAIL;
606}
607
608static __be32
609nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
610{
611 DECODE_HEAD;
612
613 READ_BUF(4);
614 READ32(lookup->lo_len);
615 READ_BUF(lookup->lo_len);
616 SAVEMEM(lookup->lo_name, lookup->lo_len);
617 if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
618 return status;
619
620 DECODE_TAIL;
621}
622
623static __be32
624nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
625{
626 DECODE_HEAD;
627
628 memset(open->op_bmval, 0, sizeof(open->op_bmval));
629 open->op_iattr.ia_valid = 0;
630 open->op_stateowner = NULL;
631
632
633 READ_BUF(16 + sizeof(clientid_t));
634 READ32(open->op_seqid);
635 READ32(open->op_share_access);
636 READ32(open->op_share_deny);
637 COPYMEM(&open->op_clientid, sizeof(clientid_t));
638 READ32(open->op_owner.len);
639
640
641 READ_BUF(open->op_owner.len + 4);
642 SAVEMEM(open->op_owner.data, open->op_owner.len);
643 READ32(open->op_create);
644 switch (open->op_create) {
645 case NFS4_OPEN_NOCREATE:
646 break;
647 case NFS4_OPEN_CREATE:
648 READ_BUF(4);
649 READ32(open->op_createmode);
650 switch (open->op_createmode) {
651 case NFS4_CREATE_UNCHECKED:
652 case NFS4_CREATE_GUARDED:
653 status = nfsd4_decode_fattr(argp, open->op_bmval,
654 &open->op_iattr, &open->op_acl);
655 if (status)
656 goto out;
657 break;
658 case NFS4_CREATE_EXCLUSIVE:
659 READ_BUF(8);
660 COPYMEM(open->op_verf.data, 8);
661 break;
662 case NFS4_CREATE_EXCLUSIVE4_1:
663 if (argp->minorversion < 1)
664 goto xdr_error;
665 READ_BUF(8);
666 COPYMEM(open->op_verf.data, 8);
667 status = nfsd4_decode_fattr(argp, open->op_bmval,
668 &open->op_iattr, &open->op_acl);
669 if (status)
670 goto out;
671 break;
672 default:
673 goto xdr_error;
674 }
675 break;
676 default:
677 goto xdr_error;
678 }
679
680
681 READ_BUF(4);
682 READ32(open->op_claim_type);
683 switch (open->op_claim_type) {
684 case NFS4_OPEN_CLAIM_NULL:
685 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
686 READ_BUF(4);
687 READ32(open->op_fname.len);
688 READ_BUF(open->op_fname.len);
689 SAVEMEM(open->op_fname.data, open->op_fname.len);
690 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
691 return status;
692 break;
693 case NFS4_OPEN_CLAIM_PREVIOUS:
694 READ_BUF(4);
695 READ32(open->op_delegate_type);
696 break;
697 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
698 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
699 if (status)
700 return status;
701 READ_BUF(4);
702 READ32(open->op_fname.len);
703 READ_BUF(open->op_fname.len);
704 SAVEMEM(open->op_fname.data, open->op_fname.len);
705 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
706 return status;
707 break;
708 default:
709 goto xdr_error;
710 }
711
712 DECODE_TAIL;
713}
714
715static __be32
716nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
717{
718 DECODE_HEAD;
719
720 open_conf->oc_stateowner = NULL;
721 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
722 if (status)
723 return status;
724 READ_BUF(4);
725 READ32(open_conf->oc_seqid);
726
727 DECODE_TAIL;
728}
729
730static __be32
731nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
732{
733 DECODE_HEAD;
734
735 open_down->od_stateowner = NULL;
736 status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
737 if (status)
738 return status;
739 READ_BUF(12);
740 READ32(open_down->od_seqid);
741 READ32(open_down->od_share_access);
742 READ32(open_down->od_share_deny);
743
744 DECODE_TAIL;
745}
746
747static __be32
748nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
749{
750 DECODE_HEAD;
751
752 READ_BUF(4);
753 READ32(putfh->pf_fhlen);
754 if (putfh->pf_fhlen > NFS4_FHSIZE)
755 goto xdr_error;
756 READ_BUF(putfh->pf_fhlen);
757 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
758
759 DECODE_TAIL;
760}
761
762static __be32
763nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
764{
765 DECODE_HEAD;
766
767 status = nfsd4_decode_stateid(argp, &read->rd_stateid);
768 if (status)
769 return status;
770 READ_BUF(12);
771 READ64(read->rd_offset);
772 READ32(read->rd_length);
773
774 DECODE_TAIL;
775}
776
777static __be32
778nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
779{
780 DECODE_HEAD;
781
782 READ_BUF(24);
783 READ64(readdir->rd_cookie);
784 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
785 READ32(readdir->rd_dircount);
786 READ32(readdir->rd_maxcount);
787 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
788 goto out;
789
790 DECODE_TAIL;
791}
792
793static __be32
794nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
795{
796 DECODE_HEAD;
797
798 READ_BUF(4);
799 READ32(remove->rm_namelen);
800 READ_BUF(remove->rm_namelen);
801 SAVEMEM(remove->rm_name, remove->rm_namelen);
802 if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
803 return status;
804
805 DECODE_TAIL;
806}
807
808static __be32
809nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
810{
811 DECODE_HEAD;
812
813 READ_BUF(4);
814 READ32(rename->rn_snamelen);
815 READ_BUF(rename->rn_snamelen + 4);
816 SAVEMEM(rename->rn_sname, rename->rn_snamelen);
817 READ32(rename->rn_tnamelen);
818 READ_BUF(rename->rn_tnamelen);
819 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
820 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
821 return status;
822 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
823 return status;
824
825 DECODE_TAIL;
826}
827
828static __be32
829nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
830{
831 DECODE_HEAD;
832
833 READ_BUF(sizeof(clientid_t));
834 COPYMEM(clientid, sizeof(clientid_t));
835
836 DECODE_TAIL;
837}
838
839static __be32
840nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
841 struct nfsd4_secinfo *secinfo)
842{
843 DECODE_HEAD;
844
845 READ_BUF(4);
846 READ32(secinfo->si_namelen);
847 READ_BUF(secinfo->si_namelen);
848 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
849 status = check_filename(secinfo->si_name, secinfo->si_namelen,
850 nfserr_noent);
851 if (status)
852 return status;
853 DECODE_TAIL;
854}
855
856static __be32
857nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
858{
859 __be32 status;
860
861 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
862 if (status)
863 return status;
864 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
865 &setattr->sa_acl);
866}
867
868static __be32
869nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
870{
871 DECODE_HEAD;
872
873 READ_BUF(12);
874 COPYMEM(setclientid->se_verf.data, 8);
875 READ32(setclientid->se_namelen);
876
877 READ_BUF(setclientid->se_namelen + 8);
878 SAVEMEM(setclientid->se_name, setclientid->se_namelen);
879 READ32(setclientid->se_callback_prog);
880 READ32(setclientid->se_callback_netid_len);
881
882 READ_BUF(setclientid->se_callback_netid_len + 4);
883 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
884 READ32(setclientid->se_callback_addr_len);
885
886 READ_BUF(setclientid->se_callback_addr_len + 4);
887 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
888 READ32(setclientid->se_callback_ident);
889
890 DECODE_TAIL;
891}
892
893static __be32
894nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
895{
896 DECODE_HEAD;
897
898 READ_BUF(8 + sizeof(nfs4_verifier));
899 COPYMEM(&scd_c->sc_clientid, 8);
900 COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
901
902 DECODE_TAIL;
903}
904
905
906static __be32
907nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
908{
909#if 0
910 struct nfsd4_compoundargs save = {
911 .p = argp->p,
912 .end = argp->end,
913 .rqstp = argp->rqstp,
914 };
915 u32 ve_bmval[2];
916 struct iattr ve_iattr;
917 struct nfs4_acl *ve_acl;
918#endif
919 DECODE_HEAD;
920
921 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
922 goto out;
923
924
925
926
927#if 0
928 status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
929 if (status == nfserr_inval) {
930 status = nfserrno(status);
931 goto out;
932 }
933#endif
934 READ_BUF(4);
935 READ32(verify->ve_attrlen);
936 READ_BUF(verify->ve_attrlen);
937 SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
938
939 DECODE_TAIL;
940}
941
942static __be32
943nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
944{
945 int avail;
946 int v;
947 int len;
948 DECODE_HEAD;
949
950 status = nfsd4_decode_stateid(argp, &write->wr_stateid);
951 if (status)
952 return status;
953 READ_BUF(16);
954 READ64(write->wr_offset);
955 READ32(write->wr_stable_how);
956 if (write->wr_stable_how > 2)
957 goto xdr_error;
958 READ32(write->wr_buflen);
959
960
961
962
963
964 avail = (char*)argp->end - (char*)argp->p;
965 if (avail + argp->pagelen < write->wr_buflen) {
966 dprintk("NFSD: xdr error (%s:%d)\n",
967 __FILE__, __LINE__);
968 goto xdr_error;
969 }
970 argp->rqstp->rq_vec[0].iov_base = p;
971 argp->rqstp->rq_vec[0].iov_len = avail;
972 v = 0;
973 len = write->wr_buflen;
974 while (len > argp->rqstp->rq_vec[v].iov_len) {
975 len -= argp->rqstp->rq_vec[v].iov_len;
976 v++;
977 argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]);
978 argp->pagelist++;
979 if (argp->pagelen >= PAGE_SIZE) {
980 argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE;
981 argp->pagelen -= PAGE_SIZE;
982 } else {
983 argp->rqstp->rq_vec[v].iov_len = argp->pagelen;
984 argp->pagelen -= len;
985 }
986 }
987 argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
988 argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
989 argp->rqstp->rq_vec[v].iov_len = len;
990 write->wr_vlen = v+1;
991
992 DECODE_TAIL;
993}
994
995static __be32
996nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
997{
998 DECODE_HEAD;
999
1000 READ_BUF(12);
1001 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
1002 READ32(rlockowner->rl_owner.len);
1003 READ_BUF(rlockowner->rl_owner.len);
1004 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
1005
1006 if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
1007 return nfserr_inval;
1008 DECODE_TAIL;
1009}
1010
1011static __be32
1012nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
1013 struct nfsd4_exchange_id *exid)
1014{
1015 int dummy;
1016 DECODE_HEAD;
1017
1018 READ_BUF(NFS4_VERIFIER_SIZE);
1019 COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
1020
1021 READ_BUF(4);
1022 READ32(exid->clname.len);
1023
1024 READ_BUF(exid->clname.len);
1025 SAVEMEM(exid->clname.data, exid->clname.len);
1026
1027 READ_BUF(4);
1028 READ32(exid->flags);
1029
1030
1031 READ_BUF(4);
1032 READ32(exid->spa_how);
1033 switch (exid->spa_how) {
1034 case SP4_NONE:
1035 break;
1036 case SP4_MACH_CRED:
1037
1038 READ_BUF(4);
1039 READ32(dummy);
1040 READ_BUF(dummy * 4);
1041 p += dummy;
1042
1043
1044 READ_BUF(4);
1045 READ32(dummy);
1046 READ_BUF(dummy * 4);
1047 p += dummy;
1048 break;
1049 case SP4_SSV:
1050
1051 READ_BUF(4);
1052 READ32(dummy);
1053 READ_BUF(dummy * 4);
1054 p += dummy;
1055
1056 READ_BUF(4);
1057 READ32(dummy);
1058 READ_BUF(dummy * 4);
1059 p += dummy;
1060
1061
1062 READ_BUF(4);
1063 READ32(dummy);
1064 READ_BUF(dummy);
1065 p += XDR_QUADLEN(dummy);
1066
1067
1068 READ_BUF(4);
1069 READ32(dummy);
1070 READ_BUF(dummy);
1071 p += XDR_QUADLEN(dummy);
1072
1073
1074 READ_BUF(8);
1075 READ32(dummy);
1076 READ32(dummy);
1077 break;
1078 default:
1079 goto xdr_error;
1080 }
1081
1082
1083 READ_BUF(4);
1084 READ32(dummy);
1085
1086 if (dummy > 1)
1087 goto xdr_error;
1088
1089 if (dummy == 1) {
1090
1091 READ_BUF(4);
1092 READ32(dummy);
1093 READ_BUF(dummy);
1094 p += XDR_QUADLEN(dummy);
1095
1096
1097 READ_BUF(4);
1098 READ32(dummy);
1099 READ_BUF(dummy);
1100 p += XDR_QUADLEN(dummy);
1101
1102
1103 READ_BUF(12);
1104 p += 3;
1105 }
1106 DECODE_TAIL;
1107}
1108
1109static __be32
1110nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1111 struct nfsd4_create_session *sess)
1112{
1113 DECODE_HEAD;
1114
1115 u32 dummy;
1116 char *machine_name;
1117 int i;
1118 int nr_secflavs;
1119
1120 READ_BUF(16);
1121 COPYMEM(&sess->clientid, 8);
1122 READ32(sess->seqid);
1123 READ32(sess->flags);
1124
1125
1126 READ_BUF(28);
1127 READ32(dummy);
1128 READ32(sess->fore_channel.maxreq_sz);
1129 READ32(sess->fore_channel.maxresp_sz);
1130 READ32(sess->fore_channel.maxresp_cached);
1131 READ32(sess->fore_channel.maxops);
1132 READ32(sess->fore_channel.maxreqs);
1133 READ32(sess->fore_channel.nr_rdma_attrs);
1134 if (sess->fore_channel.nr_rdma_attrs == 1) {
1135 READ_BUF(4);
1136 READ32(sess->fore_channel.rdma_attrs);
1137 } else if (sess->fore_channel.nr_rdma_attrs > 1) {
1138 dprintk("Too many fore channel attr bitmaps!\n");
1139 goto xdr_error;
1140 }
1141
1142
1143 READ_BUF(28);
1144 READ32(dummy);
1145 READ32(sess->back_channel.maxreq_sz);
1146 READ32(sess->back_channel.maxresp_sz);
1147 READ32(sess->back_channel.maxresp_cached);
1148 READ32(sess->back_channel.maxops);
1149 READ32(sess->back_channel.maxreqs);
1150 READ32(sess->back_channel.nr_rdma_attrs);
1151 if (sess->back_channel.nr_rdma_attrs == 1) {
1152 READ_BUF(4);
1153 READ32(sess->back_channel.rdma_attrs);
1154 } else if (sess->back_channel.nr_rdma_attrs > 1) {
1155 dprintk("Too many back channel attr bitmaps!\n");
1156 goto xdr_error;
1157 }
1158
1159 READ_BUF(8);
1160 READ32(sess->callback_prog);
1161
1162
1163 READ32(nr_secflavs);
1164 for (i = 0; i < nr_secflavs; ++i) {
1165 READ_BUF(4);
1166 READ32(dummy);
1167 switch (dummy) {
1168 case RPC_AUTH_NULL:
1169
1170 break;
1171 case RPC_AUTH_UNIX:
1172 READ_BUF(8);
1173
1174 READ32(dummy);
1175
1176
1177 READ32(dummy);
1178 READ_BUF(dummy);
1179 SAVEMEM(machine_name, dummy);
1180
1181
1182 READ_BUF(8);
1183 READ32(sess->uid);
1184 READ32(sess->gid);
1185
1186
1187 READ_BUF(4);
1188 READ32(dummy);
1189 READ_BUF(dummy * 4);
1190 break;
1191 case RPC_AUTH_GSS:
1192 dprintk("RPC_AUTH_GSS callback secflavor "
1193 "not supported!\n");
1194 READ_BUF(8);
1195
1196 READ32(dummy);
1197
1198 READ32(dummy);
1199 READ_BUF(dummy);
1200 p += XDR_QUADLEN(dummy);
1201
1202 READ_BUF(4);
1203 READ32(dummy);
1204 READ_BUF(dummy);
1205 break;
1206 default:
1207 dprintk("Illegal callback secflavor\n");
1208 return nfserr_inval;
1209 }
1210 }
1211 DECODE_TAIL;
1212}
1213
1214static __be32
1215nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1216 struct nfsd4_destroy_session *destroy_session)
1217{
1218 DECODE_HEAD;
1219 READ_BUF(NFS4_MAX_SESSIONID_LEN);
1220 COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1221
1222 DECODE_TAIL;
1223}
1224
1225static __be32
1226nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1227 struct nfsd4_sequence *seq)
1228{
1229 DECODE_HEAD;
1230
1231 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1232 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1233 READ32(seq->seqid);
1234 READ32(seq->slotid);
1235 READ32(seq->maxslots);
1236 READ32(seq->cachethis);
1237
1238 DECODE_TAIL;
1239}
1240
1241static __be32
1242nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
1243{
1244 return nfs_ok;
1245}
1246
1247static __be32
1248nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
1249{
1250 return nfserr_notsupp;
1251}
1252
1253typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1254
1255static nfsd4_dec nfsd4_dec_ops[] = {
1256 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1257 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1258 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1259 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1260 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1261 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1262 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1263 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1264 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1265 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1266 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1267 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1268 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1269 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1270 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1271 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1272 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1273 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm,
1274 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1275 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
1276 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_noop,
1277 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1278 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1279 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1280 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1281 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1282 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1283 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew,
1284 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1285 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1286 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1287 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1288 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid,
1289 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
1290 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1291 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1292 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner,
1293};
1294
1295static nfsd4_dec nfsd41_dec_ops[] = {
1296 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1297 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1298 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1299 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1300 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1301 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1302 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1303 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1304 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1305 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1306 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1307 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1308 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1309 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1310 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1311 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1312 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1313 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_notsupp,
1314 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1315 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
1316 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp,
1317 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1318 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1319 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1320 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1321 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1322 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1323 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_notsupp,
1324 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1325 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1326 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1327 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1328 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
1329 [OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp,
1330 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1331 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1332 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp,
1333
1334
1335 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp,
1336 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp,
1337 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1338 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1339 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
1340 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp,
1341 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1342 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
1343 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1344 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
1345 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
1346 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
1347 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_notsupp,
1348 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1349 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1350 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp,
1351 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1352 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
1353 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_notsupp,
1354};
1355
1356struct nfsd4_minorversion_ops {
1357 nfsd4_dec *decoders;
1358 int nops;
1359};
1360
1361static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
1362 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
1363 [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
1364};
1365
1366static __be32
1367nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1368{
1369 DECODE_HEAD;
1370 struct nfsd4_op *op;
1371 struct nfsd4_minorversion_ops *ops;
1372 int i;
1373
1374
1375
1376
1377
1378
1379
1380 READ_BUF(4);
1381 READ32(argp->taglen);
1382 READ_BUF(argp->taglen + 8);
1383 SAVEMEM(argp->tag, argp->taglen);
1384 READ32(argp->minorversion);
1385 READ32(argp->opcnt);
1386
1387 if (argp->taglen > NFSD4_MAX_TAGLEN)
1388 goto xdr_error;
1389 if (argp->opcnt > 100)
1390 goto xdr_error;
1391
1392 if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
1393 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1394 if (!argp->ops) {
1395 argp->ops = argp->iops;
1396 dprintk("nfsd: couldn't allocate room for COMPOUND\n");
1397 goto xdr_error;
1398 }
1399 }
1400
1401 if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
1402 argp->opcnt = 0;
1403
1404 ops = &nfsd4_minorversion[argp->minorversion];
1405 for (i = 0; i < argp->opcnt; i++) {
1406 op = &argp->ops[i];
1407 op->replay = NULL;
1408
1409
1410
1411
1412
1413
1414
1415
1416 if (argp->p == argp->end) {
1417 if (argp->pagelen < 4) {
1418
1419 op->opnum = OP_WRITE + 1;
1420 op->status = nfserr_bad_xdr;
1421 argp->opcnt = i+1;
1422 break;
1423 }
1424
1425
1426
1427
1428
1429
1430 argp->p = page_address(argp->pagelist[0]);
1431 argp->pagelist++;
1432 if (argp->pagelen < PAGE_SIZE) {
1433 argp->end = argp->p + (argp->pagelen>>2);
1434 argp->pagelen = 0;
1435 } else {
1436 argp->end = argp->p + (PAGE_SIZE>>2);
1437 argp->pagelen -= PAGE_SIZE;
1438 }
1439 }
1440 op->opnum = ntohl(*argp->p++);
1441
1442 if (op->opnum >= OP_ACCESS && op->opnum < ops->nops)
1443 op->status = ops->decoders[op->opnum](argp, &op->u);
1444 else {
1445 op->opnum = OP_ILLEGAL;
1446 op->status = nfserr_op_illegal;
1447 }
1448
1449 if (op->status) {
1450 argp->opcnt = i+1;
1451 break;
1452 }
1453 }
1454
1455 DECODE_TAIL;
1456}
1457
1458#define WRITE32(n) *p++ = htonl(n)
1459#define WRITE64(n) do { \
1460 *p++ = htonl((u32)((n) >> 32)); \
1461 *p++ = htonl((u32)(n)); \
1462} while (0)
1463#define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \
1464 *(p + XDR_QUADLEN(nbytes) -1) = 0; \
1465 memcpy(p, ptr, nbytes); \
1466 p += XDR_QUADLEN(nbytes); \
1467}} while (0)
1468
1469static void write32(__be32 **p, u32 n)
1470{
1471 *(*p)++ = n;
1472}
1473
1474static void write64(__be32 **p, u64 n)
1475{
1476 write32(p, (u32)(n >> 32));
1477 write32(p, (u32)n);
1478}
1479
1480static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
1481{
1482 if (IS_I_VERSION(inode)) {
1483 write64(p, inode->i_version);
1484 } else {
1485 write32(p, stat->ctime.tv_sec);
1486 write32(p, stat->ctime.tv_nsec);
1487 }
1488}
1489
1490static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
1491{
1492 write32(p, c->atomic);
1493 if (c->change_supported) {
1494 write64(p, c->before_change);
1495 write64(p, c->after_change);
1496 } else {
1497 write32(p, c->before_ctime_sec);
1498 write32(p, c->before_ctime_nsec);
1499 write32(p, c->after_ctime_sec);
1500 write32(p, c->after_ctime_nsec);
1501 }
1502}
1503
1504#define RESERVE_SPACE(nbytes) do { \
1505 p = resp->p; \
1506 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \
1507} while (0)
1508#define ADJUST_ARGS() resp->p = p
1509
1510
1511
1512
1513#define ENCODE_SEQID_OP_HEAD \
1514 __be32 *save; \
1515 \
1516 save = resp->p;
1517
1518
1519
1520
1521
1522
1523
1524
1525#define ENCODE_SEQID_OP_TAIL(stateowner) do { \
1526 if (seqid_mutating_err(nfserr) && stateowner) { \
1527 stateowner->so_seqid++; \
1528 stateowner->so_replay.rp_status = nfserr; \
1529 stateowner->so_replay.rp_buflen = \
1530 (((char *)(resp)->p - (char *)save)); \
1531 memcpy(stateowner->so_replay.rp_buf, save, \
1532 stateowner->so_replay.rp_buflen); \
1533 } } while (0);
1534
1535
1536
1537
1538static __be32 nfsd4_encode_components(char sep, char *components,
1539 __be32 **pp, int *buflen)
1540{
1541 __be32 *p = *pp;
1542 __be32 *countp = p;
1543 int strlen, count=0;
1544 char *str, *end;
1545
1546 dprintk("nfsd4_encode_components(%s)\n", components);
1547 if ((*buflen -= 4) < 0)
1548 return nfserr_resource;
1549 WRITE32(0);
1550 end = str = components;
1551 while (*end) {
1552 for (; *end && (*end != sep); end++)
1553 ;
1554 strlen = end - str;
1555 if (strlen) {
1556 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0)
1557 return nfserr_resource;
1558 WRITE32(strlen);
1559 WRITEMEM(str, strlen);
1560 count++;
1561 }
1562 else
1563 end++;
1564 str = end;
1565 }
1566 *pp = p;
1567 p = countp;
1568 WRITE32(count);
1569 return 0;
1570}
1571
1572
1573
1574
1575static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1576 __be32 **pp, int *buflen)
1577{
1578 __be32 status;
1579 __be32 *p = *pp;
1580
1581 status = nfsd4_encode_components(':', location->hosts, &p, buflen);
1582 if (status)
1583 return status;
1584 status = nfsd4_encode_components('/', location->path, &p, buflen);
1585 if (status)
1586 return status;
1587 *pp = p;
1588 return 0;
1589}
1590
1591
1592
1593
1594
1595
1596static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat)
1597{
1598 struct svc_fh tmp_fh;
1599 char *path = NULL, *rootpath;
1600 size_t rootlen;
1601
1602 fh_init(&tmp_fh, NFS4_FHSIZE);
1603 *stat = exp_pseudoroot(rqstp, &tmp_fh);
1604 if (*stat)
1605 return NULL;
1606 rootpath = tmp_fh.fh_export->ex_pathname;
1607
1608 path = exp->ex_pathname;
1609
1610 rootlen = strlen(rootpath);
1611 if (strncmp(path, rootpath, rootlen)) {
1612 dprintk("nfsd: fs_locations failed;"
1613 "%s is not contained in %s\n", path, rootpath);
1614 *stat = nfserr_notsupp;
1615 path = NULL;
1616 goto out;
1617 }
1618 path += rootlen;
1619out:
1620 fh_put(&tmp_fh);
1621 return path;
1622}
1623
1624
1625
1626
1627static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1628 struct svc_export *exp,
1629 __be32 **pp, int *buflen)
1630{
1631 __be32 status;
1632 int i;
1633 __be32 *p = *pp;
1634 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1635 char *root = nfsd4_path(rqstp, exp, &status);
1636
1637 if (status)
1638 return status;
1639 status = nfsd4_encode_components('/', root, &p, buflen);
1640 if (status)
1641 return status;
1642 if ((*buflen -= 4) < 0)
1643 return nfserr_resource;
1644 WRITE32(fslocs->locations_count);
1645 for (i=0; i<fslocs->locations_count; i++) {
1646 status = nfsd4_encode_fs_location4(&fslocs->locations[i],
1647 &p, buflen);
1648 if (status)
1649 return status;
1650 }
1651 *pp = p;
1652 return 0;
1653}
1654
1655static u32 nfs4_ftypes[16] = {
1656 NF4BAD, NF4FIFO, NF4CHR, NF4BAD,
1657 NF4DIR, NF4BAD, NF4BLK, NF4BAD,
1658 NF4REG, NF4BAD, NF4LNK, NF4BAD,
1659 NF4SOCK, NF4BAD, NF4LNK, NF4BAD,
1660};
1661
1662static __be32
1663nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1664 __be32 **p, int *buflen)
1665{
1666 int status;
1667
1668 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1669 return nfserr_resource;
1670 if (whotype != NFS4_ACL_WHO_NAMED)
1671 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1672 else if (group)
1673 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1674 else
1675 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1676 if (status < 0)
1677 return nfserrno(status);
1678 *p = xdr_encode_opaque(*p, NULL, status);
1679 *buflen -= (XDR_QUADLEN(status) << 2) + 4;
1680 BUG_ON(*buflen < 0);
1681 return 0;
1682}
1683
1684static inline __be32
1685nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
1686{
1687 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1688}
1689
1690static inline __be32
1691nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
1692{
1693 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1694}
1695
1696static inline __be32
1697nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1698 __be32 **p, int *buflen)
1699{
1700 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1701}
1702
1703#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
1704 FATTR4_WORD0_RDATTR_ERROR)
1705#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1706
1707static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1708{
1709
1710 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
1711 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
1712 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
1713 *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
1714 *rdattr_err = NFSERR_MOVED;
1715 else
1716 return nfserr_moved;
1717 }
1718 *bmval0 &= WORD0_ABSENT_FS_ATTRS;
1719 *bmval1 &= WORD1_ABSENT_FS_ATTRS;
1720 return 0;
1721}
1722
1723
1724
1725
1726
1727
1728
1729
1730__be32
1731nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1732 struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
1733 struct svc_rqst *rqstp, int ignore_crossmnt)
1734{
1735 u32 bmval0 = bmval[0];
1736 u32 bmval1 = bmval[1];
1737 u32 bmval2 = bmval[2];
1738 struct kstat stat;
1739 struct svc_fh tempfh;
1740 struct kstatfs statfs;
1741 int buflen = *countp << 2;
1742 __be32 *attrlenp;
1743 u32 dummy;
1744 u64 dummy64;
1745 u32 rdattr_err = 0;
1746 __be32 *p = buffer;
1747 __be32 status;
1748 int err;
1749 int aclsupport = 0;
1750 struct nfs4_acl *acl = NULL;
1751 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1752 u32 minorversion = resp->cstate.minorversion;
1753
1754 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1755 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
1756 BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
1757 BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
1758
1759 if (exp->ex_fslocs.migrated) {
1760 BUG_ON(bmval[2]);
1761 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
1762 if (status)
1763 goto out;
1764 }
1765
1766 err = vfs_getattr(exp->ex_path.mnt, dentry, &stat);
1767 if (err)
1768 goto out_nfserr;
1769 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
1770 FATTR4_WORD0_MAXNAME)) ||
1771 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1772 FATTR4_WORD1_SPACE_TOTAL))) {
1773 err = vfs_statfs(dentry, &statfs);
1774 if (err)
1775 goto out_nfserr;
1776 }
1777 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
1778 fh_init(&tempfh, NFS4_FHSIZE);
1779 status = fh_compose(&tempfh, exp, dentry, NULL);
1780 if (status)
1781 goto out;
1782 fhp = &tempfh;
1783 }
1784 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1785 | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1786 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1787 aclsupport = (err == 0);
1788 if (bmval0 & FATTR4_WORD0_ACL) {
1789 if (err == -EOPNOTSUPP)
1790 bmval0 &= ~FATTR4_WORD0_ACL;
1791 else if (err == -EINVAL) {
1792 status = nfserr_attrnotsupp;
1793 goto out;
1794 } else if (err != 0)
1795 goto out_nfserr;
1796 }
1797 }
1798 if ((buflen -= 16) < 0)
1799 goto out_resource;
1800
1801 if (unlikely(bmval2)) {
1802 WRITE32(3);
1803 WRITE32(bmval0);
1804 WRITE32(bmval1);
1805 WRITE32(bmval2);
1806 } else if (likely(bmval1)) {
1807 WRITE32(2);
1808 WRITE32(bmval0);
1809 WRITE32(bmval1);
1810 } else {
1811 WRITE32(1);
1812 WRITE32(bmval0);
1813 }
1814 attrlenp = p++;
1815
1816 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1817 u32 word0 = nfsd_suppattrs0(minorversion);
1818 u32 word1 = nfsd_suppattrs1(minorversion);
1819 u32 word2 = nfsd_suppattrs2(minorversion);
1820
1821 if ((buflen -= 12) < 0)
1822 goto out_resource;
1823 if (!aclsupport)
1824 word0 &= ~FATTR4_WORD0_ACL;
1825 if (!word2) {
1826 WRITE32(2);
1827 WRITE32(word0);
1828 WRITE32(word1);
1829 } else {
1830 WRITE32(3);
1831 WRITE32(word0);
1832 WRITE32(word1);
1833 WRITE32(word2);
1834 }
1835 }
1836 if (bmval0 & FATTR4_WORD0_TYPE) {
1837 if ((buflen -= 4) < 0)
1838 goto out_resource;
1839 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1840 if (dummy == NF4BAD)
1841 goto out_serverfault;
1842 WRITE32(dummy);
1843 }
1844 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1845 if ((buflen -= 4) < 0)
1846 goto out_resource;
1847 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
1848 WRITE32(NFS4_FH_PERSISTENT);
1849 else
1850 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
1851 }
1852 if (bmval0 & FATTR4_WORD0_CHANGE) {
1853 if ((buflen -= 8) < 0)
1854 goto out_resource;
1855 write_change(&p, &stat, dentry->d_inode);
1856 }
1857 if (bmval0 & FATTR4_WORD0_SIZE) {
1858 if ((buflen -= 8) < 0)
1859 goto out_resource;
1860 WRITE64(stat.size);
1861 }
1862 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1863 if ((buflen -= 4) < 0)
1864 goto out_resource;
1865 WRITE32(1);
1866 }
1867 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1868 if ((buflen -= 4) < 0)
1869 goto out_resource;
1870 WRITE32(1);
1871 }
1872 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1873 if ((buflen -= 4) < 0)
1874 goto out_resource;
1875 WRITE32(0);
1876 }
1877 if (bmval0 & FATTR4_WORD0_FSID) {
1878 if ((buflen -= 16) < 0)
1879 goto out_resource;
1880 if (exp->ex_fslocs.migrated) {
1881 WRITE64(NFS4_REFERRAL_FSID_MAJOR);
1882 WRITE64(NFS4_REFERRAL_FSID_MINOR);
1883 } else switch(fsid_source(fhp)) {
1884 case FSIDSOURCE_FSID:
1885 WRITE64((u64)exp->ex_fsid);
1886 WRITE64((u64)0);
1887 break;
1888 case FSIDSOURCE_DEV:
1889 WRITE32(0);
1890 WRITE32(MAJOR(stat.dev));
1891 WRITE32(0);
1892 WRITE32(MINOR(stat.dev));
1893 break;
1894 case FSIDSOURCE_UUID:
1895 WRITEMEM(exp->ex_uuid, 16);
1896 break;
1897 }
1898 }
1899 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1900 if ((buflen -= 4) < 0)
1901 goto out_resource;
1902 WRITE32(0);
1903 }
1904 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1905 if ((buflen -= 4) < 0)
1906 goto out_resource;
1907 WRITE32(NFSD_LEASE_TIME);
1908 }
1909 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1910 if ((buflen -= 4) < 0)
1911 goto out_resource;
1912 WRITE32(rdattr_err);
1913 }
1914 if (bmval0 & FATTR4_WORD0_ACL) {
1915 struct nfs4_ace *ace;
1916
1917 if (acl == NULL) {
1918 if ((buflen -= 4) < 0)
1919 goto out_resource;
1920
1921 WRITE32(0);
1922 goto out_acl;
1923 }
1924 if ((buflen -= 4) < 0)
1925 goto out_resource;
1926 WRITE32(acl->naces);
1927
1928 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
1929 if ((buflen -= 4*3) < 0)
1930 goto out_resource;
1931 WRITE32(ace->type);
1932 WRITE32(ace->flag);
1933 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
1934 status = nfsd4_encode_aclname(rqstp, ace->whotype,
1935 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
1936 &p, &buflen);
1937 if (status == nfserr_resource)
1938 goto out_resource;
1939 if (status)
1940 goto out;
1941 }
1942 }
1943out_acl:
1944 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1945 if ((buflen -= 4) < 0)
1946 goto out_resource;
1947 WRITE32(aclsupport ?
1948 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
1949 }
1950 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1951 if ((buflen -= 4) < 0)
1952 goto out_resource;
1953 WRITE32(1);
1954 }
1955 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1956 if ((buflen -= 4) < 0)
1957 goto out_resource;
1958 WRITE32(1);
1959 }
1960 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1961 if ((buflen -= 4) < 0)
1962 goto out_resource;
1963 WRITE32(1);
1964 }
1965 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1966 if ((buflen -= 4) < 0)
1967 goto out_resource;
1968 WRITE32(1);
1969 }
1970 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1971 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1972 if (buflen < 0)
1973 goto out_resource;
1974 WRITE32(fhp->fh_handle.fh_size);
1975 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1976 }
1977 if (bmval0 & FATTR4_WORD0_FILEID) {
1978 if ((buflen -= 8) < 0)
1979 goto out_resource;
1980 WRITE64(stat.ino);
1981 }
1982 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1983 if ((buflen -= 8) < 0)
1984 goto out_resource;
1985 WRITE64((u64) statfs.f_ffree);
1986 }
1987 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1988 if ((buflen -= 8) < 0)
1989 goto out_resource;
1990 WRITE64((u64) statfs.f_ffree);
1991 }
1992 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1993 if ((buflen -= 8) < 0)
1994 goto out_resource;
1995 WRITE64((u64) statfs.f_files);
1996 }
1997 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1998 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
1999 if (status == nfserr_resource)
2000 goto out_resource;
2001 if (status)
2002 goto out;
2003 }
2004 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
2005 if ((buflen -= 4) < 0)
2006 goto out_resource;
2007 WRITE32(1);
2008 }
2009 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
2010 if ((buflen -= 8) < 0)
2011 goto out_resource;
2012 WRITE64(~(u64)0);
2013 }
2014 if (bmval0 & FATTR4_WORD0_MAXLINK) {
2015 if ((buflen -= 4) < 0)
2016 goto out_resource;
2017 WRITE32(255);
2018 }
2019 if (bmval0 & FATTR4_WORD0_MAXNAME) {
2020 if ((buflen -= 4) < 0)
2021 goto out_resource;
2022 WRITE32(statfs.f_namelen);
2023 }
2024 if (bmval0 & FATTR4_WORD0_MAXREAD) {
2025 if ((buflen -= 8) < 0)
2026 goto out_resource;
2027 WRITE64((u64) svc_max_payload(rqstp));
2028 }
2029 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
2030 if ((buflen -= 8) < 0)
2031 goto out_resource;
2032 WRITE64((u64) svc_max_payload(rqstp));
2033 }
2034 if (bmval1 & FATTR4_WORD1_MODE) {
2035 if ((buflen -= 4) < 0)
2036 goto out_resource;
2037 WRITE32(stat.mode & S_IALLUGO);
2038 }
2039 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
2040 if ((buflen -= 4) < 0)
2041 goto out_resource;
2042 WRITE32(1);
2043 }
2044 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
2045 if ((buflen -= 4) < 0)
2046 goto out_resource;
2047 WRITE32(stat.nlink);
2048 }
2049 if (bmval1 & FATTR4_WORD1_OWNER) {
2050 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
2051 if (status == nfserr_resource)
2052 goto out_resource;
2053 if (status)
2054 goto out;
2055 }
2056 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
2057 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
2058 if (status == nfserr_resource)
2059 goto out_resource;
2060 if (status)
2061 goto out;
2062 }
2063 if (bmval1 & FATTR4_WORD1_RAWDEV) {
2064 if ((buflen -= 8) < 0)
2065 goto out_resource;
2066 WRITE32((u32) MAJOR(stat.rdev));
2067 WRITE32((u32) MINOR(stat.rdev));
2068 }
2069 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
2070 if ((buflen -= 8) < 0)
2071 goto out_resource;
2072 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
2073 WRITE64(dummy64);
2074 }
2075 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
2076 if ((buflen -= 8) < 0)
2077 goto out_resource;
2078 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
2079 WRITE64(dummy64);
2080 }
2081 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
2082 if ((buflen -= 8) < 0)
2083 goto out_resource;
2084 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
2085 WRITE64(dummy64);
2086 }
2087 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
2088 if ((buflen -= 8) < 0)
2089 goto out_resource;
2090 dummy64 = (u64)stat.blocks << 9;
2091 WRITE64(dummy64);
2092 }
2093 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
2094 if ((buflen -= 12) < 0)
2095 goto out_resource;
2096 WRITE32(0);
2097 WRITE32(stat.atime.tv_sec);
2098 WRITE32(stat.atime.tv_nsec);
2099 }
2100 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
2101 if ((buflen -= 12) < 0)
2102 goto out_resource;
2103 WRITE32(0);
2104 WRITE32(1);
2105 WRITE32(0);
2106 }
2107 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
2108 if ((buflen -= 12) < 0)
2109 goto out_resource;
2110 WRITE32(0);
2111 WRITE32(stat.ctime.tv_sec);
2112 WRITE32(stat.ctime.tv_nsec);
2113 }
2114 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
2115 if ((buflen -= 12) < 0)
2116 goto out_resource;
2117 WRITE32(0);
2118 WRITE32(stat.mtime.tv_sec);
2119 WRITE32(stat.mtime.tv_nsec);
2120 }
2121 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
2122 if ((buflen -= 8) < 0)
2123 goto out_resource;
2124
2125
2126
2127
2128 if (ignore_crossmnt == 0 &&
2129 dentry == exp->ex_path.mnt->mnt_root) {
2130 struct path path = exp->ex_path;
2131 path_get(&path);
2132 while (follow_up(&path)) {
2133 if (path.dentry != path.mnt->mnt_root)
2134 break;
2135 }
2136 err = vfs_getattr(path.mnt, path.dentry, &stat);
2137 path_put(&path);
2138 if (err)
2139 goto out_nfserr;
2140 }
2141 WRITE64(stat.ino);
2142 }
2143 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2144 WRITE32(3);
2145 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
2146 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
2147 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2);
2148 }
2149
2150 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2151 *countp = p - buffer;
2152 status = nfs_ok;
2153
2154out:
2155 kfree(acl);
2156 if (fhp == &tempfh)
2157 fh_put(&tempfh);
2158 return status;
2159out_nfserr:
2160 status = nfserrno(err);
2161 goto out;
2162out_resource:
2163 *countp = 0;
2164 status = nfserr_resource;
2165 goto out;
2166out_serverfault:
2167 status = nfserr_serverfault;
2168 goto out;
2169}
2170
2171static inline int attributes_need_mount(u32 *bmval)
2172{
2173 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
2174 return 1;
2175 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
2176 return 1;
2177 return 0;
2178}
2179
2180static __be32
2181nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2182 const char *name, int namlen, __be32 *p, int *buflen)
2183{
2184 struct svc_export *exp = cd->rd_fhp->fh_export;
2185 struct dentry *dentry;
2186 __be32 nfserr;
2187 int ignore_crossmnt = 0;
2188
2189 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
2190 if (IS_ERR(dentry))
2191 return nfserrno(PTR_ERR(dentry));
2192 if (!dentry->d_inode) {
2193
2194
2195
2196
2197
2198 dput(dentry);
2199 return nfserr_noent;
2200 }
2201
2202 exp_get(exp);
2203
2204
2205
2206
2207
2208
2209
2210 if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
2211 ignore_crossmnt = 1;
2212 else if (d_mountpoint(dentry)) {
2213 int err;
2214
2215
2216
2217
2218
2219
2220 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
2221 if (err) {
2222 nfserr = nfserrno(err);
2223 goto out_put;
2224 }
2225 nfserr = check_nfsd_access(exp, cd->rd_rqstp);
2226 if (nfserr)
2227 goto out_put;
2228
2229 }
2230 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
2231 cd->rd_rqstp, ignore_crossmnt);
2232out_put:
2233 dput(dentry);
2234 exp_put(exp);
2235 return nfserr;
2236}
2237
2238static __be32 *
2239nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
2240{
2241 __be32 *attrlenp;
2242
2243 if (buflen < 6)
2244 return NULL;
2245 *p++ = htonl(2);
2246 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR);
2247 *p++ = htonl(0);
2248
2249 attrlenp = p++;
2250 *p++ = nfserr;
2251 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2252 return p;
2253}
2254
2255static int
2256nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2257 loff_t offset, u64 ino, unsigned int d_type)
2258{
2259 struct readdir_cd *ccd = ccdv;
2260 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
2261 int buflen;
2262 __be32 *p = cd->buffer;
2263 __be32 *cookiep;
2264 __be32 nfserr = nfserr_toosmall;
2265
2266
2267 if (name && isdotent(name, namlen)) {
2268 cd->common.err = nfs_ok;
2269 return 0;
2270 }
2271
2272 if (cd->offset)
2273 xdr_encode_hyper(cd->offset, (u64) offset);
2274
2275 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
2276 if (buflen < 0)
2277 goto fail;
2278
2279 *p++ = xdr_one;
2280 cookiep = p;
2281 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);
2282 p = xdr_encode_array(p, name, namlen);
2283
2284 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
2285 switch (nfserr) {
2286 case nfs_ok:
2287 p += buflen;
2288 break;
2289 case nfserr_resource:
2290 nfserr = nfserr_toosmall;
2291 goto fail;
2292 case nfserr_dropit:
2293 goto fail;
2294 case nfserr_noent:
2295 goto skip_entry;
2296 default:
2297
2298
2299
2300
2301
2302
2303
2304 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
2305 goto fail;
2306 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
2307 if (p == NULL) {
2308 nfserr = nfserr_toosmall;
2309 goto fail;
2310 }
2311 }
2312 cd->buflen -= (p - cd->buffer);
2313 cd->buffer = p;
2314 cd->offset = cookiep;
2315skip_entry:
2316 cd->common.err = nfs_ok;
2317 return 0;
2318fail:
2319 cd->common.err = nfserr;
2320 return -EINVAL;
2321}
2322
2323static void
2324nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
2325{
2326 __be32 *p;
2327
2328 RESERVE_SPACE(sizeof(stateid_t));
2329 WRITE32(sid->si_generation);
2330 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
2331 ADJUST_ARGS();
2332}
2333
2334static __be32
2335nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
2336{
2337 __be32 *p;
2338
2339 if (!nfserr) {
2340 RESERVE_SPACE(8);
2341 WRITE32(access->ac_supported);
2342 WRITE32(access->ac_resp_access);
2343 ADJUST_ARGS();
2344 }
2345 return nfserr;
2346}
2347
2348static __be32
2349nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
2350{
2351 ENCODE_SEQID_OP_HEAD;
2352
2353 if (!nfserr)
2354 nfsd4_encode_stateid(resp, &close->cl_stateid);
2355
2356 ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
2357 return nfserr;
2358}
2359
2360
2361static __be32
2362nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
2363{
2364 __be32 *p;
2365
2366 if (!nfserr) {
2367 RESERVE_SPACE(8);
2368 WRITEMEM(commit->co_verf.data, 8);
2369 ADJUST_ARGS();
2370 }
2371 return nfserr;
2372}
2373
2374static __be32
2375nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
2376{
2377 __be32 *p;
2378
2379 if (!nfserr) {
2380 RESERVE_SPACE(32);
2381 write_cinfo(&p, &create->cr_cinfo);
2382 WRITE32(2);
2383 WRITE32(create->cr_bmval[0]);
2384 WRITE32(create->cr_bmval[1]);
2385 ADJUST_ARGS();
2386 }
2387 return nfserr;
2388}
2389
2390static __be32
2391nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
2392{
2393 struct svc_fh *fhp = getattr->ga_fhp;
2394 int buflen;
2395
2396 if (nfserr)
2397 return nfserr;
2398
2399 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
2400 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
2401 resp->p, &buflen, getattr->ga_bmval,
2402 resp->rqstp, 0);
2403 if (!nfserr)
2404 resp->p += buflen;
2405 return nfserr;
2406}
2407
2408static __be32
2409nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
2410{
2411 struct svc_fh *fhp = *fhpp;
2412 unsigned int len;
2413 __be32 *p;
2414
2415 if (!nfserr) {
2416 len = fhp->fh_handle.fh_size;
2417 RESERVE_SPACE(len + 4);
2418 WRITE32(len);
2419 WRITEMEM(&fhp->fh_handle.fh_base, len);
2420 ADJUST_ARGS();
2421 }
2422 return nfserr;
2423}
2424
2425
2426
2427
2428
2429static void
2430nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
2431{
2432 __be32 *p;
2433
2434 RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
2435 WRITE64(ld->ld_start);
2436 WRITE64(ld->ld_length);
2437 WRITE32(ld->ld_type);
2438 if (ld->ld_sop) {
2439 WRITEMEM(&ld->ld_clientid, 8);
2440 WRITE32(ld->ld_sop->so_owner.len);
2441 WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
2442 kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
2443 } else {
2444 WRITE64((u64)0);
2445 WRITE32(0);
2446 }
2447 ADJUST_ARGS();
2448}
2449
2450static __be32
2451nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
2452{
2453 ENCODE_SEQID_OP_HEAD;
2454
2455 if (!nfserr)
2456 nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
2457 else if (nfserr == nfserr_denied)
2458 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
2459
2460 ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
2461 return nfserr;
2462}
2463
2464static __be32
2465nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
2466{
2467 if (nfserr == nfserr_denied)
2468 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
2469 return nfserr;
2470}
2471
2472static __be32
2473nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
2474{
2475 ENCODE_SEQID_OP_HEAD;
2476
2477 if (!nfserr)
2478 nfsd4_encode_stateid(resp, &locku->lu_stateid);
2479
2480 ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
2481 return nfserr;
2482}
2483
2484
2485static __be32
2486nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
2487{
2488 __be32 *p;
2489
2490 if (!nfserr) {
2491 RESERVE_SPACE(20);
2492 write_cinfo(&p, &link->li_cinfo);
2493 ADJUST_ARGS();
2494 }
2495 return nfserr;
2496}
2497
2498
2499static __be32
2500nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
2501{
2502 __be32 *p;
2503 ENCODE_SEQID_OP_HEAD;
2504
2505 if (nfserr)
2506 goto out;
2507
2508 nfsd4_encode_stateid(resp, &open->op_stateid);
2509 RESERVE_SPACE(40);
2510 write_cinfo(&p, &open->op_cinfo);
2511 WRITE32(open->op_rflags);
2512 WRITE32(2);
2513 WRITE32(open->op_bmval[0]);
2514 WRITE32(open->op_bmval[1]);
2515 WRITE32(open->op_delegate_type);
2516 ADJUST_ARGS();
2517
2518 switch (open->op_delegate_type) {
2519 case NFS4_OPEN_DELEGATE_NONE:
2520 break;
2521 case NFS4_OPEN_DELEGATE_READ:
2522 nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2523 RESERVE_SPACE(20);
2524 WRITE32(open->op_recall);
2525
2526
2527
2528
2529 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2530 WRITE32(0);
2531 WRITE32(0);
2532 WRITE32(0);
2533 ADJUST_ARGS();
2534 break;
2535 case NFS4_OPEN_DELEGATE_WRITE:
2536 nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2537 RESERVE_SPACE(32);
2538 WRITE32(0);
2539
2540
2541
2542
2543 WRITE32(NFS4_LIMIT_SIZE);
2544 WRITE32(~(u32)0);
2545 WRITE32(~(u32)0);
2546
2547
2548
2549
2550 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2551 WRITE32(0);
2552 WRITE32(0);
2553 WRITE32(0);
2554 ADJUST_ARGS();
2555 break;
2556 default:
2557 BUG();
2558 }
2559
2560out:
2561 ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2562 return nfserr;
2563}
2564
2565static __be32
2566nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
2567{
2568 ENCODE_SEQID_OP_HEAD;
2569
2570 if (!nfserr)
2571 nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
2572
2573 ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2574 return nfserr;
2575}
2576
2577static __be32
2578nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
2579{
2580 ENCODE_SEQID_OP_HEAD;
2581
2582 if (!nfserr)
2583 nfsd4_encode_stateid(resp, &od->od_stateid);
2584
2585 ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2586 return nfserr;
2587}
2588
2589static __be32
2590nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2591 struct nfsd4_read *read)
2592{
2593 u32 eof;
2594 int v, pn;
2595 unsigned long maxcount;
2596 long len;
2597 __be32 *p;
2598
2599 if (nfserr)
2600 return nfserr;
2601 if (resp->xbuf->page_len)
2602 return nfserr_resource;
2603
2604 RESERVE_SPACE(8);
2605
2606 maxcount = svc_max_payload(resp->rqstp);
2607 if (maxcount > read->rd_length)
2608 maxcount = read->rd_length;
2609
2610 len = maxcount;
2611 v = 0;
2612 while (len > 0) {
2613 pn = resp->rqstp->rq_resused++;
2614 resp->rqstp->rq_vec[v].iov_base =
2615 page_address(resp->rqstp->rq_respages[pn]);
2616 resp->rqstp->rq_vec[v].iov_len =
2617 len < PAGE_SIZE ? len : PAGE_SIZE;
2618 v++;
2619 len -= PAGE_SIZE;
2620 }
2621 read->rd_vlen = v;
2622
2623 nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2624 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
2625 &maxcount);
2626
2627 if (nfserr == nfserr_symlink)
2628 nfserr = nfserr_inval;
2629 if (nfserr)
2630 return nfserr;
2631 eof = (read->rd_offset + maxcount >=
2632 read->rd_fhp->fh_dentry->d_inode->i_size);
2633
2634 WRITE32(eof);
2635 WRITE32(maxcount);
2636 ADJUST_ARGS();
2637 resp->xbuf->head[0].iov_len = (char*)p
2638 - (char*)resp->xbuf->head[0].iov_base;
2639 resp->xbuf->page_len = maxcount;
2640
2641
2642 resp->xbuf->tail[0].iov_base = p;
2643 resp->xbuf->tail[0].iov_len = 0;
2644 if (maxcount&3) {
2645 RESERVE_SPACE(4);
2646 WRITE32(0);
2647 resp->xbuf->tail[0].iov_base += maxcount&3;
2648 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2649 ADJUST_ARGS();
2650 }
2651 return 0;
2652}
2653
2654static __be32
2655nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
2656{
2657 int maxcount;
2658 char *page;
2659 __be32 *p;
2660
2661 if (nfserr)
2662 return nfserr;
2663 if (resp->xbuf->page_len)
2664 return nfserr_resource;
2665
2666 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2667
2668 maxcount = PAGE_SIZE;
2669 RESERVE_SPACE(4);
2670
2671
2672
2673
2674
2675
2676
2677 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2678 if (nfserr == nfserr_isdir)
2679 return nfserr_inval;
2680 if (nfserr)
2681 return nfserr;
2682
2683 WRITE32(maxcount);
2684 ADJUST_ARGS();
2685 resp->xbuf->head[0].iov_len = (char*)p
2686 - (char*)resp->xbuf->head[0].iov_base;
2687 resp->xbuf->page_len = maxcount;
2688
2689
2690 resp->xbuf->tail[0].iov_base = p;
2691 resp->xbuf->tail[0].iov_len = 0;
2692 if (maxcount&3) {
2693 RESERVE_SPACE(4);
2694 WRITE32(0);
2695 resp->xbuf->tail[0].iov_base += maxcount&3;
2696 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2697 ADJUST_ARGS();
2698 }
2699 return 0;
2700}
2701
2702static __be32
2703nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
2704{
2705 int maxcount;
2706 loff_t offset;
2707 __be32 *page, *savep, *tailbase;
2708 __be32 *p;
2709
2710 if (nfserr)
2711 return nfserr;
2712 if (resp->xbuf->page_len)
2713 return nfserr_resource;
2714
2715 RESERVE_SPACE(8);
2716 savep = p;
2717
2718
2719 WRITE32(0);
2720 WRITE32(0);
2721 ADJUST_ARGS();
2722 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2723 tailbase = p;
2724
2725 maxcount = PAGE_SIZE;
2726 if (maxcount > readdir->rd_maxcount)
2727 maxcount = readdir->rd_maxcount;
2728
2729
2730
2731
2732
2733
2734 maxcount = (maxcount >> 2) - 4;
2735 if (maxcount < 0) {
2736 nfserr = nfserr_toosmall;
2737 goto err_no_verf;
2738 }
2739
2740 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2741 readdir->common.err = 0;
2742 readdir->buflen = maxcount;
2743 readdir->buffer = page;
2744 readdir->offset = NULL;
2745
2746 offset = readdir->rd_cookie;
2747 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2748 &offset,
2749 &readdir->common, nfsd4_encode_dirent);
2750 if (nfserr == nfs_ok &&
2751 readdir->common.err == nfserr_toosmall &&
2752 readdir->buffer == page)
2753 nfserr = nfserr_toosmall;
2754 if (nfserr == nfserr_symlink)
2755 nfserr = nfserr_notdir;
2756 if (nfserr)
2757 goto err_no_verf;
2758
2759 if (readdir->offset)
2760 xdr_encode_hyper(readdir->offset, offset);
2761
2762 p = readdir->buffer;
2763 *p++ = 0;
2764 *p++ = htonl(readdir->common.err == nfserr_eof);
2765 resp->xbuf->page_len = ((char*)p) - (char*)page_address(
2766 resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2767
2768
2769 resp->xbuf->tail[0].iov_base = tailbase;
2770 resp->xbuf->tail[0].iov_len = 0;
2771 resp->p = resp->xbuf->tail[0].iov_base;
2772 resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
2773
2774 return 0;
2775err_no_verf:
2776 p = savep;
2777 ADJUST_ARGS();
2778 return nfserr;
2779}
2780
2781static __be32
2782nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
2783{
2784 __be32 *p;
2785
2786 if (!nfserr) {
2787 RESERVE_SPACE(20);
2788 write_cinfo(&p, &remove->rm_cinfo);
2789 ADJUST_ARGS();
2790 }
2791 return nfserr;
2792}
2793
2794static __be32
2795nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
2796{
2797 __be32 *p;
2798
2799 if (!nfserr) {
2800 RESERVE_SPACE(40);
2801 write_cinfo(&p, &rename->rn_sinfo);
2802 write_cinfo(&p, &rename->rn_tinfo);
2803 ADJUST_ARGS();
2804 }
2805 return nfserr;
2806}
2807
2808static __be32
2809nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
2810 struct nfsd4_secinfo *secinfo)
2811{
2812 int i = 0;
2813 struct svc_export *exp = secinfo->si_exp;
2814 u32 nflavs;
2815 struct exp_flavor_info *flavs;
2816 struct exp_flavor_info def_flavs[2];
2817 __be32 *p;
2818
2819 if (nfserr)
2820 goto out;
2821 if (exp->ex_nflavors) {
2822 flavs = exp->ex_flavors;
2823 nflavs = exp->ex_nflavors;
2824 } else {
2825 flavs = def_flavs;
2826 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
2827 nflavs = 2;
2828 flavs[0].pseudoflavor = RPC_AUTH_UNIX;
2829 flavs[1].pseudoflavor = RPC_AUTH_NULL;
2830 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
2831 nflavs = 1;
2832 flavs[0].pseudoflavor
2833 = svcauth_gss_flavor(exp->ex_client);
2834 } else {
2835 nflavs = 1;
2836 flavs[0].pseudoflavor
2837 = exp->ex_client->flavour->flavour;
2838 }
2839 }
2840
2841 RESERVE_SPACE(4);
2842 WRITE32(nflavs);
2843 ADJUST_ARGS();
2844 for (i = 0; i < nflavs; i++) {
2845 u32 flav = flavs[i].pseudoflavor;
2846 struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
2847
2848 if (gm) {
2849 RESERVE_SPACE(4);
2850 WRITE32(RPC_AUTH_GSS);
2851 ADJUST_ARGS();
2852 RESERVE_SPACE(4 + gm->gm_oid.len);
2853 WRITE32(gm->gm_oid.len);
2854 WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
2855 ADJUST_ARGS();
2856 RESERVE_SPACE(4);
2857 WRITE32(0);
2858 ADJUST_ARGS();
2859 RESERVE_SPACE(4);
2860 WRITE32(gss_pseudoflavor_to_service(gm, flav));
2861 ADJUST_ARGS();
2862 gss_mech_put(gm);
2863 } else {
2864 RESERVE_SPACE(4);
2865 WRITE32(flav);
2866 ADJUST_ARGS();
2867 }
2868 }
2869out:
2870 if (exp)
2871 exp_put(exp);
2872 return nfserr;
2873}
2874
2875
2876
2877
2878
2879static __be32
2880nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
2881{
2882 __be32 *p;
2883
2884 RESERVE_SPACE(12);
2885 if (nfserr) {
2886 WRITE32(2);
2887 WRITE32(0);
2888 WRITE32(0);
2889 }
2890 else {
2891 WRITE32(2);
2892 WRITE32(setattr->sa_bmval[0]);
2893 WRITE32(setattr->sa_bmval[1]);
2894 }
2895 ADJUST_ARGS();
2896 return nfserr;
2897}
2898
2899static __be32
2900nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
2901{
2902 __be32 *p;
2903
2904 if (!nfserr) {
2905 RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2906 WRITEMEM(&scd->se_clientid, 8);
2907 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2908 ADJUST_ARGS();
2909 }
2910 else if (nfserr == nfserr_clid_inuse) {
2911 RESERVE_SPACE(8);
2912 WRITE32(0);
2913 WRITE32(0);
2914 ADJUST_ARGS();
2915 }
2916 return nfserr;
2917}
2918
2919static __be32
2920nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
2921{
2922 __be32 *p;
2923
2924 if (!nfserr) {
2925 RESERVE_SPACE(16);
2926 WRITE32(write->wr_bytes_written);
2927 WRITE32(write->wr_how_written);
2928 WRITEMEM(write->wr_verifier.data, 8);
2929 ADJUST_ARGS();
2930 }
2931 return nfserr;
2932}
2933
2934static __be32
2935nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr,
2936 struct nfsd4_exchange_id *exid)
2937{
2938 __be32 *p;
2939 char *major_id;
2940 char *server_scope;
2941 int major_id_sz;
2942 int server_scope_sz;
2943 uint64_t minor_id = 0;
2944
2945 if (nfserr)
2946 return nfserr;
2947
2948 major_id = utsname()->nodename;
2949 major_id_sz = strlen(major_id);
2950 server_scope = utsname()->nodename;
2951 server_scope_sz = strlen(server_scope);
2952
2953 RESERVE_SPACE(
2954 8 +
2955 4 +
2956 4 +
2957 4 +
2958 8 +
2959 4 +
2960 (XDR_QUADLEN(major_id_sz) * 4) +
2961 4 +
2962 (XDR_QUADLEN(server_scope_sz) * 4) +
2963 4 );
2964
2965 WRITEMEM(&exid->clientid, 8);
2966 WRITE32(exid->seqid);
2967 WRITE32(exid->flags);
2968
2969
2970 BUG_ON(exid->spa_how != SP4_NONE);
2971 WRITE32(exid->spa_how);
2972
2973
2974 WRITE64(minor_id);
2975
2976 WRITE32(major_id_sz);
2977 WRITEMEM(major_id, major_id_sz);
2978
2979
2980 WRITE32(server_scope_sz);
2981 WRITEMEM(server_scope, server_scope_sz);
2982
2983
2984 WRITE32(0);
2985 ADJUST_ARGS();
2986 return 0;
2987}
2988
2989static __be32
2990nfsd4_encode_create_session(struct nfsd4_compoundres *resp, int nfserr,
2991 struct nfsd4_create_session *sess)
2992{
2993 __be32 *p;
2994
2995 if (nfserr)
2996 return nfserr;
2997
2998 RESERVE_SPACE(24);
2999 WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN);
3000 WRITE32(sess->seqid);
3001 WRITE32(sess->flags);
3002 ADJUST_ARGS();
3003
3004 RESERVE_SPACE(28);
3005 WRITE32(0);
3006 WRITE32(sess->fore_channel.maxreq_sz);
3007 WRITE32(sess->fore_channel.maxresp_sz);
3008 WRITE32(sess->fore_channel.maxresp_cached);
3009 WRITE32(sess->fore_channel.maxops);
3010 WRITE32(sess->fore_channel.maxreqs);
3011 WRITE32(sess->fore_channel.nr_rdma_attrs);
3012 ADJUST_ARGS();
3013
3014 if (sess->fore_channel.nr_rdma_attrs) {
3015 RESERVE_SPACE(4);
3016 WRITE32(sess->fore_channel.rdma_attrs);
3017 ADJUST_ARGS();
3018 }
3019
3020 RESERVE_SPACE(28);
3021 WRITE32(0);
3022 WRITE32(sess->back_channel.maxreq_sz);
3023 WRITE32(sess->back_channel.maxresp_sz);
3024 WRITE32(sess->back_channel.maxresp_cached);
3025 WRITE32(sess->back_channel.maxops);
3026 WRITE32(sess->back_channel.maxreqs);
3027 WRITE32(sess->back_channel.nr_rdma_attrs);
3028 ADJUST_ARGS();
3029
3030 if (sess->back_channel.nr_rdma_attrs) {
3031 RESERVE_SPACE(4);
3032 WRITE32(sess->back_channel.rdma_attrs);
3033 ADJUST_ARGS();
3034 }
3035 return 0;
3036}
3037
3038static __be32
3039nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
3040 struct nfsd4_destroy_session *destroy_session)
3041{
3042 return nfserr;
3043}
3044
3045__be32
3046nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3047 struct nfsd4_sequence *seq)
3048{
3049 __be32 *p;
3050
3051 if (nfserr)
3052 return nfserr;
3053
3054 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20);
3055 WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
3056 WRITE32(seq->seqid);
3057 WRITE32(seq->slotid);
3058 WRITE32(seq->maxslots);
3059
3060
3061
3062
3063
3064 WRITE32(seq->maxslots);
3065 WRITE32(0);
3066
3067 ADJUST_ARGS();
3068 resp->cstate.datap = p;
3069 return 0;
3070}
3071
3072static __be32
3073nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
3074{
3075 return nfserr;
3076}
3077
3078typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
3079
3080
3081
3082
3083
3084
3085static nfsd4_enc nfsd4_enc_ops[] = {
3086 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
3087 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
3088 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
3089 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create,
3090 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop,
3091 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop,
3092 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr,
3093 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh,
3094 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link,
3095 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock,
3096 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt,
3097 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku,
3098 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop,
3099 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop,
3100 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop,
3101 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open,
3102 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop,
3103 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm,
3104 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade,
3105 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop,
3106 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop,
3107 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop,
3108 [OP_READ] = (nfsd4_enc)nfsd4_encode_read,
3109 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir,
3110 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink,
3111 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove,
3112 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename,
3113 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop,
3114 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop,
3115 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop,
3116 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo,
3117 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr,
3118 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid,
3119 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
3120 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop,
3121 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write,
3122 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop,
3123
3124
3125 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
3126 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop,
3127 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
3128 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
3129 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
3130 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
3131 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3132 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
3133 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
3134 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop,
3135 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop,
3136 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop,
3137 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_noop,
3138 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
3139 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
3140 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
3141 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3142 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
3143 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
3144};
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp)
3159{
3160 int status = 0;
3161 struct xdr_buf *xb = &resp->rqstp->rq_res;
3162 struct nfsd4_compoundargs *args = resp->rqstp->rq_argp;
3163 struct nfsd4_session *session = NULL;
3164 struct nfsd4_slot *slot = resp->cstate.slot;
3165 u32 length, tlen = 0, pad = 8;
3166
3167 if (!nfsd4_has_session(&resp->cstate))
3168 return status;
3169
3170 session = resp->cstate.session;
3171 if (session == NULL || slot->sl_cachethis == 0)
3172 return status;
3173
3174 if (resp->opcnt >= args->opcnt)
3175 pad = 0;
3176
3177 if (xb->page_len == 0) {
3178 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
3179 } else {
3180 if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0)
3181 tlen = (char *)resp->p - (char *)xb->tail[0].iov_base;
3182
3183 length = xb->head[0].iov_len + xb->page_len + tlen + pad;
3184 }
3185 dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__,
3186 length, xb->page_len, tlen, pad);
3187
3188 if (length <= session->se_fchannel.maxresp_cached)
3189 return status;
3190 else
3191 return nfserr_rep_too_big_to_cache;
3192}
3193
3194void
3195nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3196{
3197 __be32 *statp;
3198 __be32 *p;
3199
3200 RESERVE_SPACE(8);
3201 WRITE32(op->opnum);
3202 statp = p++;
3203 ADJUST_ARGS();
3204
3205 if (op->opnum == OP_ILLEGAL)
3206 goto status;
3207 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
3208 !nfsd4_enc_ops[op->opnum]);
3209 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
3210
3211 if (!op->status && nfsd4_check_drc_limit(resp))
3212 op->status = nfserr_rep_too_big_to_cache;
3213status:
3214
3215
3216
3217
3218 *statp = op->status;
3219}
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229void
3230nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3231{
3232 __be32 *p;
3233 struct nfs4_replay *rp = op->replay;
3234
3235 BUG_ON(!rp);
3236
3237 RESERVE_SPACE(8);
3238 WRITE32(op->opnum);
3239 *p++ = rp->rp_status;
3240 ADJUST_ARGS();
3241
3242 RESERVE_SPACE(rp->rp_buflen);
3243 WRITEMEM(rp->rp_buf, rp->rp_buflen);
3244 ADJUST_ARGS();
3245}
3246
3247int
3248nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
3249{
3250 return xdr_ressize_check(rqstp, p);
3251}
3252
3253void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
3254{
3255 if (args->ops != args->iops) {
3256 kfree(args->ops);
3257 args->ops = args->iops;
3258 }
3259 kfree(args->tmpp);
3260 args->tmpp = NULL;
3261 while (args->to_free) {
3262 struct tmpbuf *tb = args->to_free;
3263 args->to_free = tb->next;
3264 tb->release(tb->buf);
3265 kfree(tb);
3266 }
3267}
3268
3269int
3270nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
3271{
3272 __be32 status;
3273
3274 args->p = p;
3275 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
3276 args->pagelist = rqstp->rq_arg.pages;
3277 args->pagelen = rqstp->rq_arg.page_len;
3278 args->tmpp = NULL;
3279 args->to_free = NULL;
3280 args->ops = args->iops;
3281 args->rqstp = rqstp;
3282
3283 status = nfsd4_decode_compound(args);
3284 if (status) {
3285 nfsd4_release_compoundargs(args);
3286 }
3287 return !status;
3288}
3289
3290int
3291nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
3292{
3293
3294
3295
3296 struct nfsd4_compound_state *cs = &resp->cstate;
3297 struct kvec *iov;
3298 p = resp->tagp;
3299 *p++ = htonl(resp->taglen);
3300 memcpy(p, resp->tag, resp->taglen);
3301 p += XDR_QUADLEN(resp->taglen);
3302 *p++ = htonl(resp->opcnt);
3303
3304 if (rqstp->rq_res.page_len)
3305 iov = &rqstp->rq_res.tail[0];
3306 else
3307 iov = &rqstp->rq_res.head[0];
3308 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
3309 BUG_ON(iov->iov_len > PAGE_SIZE);
3310 if (nfsd4_has_session(cs) && cs->status != nfserr_replay_cache) {
3311 nfsd4_store_cache_entry(resp);
3312 dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
3313 resp->cstate.slot->sl_inuse = false;
3314 nfsd4_put_session(resp->cstate.session);
3315 }
3316 return 1;
3317}
3318
3319
3320
3321
3322
3323
3324