1// SPDX-License-Identifier: GPL-2.0
2/*
3 * XDR support for nfsd/protocol version 3.
4 *
5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
6 *
7 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
8 */
9
10#include <linux/namei.h>
11#include <linux/sunrpc/svc_xprt.h>
12#include "xdr3.h"
13#include "auth.h"
14#include "netns.h"
15#include "vfs.h"
16
17/*
18 * Force construction of an empty post-op attr
19 */
20static const struct svc_fh nfs3svc_null_fh = {
21	.fh_no_wcc	= true,
22};
23
24/*
25 * time_delta. {1, 0} means the server is accurate only
26 * to the nearest second.
27 */
28static const struct timespec64 nfs3svc_time_delta = {
29	.tv_sec		= 1,
30	.tv_nsec	= 0,
31};
32
33/*
34 * Mapping of S_IF* types to NFS file types
35 */
36static const u32 nfs3_ftypes[] = {
37	NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
38	NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
39	NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
40	NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
41};
42
43
44/*
45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
46 */
47
48static __be32 *
49encode_nfstime3(__be32 *p, const struct timespec64 *time)
50{
51	*p++ = cpu_to_be32((u32)time->tv_sec);
52	*p++ = cpu_to_be32(time->tv_nsec);
53
54	return p;
55}
56
57static bool
58svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
59{
60	__be32 *p;
61
62	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
63	if (!p)
64		return false;
65	timep->tv_sec = be32_to_cpup(p++);
66	timep->tv_nsec = be32_to_cpup(p);
67
68	return true;
69}
70
71/**
72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH
74 * @fhp: OUT: filled-in server file handle
75 *
76 * Return values:
77 *  %false: The encoded file handle was not valid
78 *  %true: @fhp has been initialized
79 */
80bool
81svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
82{
83	__be32 *p;
84	u32 size;
85
86	if (xdr_stream_decode_u32(xdr, &size) < 0)
87		return false;
88	if (size == 0 || size > NFS3_FHSIZE)
89		return false;
90	p = xdr_inline_decode(xdr, size);
91	if (!p)
92		return false;
93	fh_init(fhp, NFS3_FHSIZE);
94	fhp->fh_handle.fh_size = size;
95	memcpy(&fhp->fh_handle.fh_raw, p, size);
96
97	return true;
98}
99
100/**
101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code
102 * @xdr: XDR stream
103 * @status: status value to encode
104 *
105 * Return values:
106 *   %false: Send buffer space was exhausted
107 *   %true: Success
108 */
109bool
110svcxdr_encode_nfsstat3(struct xdr_stream *xdr, __be32 status)
111{
112	__be32 *p;
113
114	p = xdr_reserve_space(xdr, sizeof(status));
115	if (!p)
116		return false;
117	*p = status;
118
119	return true;
120}
121
122static bool
123svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
124{
125	u32 size = fhp->fh_handle.fh_size;
126	__be32 *p;
127
128	p = xdr_reserve_space(xdr, XDR_UNIT + size);
129	if (!p)
130		return false;
131	*p++ = cpu_to_be32(size);
132	if (size)
133		p[XDR_QUADLEN(size) - 1] = 0;
134	memcpy(p, &fhp->fh_handle.fh_raw, size);
135
136	return true;
137}
138
139static bool
140svcxdr_encode_post_op_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
141{
142	if (xdr_stream_encode_item_present(xdr) < 0)
143		return false;
144	if (!svcxdr_encode_nfs_fh3(xdr, fhp))
145		return false;
146
147	return true;
148}
149
150static bool
151svcxdr_encode_cookieverf3(struct xdr_stream *xdr, const __be32 *verf)
152{
153	__be32 *p;
154
155	p = xdr_reserve_space(xdr, NFS3_COOKIEVERFSIZE);
156	if (!p)
157		return false;
158	memcpy(p, verf, NFS3_COOKIEVERFSIZE);
159
160	return true;
161}
162
163static bool
164svcxdr_encode_writeverf3(struct xdr_stream *xdr, const __be32 *verf)
165{
166	__be32 *p;
167
168	p = xdr_reserve_space(xdr, NFS3_WRITEVERFSIZE);
169	if (!p)
170		return false;
171	memcpy(p, verf, NFS3_WRITEVERFSIZE);
172
173	return true;
174}
175
176static bool
177svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
178{
179	u32 size, i;
180	__be32 *p;
181	char *c;
182
183	if (xdr_stream_decode_u32(xdr, &size) < 0)
184		return false;
185	if (size == 0 || size > NFS3_MAXNAMLEN)
186		return false;
187	p = xdr_inline_decode(xdr, size);
188	if (!p)
189		return false;
190
191	*len = size;
192	*name = (char *)p;
193	for (i = 0, c = *name; i < size; i++, c++) {
194		if (*c == '\0' || *c == '/')
195			return false;
196	}
197
198	return true;
199}
200
201static bool
202svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
203			 char **name, unsigned int *len)
204{
205	return svcxdr_decode_nfs_fh3(xdr, fhp) &&
206		svcxdr_decode_filename3(xdr, name, len);
207}
208
209static bool
210svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
211		     struct iattr *iap)
212{
213	u32 set_it;
214
215	iap->ia_valid = 0;
216
217	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
218		return false;
219	if (set_it) {
220		u32 mode;
221
222		if (xdr_stream_decode_u32(xdr, &mode) < 0)
223			return false;
224		iap->ia_valid |= ATTR_MODE;
225		iap->ia_mode = mode;
226	}
227	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
228		return false;
229	if (set_it) {
230		u32 uid;
231
232		if (xdr_stream_decode_u32(xdr, &uid) < 0)
233			return false;
234		iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid);
235		if (uid_valid(iap->ia_uid))
236			iap->ia_valid |= ATTR_UID;
237	}
238	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
239		return false;
240	if (set_it) {
241		u32 gid;
242
243		if (xdr_stream_decode_u32(xdr, &gid) < 0)
244			return false;
245		iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid);
246		if (gid_valid(iap->ia_gid))
247			iap->ia_valid |= ATTR_GID;
248	}
249	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
250		return false;
251	if (set_it) {
252		u64 newsize;
253
254		if (xdr_stream_decode_u64(xdr, &newsize) < 0)
255			return false;
256		iap->ia_valid |= ATTR_SIZE;
257		iap->ia_size = newsize;
258	}
259	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
260		return false;
261	switch (set_it) {
262	case DONT_CHANGE:
263		break;
264	case SET_TO_SERVER_TIME:
265		iap->ia_valid |= ATTR_ATIME;
266		break;
267	case SET_TO_CLIENT_TIME:
268		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime))
269			return false;
270		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
271		break;
272	default:
273		return false;
274	}
275	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
276		return false;
277	switch (set_it) {
278	case DONT_CHANGE:
279		break;
280	case SET_TO_SERVER_TIME:
281		iap->ia_valid |= ATTR_MTIME;
282		break;
283	case SET_TO_CLIENT_TIME:
284		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime))
285			return false;
286		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
287		break;
288	default:
289		return false;
290	}
291
292	return true;
293}
294
295static bool
296svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
297{
298	u32 check;
299
300	if (xdr_stream_decode_bool(xdr, &check) < 0)
301		return false;
302	if (check) {
303		if (!svcxdr_decode_nfstime3(xdr, &args->guardtime))
304			return false;
305		args->check_guard = 1;
306	} else
307		args->check_guard = 0;
308
309	return true;
310}
311
312static bool
313svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
314{
315	__be32 *p;
316
317	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
318	if (!p)
319		return false;
320	args->major = be32_to_cpup(p++);
321	args->minor = be32_to_cpup(p);
322
323	return true;
324}
325
326static bool
327svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
328			  struct nfsd3_mknodargs *args)
329{
330	return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
331		svcxdr_decode_specdata3(xdr, args);
332}
333
334static bool
335svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
336		     const struct svc_fh *fhp, const struct kstat *stat)
337{
338	struct user_namespace *userns = nfsd_user_namespace(rqstp);
339	__be32 *p;
340	u64 fsid;
341
342	p = xdr_reserve_space(xdr, XDR_UNIT * 21);
343	if (!p)
344		return false;
345
346	*p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
347	*p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO));
348	*p++ = cpu_to_be32((u32)stat->nlink);
349	*p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
350	*p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
351	if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN)
352		p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN);
353	else
354		p = xdr_encode_hyper(p, (u64)stat->size);
355
356	/* used */
357	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
358
359	/* rdev */
360	*p++ = cpu_to_be32((u32)MAJOR(stat->rdev));
361	*p++ = cpu_to_be32((u32)MINOR(stat->rdev));
362
363	switch(fsid_source(fhp)) {
364	case FSIDSOURCE_FSID:
365		fsid = (u64)fhp->fh_export->ex_fsid;
366		break;
367	case FSIDSOURCE_UUID:
368		fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
369		fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
370		break;
371	default:
372		fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
373	}
374	p = xdr_encode_hyper(p, fsid);
375
376	/* fileid */
377	p = xdr_encode_hyper(p, stat->ino);
378
379	p = encode_nfstime3(p, &stat->atime);
380	p = encode_nfstime3(p, &stat->mtime);
381	encode_nfstime3(p, &stat->ctime);
382
383	return true;
384}
385
386static bool
387svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
388{
389	__be32 *p;
390
391	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
392	if (!p)
393		return false;
394	p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size);
395	p = encode_nfstime3(p, &fhp->fh_pre_mtime);
396	encode_nfstime3(p, &fhp->fh_pre_ctime);
397
398	return true;
399}
400
401static bool
402svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
403{
404	if (!fhp->fh_pre_saved) {
405		if (xdr_stream_encode_item_absent(xdr) < 0)
406			return false;
407		return true;
408	}
409
410	if (xdr_stream_encode_item_present(xdr) < 0)
411		return false;
412	return svcxdr_encode_wcc_attr(xdr, fhp);
413}
414
415/**
416 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
417 * @rqstp: Context of a completed RPC transaction
418 * @xdr: XDR stream
419 * @fhp: File handle to encode
420 *
421 * Return values:
422 *   %false: Send buffer space was exhausted
423 *   %true: Success
424 */
425bool
426svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
427			   const struct svc_fh *fhp)
428{
429	struct dentry *dentry = fhp->fh_dentry;
430	struct kstat stat;
431
432	/*
433	 * The inode may be NULL if the call failed because of a
434	 * stale file handle. In this case, no attributes are
435	 * returned.
436	 */
437	if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry))
438		goto no_post_op_attrs;
439	if (fh_getattr(fhp, &stat) != nfs_ok)
440		goto no_post_op_attrs;
441
442	if (xdr_stream_encode_item_present(xdr) < 0)
443		return false;
444	lease_get_mtime(d_inode(dentry), &stat.mtime);
445	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat))
446		return false;
447
448	return true;
449
450no_post_op_attrs:
451	return xdr_stream_encode_item_absent(xdr) > 0;
452}
453
454/*
455 * Encode weak cache consistency data
456 */
457static bool
458svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
459		       const struct svc_fh *fhp)
460{
461	struct dentry *dentry = fhp->fh_dentry;
462
463	if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved)
464		goto neither;
465
466	/* before */
467	if (!svcxdr_encode_pre_op_attr(xdr, fhp))
468		return false;
469
470	/* after */
471	if (xdr_stream_encode_item_present(xdr) < 0)
472		return false;
473	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr))
474		return false;
475
476	return true;
477
478neither:
479	if (xdr_stream_encode_item_absent(xdr) < 0)
480		return false;
481	if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp))
482		return false;
483
484	return true;
485}
486
487/*
488 * XDR decode functions
489 */
490
491bool
492nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
493{
494	struct nfsd_fhandle *args = rqstp->rq_argp;
495
496	return svcxdr_decode_nfs_fh3(xdr, &args->fh);
497}
498
499bool
500nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
501{
502	struct nfsd3_sattrargs *args = rqstp->rq_argp;
503
504	return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
505		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
506		svcxdr_decode_sattrguard3(xdr, args);
507}
508
509bool
510nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
511{
512	struct nfsd3_diropargs *args = rqstp->rq_argp;
513
514	return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
515}
516
517bool
518nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
519{
520	struct nfsd3_accessargs *args = rqstp->rq_argp;
521
522	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
523		return false;
524	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
525		return false;
526
527	return true;
528}
529
530bool
531nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
532{
533	struct nfsd3_readargs *args = rqstp->rq_argp;
534
535	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
536		return false;
537	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
538		return false;
539	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
540		return false;
541
542	return true;
543}
544
545bool
546nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
547{
548	struct nfsd3_writeargs *args = rqstp->rq_argp;
549	u32 max_blocksize = svc_max_payload(rqstp);
550
551	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
552		return false;
553	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
554		return false;
555	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
556		return false;
557	if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
558		return false;
559
560	/* opaque data */
561	if (xdr_stream_decode_u32(xdr, &args->len) < 0)
562		return false;
563
564	/* request sanity */
565	if (args->count != args->len)
566		return false;
567	if (args->count > max_blocksize) {
568		args->count = max_blocksize;
569		args->len = max_blocksize;
570	}
571
572	return xdr_stream_subsegment(xdr, &args->payload, args->count);
573}
574
575bool
576nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
577{
578	struct nfsd3_createargs *args = rqstp->rq_argp;
579
580	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
581		return false;
582	if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
583		return false;
584	switch (args->createmode) {
585	case NFS3_CREATE_UNCHECKED:
586	case NFS3_CREATE_GUARDED:
587		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
588	case NFS3_CREATE_EXCLUSIVE:
589		args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
590		if (!args->verf)
591			return false;
592		break;
593	default:
594		return false;
595	}
596	return true;
597}
598
599bool
600nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
601{
602	struct nfsd3_createargs *args = rqstp->rq_argp;
603
604	return svcxdr_decode_diropargs3(xdr, &args->fh,
605					&args->name, &args->len) &&
606		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
607}
608
609bool
610nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
611{
612	struct nfsd3_symlinkargs *args = rqstp->rq_argp;
613	struct kvec *head = rqstp->rq_arg.head;
614
615	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
616		return false;
617	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
618		return false;
619	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
620		return false;
621
622	/* symlink_data */
623	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
624	args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
625	return args->first.iov_base != NULL;
626}
627
628bool
629nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
630{
631	struct nfsd3_mknodargs *args = rqstp->rq_argp;
632
633	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
634		return false;
635	if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
636		return false;
637	switch (args->ftype) {
638	case NF3CHR:
639	case NF3BLK:
640		return svcxdr_decode_devicedata3(rqstp, xdr, args);
641	case NF3SOCK:
642	case NF3FIFO:
643		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
644	case NF3REG:
645	case NF3DIR:
646	case NF3LNK:
647		/* Valid XDR but illegal file types */
648		break;
649	default:
650		return false;
651	}
652
653	return true;
654}
655
656bool
657nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
658{
659	struct nfsd3_renameargs *args = rqstp->rq_argp;
660
661	return svcxdr_decode_diropargs3(xdr, &args->ffh,
662					&args->fname, &args->flen) &&
663		svcxdr_decode_diropargs3(xdr, &args->tfh,
664					 &args->tname, &args->tlen);
665}
666
667bool
668nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
669{
670	struct nfsd3_linkargs *args = rqstp->rq_argp;
671
672	return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
673		svcxdr_decode_diropargs3(xdr, &args->tfh,
674					 &args->tname, &args->tlen);
675}
676
677bool
678nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
679{
680	struct nfsd3_readdirargs *args = rqstp->rq_argp;
681
682	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
683		return false;
684	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
685		return false;
686	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
687	if (!args->verf)
688		return false;
689	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
690		return false;
691
692	return true;
693}
694
695bool
696nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
697{
698	struct nfsd3_readdirargs *args = rqstp->rq_argp;
699	u32 dircount;
700
701	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
702		return false;
703	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
704		return false;
705	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
706	if (!args->verf)
707		return false;
708	/* dircount is ignored */
709	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
710		return false;
711	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
712		return false;
713
714	return true;
715}
716
717bool
718nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
719{
720	struct nfsd3_commitargs *args = rqstp->rq_argp;
721
722	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
723		return false;
724	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
725		return false;
726	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
727		return false;
728
729	return true;
730}
731
732/*
733 * XDR encode functions
734 */
735
736/* GETATTR */
737bool
738nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
739{
740	struct nfsd3_attrstat *resp = rqstp->rq_resp;
741
742	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
743		return false;
744	switch (resp->status) {
745	case nfs_ok:
746		lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
747		if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
748			return false;
749		break;
750	}
751
752	return true;
753}
754
755/* SETATTR, REMOVE, RMDIR */
756bool
757nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
758{
759	struct nfsd3_attrstat *resp = rqstp->rq_resp;
760
761	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
762		svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
763}
764
765/* LOOKUP */
766bool
767nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
768{
769	struct nfsd3_diropres *resp = rqstp->rq_resp;
770
771	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
772		return false;
773	switch (resp->status) {
774	case nfs_ok:
775		if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
776			return false;
777		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
778			return false;
779		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
780			return false;
781		break;
782	default:
783		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
784			return false;
785	}
786
787	return true;
788}
789
790/* ACCESS */
791bool
792nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
793{
794	struct nfsd3_accessres *resp = rqstp->rq_resp;
795
796	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
797		return false;
798	switch (resp->status) {
799	case nfs_ok:
800		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
801			return false;
802		if (xdr_stream_encode_u32(xdr, resp->access) < 0)
803			return false;
804		break;
805	default:
806		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
807			return false;
808	}
809
810	return true;
811}
812
813/* READLINK */
814bool
815nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
816{
817	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
818	struct kvec *head = rqstp->rq_res.head;
819
820	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
821		return false;
822	switch (resp->status) {
823	case nfs_ok:
824		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
825			return false;
826		if (xdr_stream_encode_u32(xdr, resp->len) < 0)
827			return false;
828		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0,
829					   resp->len);
830		if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
831			return false;
832		break;
833	default:
834		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
835			return false;
836	}
837
838	return true;
839}
840
841/* READ */
842bool
843nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
844{
845	struct nfsd3_readres *resp = rqstp->rq_resp;
846	struct kvec *head = rqstp->rq_res.head;
847
848	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
849		return false;
850	switch (resp->status) {
851	case nfs_ok:
852		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
853			return false;
854		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
855			return false;
856		if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
857			return false;
858		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
859			return false;
860		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
861					   rqstp->rq_res.page_base,
862					   resp->count);
863		if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
864			return false;
865		break;
866	default:
867		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
868			return false;
869	}
870
871	return true;
872}
873
874/* WRITE */
875bool
876nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
877{
878	struct nfsd3_writeres *resp = rqstp->rq_resp;
879
880	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
881		return false;
882	switch (resp->status) {
883	case nfs_ok:
884		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
885			return false;
886		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
887			return false;
888		if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
889			return false;
890		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
891			return false;
892		break;
893	default:
894		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
895			return false;
896	}
897
898	return true;
899}
900
901/* CREATE, MKDIR, SYMLINK, MKNOD */
902bool
903nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
904{
905	struct nfsd3_diropres *resp = rqstp->rq_resp;
906
907	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
908		return false;
909	switch (resp->status) {
910	case nfs_ok:
911		if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
912			return false;
913		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
914			return false;
915		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
916			return false;
917		break;
918	default:
919		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
920			return false;
921	}
922
923	return true;
924}
925
926/* RENAME */
927bool
928nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
929{
930	struct nfsd3_renameres *resp = rqstp->rq_resp;
931
932	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
933		svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
934		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
935}
936
937/* LINK */
938bool
939nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
940{
941	struct nfsd3_linkres *resp = rqstp->rq_resp;
942
943	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
944		svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
945		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
946}
947
948/* READDIR */
949bool
950nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
951{
952	struct nfsd3_readdirres *resp = rqstp->rq_resp;
953	struct xdr_buf *dirlist = &resp->dirlist;
954
955	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
956		return false;
957	switch (resp->status) {
958	case nfs_ok:
959		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
960			return false;
961		if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
962			return false;
963		svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
964					   dirlist->len);
965		/* no more entries */
966		if (xdr_stream_encode_item_absent(xdr) < 0)
967			return false;
968		if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
969			return false;
970		break;
971	default:
972		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
973			return false;
974	}
975
976	return true;
977}
978
979static __be32
980compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
981		 const char *name, int namlen, u64 ino)
982{
983	struct svc_export	*exp;
984	struct dentry		*dparent, *dchild;
985	__be32 rv = nfserr_noent;
986
987	dparent = cd->fh.fh_dentry;
988	exp  = cd->fh.fh_export;
989
990	if (isdotent(name, namlen)) {
991		if (namlen == 2) {
992			dchild = dget_parent(dparent);
993			/*
994			 * Don't return filehandle for ".." if we're at
995			 * the filesystem or export root:
996			 */
997			if (dchild == dparent)
998				goto out;
999			if (dparent == exp->ex_path.dentry)
1000				goto out;
1001		} else
1002			dchild = dget(dparent);
1003	} else
1004		dchild = lookup_positive_unlocked(name, dparent, namlen);
1005	if (IS_ERR(dchild))
1006		return rv;
1007	if (d_mountpoint(dchild))
1008		goto out;
1009	if (dchild->d_inode->i_ino != ino)
1010		goto out;
1011	rv = fh_compose(fhp, exp, dchild, &cd->fh);
1012out:
1013	dput(dchild);
1014	return rv;
1015}
1016
1017/**
1018 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1019 * @resp: readdir result context
1020 * @offset: offset cookie to encode
1021 *
1022 * The buffer space for the offset cookie has already been reserved
1023 * by svcxdr_encode_entry3_common().
1024 */
1025void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1026{
1027	__be64 cookie = cpu_to_be64(offset);
1028
1029	if (!resp->cookie_offset)
1030		return;
1031	write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1032			       sizeof(cookie));
1033	resp->cookie_offset = 0;
1034}
1035
1036static bool
1037svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1038			    int namlen, loff_t offset, u64 ino)
1039{
1040	struct xdr_buf *dirlist = &resp->dirlist;
1041	struct xdr_stream *xdr = &resp->xdr;
1042
1043	if (xdr_stream_encode_item_present(xdr) < 0)
1044		return false;
1045	/* fileid */
1046	if (xdr_stream_encode_u64(xdr, ino) < 0)
1047		return false;
1048	/* name */
1049	if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1050		return false;
1051	/* cookie */
1052	resp->cookie_offset = dirlist->len;
1053	if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1054		return false;
1055
1056	return true;
1057}
1058
1059/**
1060 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1061 * @data: directory context
1062 * @name: name of the object to be encoded
1063 * @namlen: length of that name, in bytes
1064 * @offset: the offset of the previous entry
1065 * @ino: the fileid of this entry
1066 * @d_type: unused
1067 *
1068 * Return values:
1069 *   %0: Entry was successfully encoded.
1070 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1071 *
1072 * On exit, the following fields are updated:
1073 *   - resp->xdr
1074 *   - resp->common.err
1075 *   - resp->cookie_offset
1076 */
1077int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1078			  loff_t offset, u64 ino, unsigned int d_type)
1079{
1080	struct readdir_cd *ccd = data;
1081	struct nfsd3_readdirres *resp = container_of(ccd,
1082						     struct nfsd3_readdirres,
1083						     common);
1084	unsigned int starting_length = resp->dirlist.len;
1085
1086	/* The offset cookie for the previous entry */
1087	nfs3svc_encode_cookie3(resp, offset);
1088
1089	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1090		goto out_toosmall;
1091
1092	xdr_commit_encode(&resp->xdr);
1093	resp->common.err = nfs_ok;
1094	return 0;
1095
1096out_toosmall:
1097	resp->cookie_offset = 0;
1098	resp->common.err = nfserr_toosmall;
1099	resp->dirlist.len = starting_length;
1100	return -EINVAL;
1101}
1102
1103static bool
1104svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1105			  int namlen, u64 ino)
1106{
1107	struct xdr_stream *xdr = &resp->xdr;
1108	struct svc_fh *fhp = &resp->scratch;
1109	bool result;
1110
1111	result = false;
1112	fh_init(fhp, NFS3_FHSIZE);
1113	if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1114		goto out_noattrs;
1115
1116	if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1117		goto out;
1118	if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1119		goto out;
1120	result = true;
1121
1122out:
1123	fh_put(fhp);
1124	return result;
1125
1126out_noattrs:
1127	if (xdr_stream_encode_item_absent(xdr) < 0)
1128		return false;
1129	if (xdr_stream_encode_item_absent(xdr) < 0)
1130		return false;
1131	return true;
1132}
1133
1134/**
1135 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1136 * @data: directory context
1137 * @name: name of the object to be encoded
1138 * @namlen: length of that name, in bytes
1139 * @offset: the offset of the previous entry
1140 * @ino: the fileid of this entry
1141 * @d_type: unused
1142 *
1143 * Return values:
1144 *   %0: Entry was successfully encoded.
1145 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1146 *
1147 * On exit, the following fields are updated:
1148 *   - resp->xdr
1149 *   - resp->common.err
1150 *   - resp->cookie_offset
1151 */
1152int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1153			      loff_t offset, u64 ino, unsigned int d_type)
1154{
1155	struct readdir_cd *ccd = data;
1156	struct nfsd3_readdirres *resp = container_of(ccd,
1157						     struct nfsd3_readdirres,
1158						     common);
1159	unsigned int starting_length = resp->dirlist.len;
1160
1161	/* The offset cookie for the previous entry */
1162	nfs3svc_encode_cookie3(resp, offset);
1163
1164	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1165		goto out_toosmall;
1166	if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1167		goto out_toosmall;
1168
1169	xdr_commit_encode(&resp->xdr);
1170	resp->common.err = nfs_ok;
1171	return 0;
1172
1173out_toosmall:
1174	resp->cookie_offset = 0;
1175	resp->common.err = nfserr_toosmall;
1176	resp->dirlist.len = starting_length;
1177	return -EINVAL;
1178}
1179
1180static bool
1181svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1182			   const struct nfsd3_fsstatres *resp)
1183{
1184	const struct kstatfs *s = &resp->stats;
1185	u64 bs = s->f_bsize;
1186	__be32 *p;
1187
1188	p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1189	if (!p)
1190		return false;
1191	p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1192	p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1193	p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1194	p = xdr_encode_hyper(p, s->f_files);		/* total inodes */
1195	p = xdr_encode_hyper(p, s->f_ffree);		/* free inodes */
1196	p = xdr_encode_hyper(p, s->f_ffree);		/* user available inodes */
1197	*p = cpu_to_be32(resp->invarsec);		/* mean unchanged time */
1198
1199	return true;
1200}
1201
1202/* FSSTAT */
1203bool
1204nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1205{
1206	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1207
1208	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1209		return false;
1210	switch (resp->status) {
1211	case nfs_ok:
1212		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1213			return false;
1214		if (!svcxdr_encode_fsstat3resok(xdr, resp))
1215			return false;
1216		break;
1217	default:
1218		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1219			return false;
1220	}
1221
1222	return true;
1223}
1224
1225static bool
1226svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1227			   const struct nfsd3_fsinfores *resp)
1228{
1229	__be32 *p;
1230
1231	p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1232	if (!p)
1233		return false;
1234	*p++ = cpu_to_be32(resp->f_rtmax);
1235	*p++ = cpu_to_be32(resp->f_rtpref);
1236	*p++ = cpu_to_be32(resp->f_rtmult);
1237	*p++ = cpu_to_be32(resp->f_wtmax);
1238	*p++ = cpu_to_be32(resp->f_wtpref);
1239	*p++ = cpu_to_be32(resp->f_wtmult);
1240	*p++ = cpu_to_be32(resp->f_dtpref);
1241	p = xdr_encode_hyper(p, resp->f_maxfilesize);
1242	p = encode_nfstime3(p, &nfs3svc_time_delta);
1243	*p = cpu_to_be32(resp->f_properties);
1244
1245	return true;
1246}
1247
1248/* FSINFO */
1249bool
1250nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1251{
1252	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1253
1254	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1255		return false;
1256	switch (resp->status) {
1257	case nfs_ok:
1258		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1259			return false;
1260		if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1261			return false;
1262		break;
1263	default:
1264		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1265			return false;
1266	}
1267
1268	return true;
1269}
1270
1271static bool
1272svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1273			     const struct nfsd3_pathconfres *resp)
1274{
1275	__be32 *p;
1276
1277	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1278	if (!p)
1279		return false;
1280	*p++ = cpu_to_be32(resp->p_link_max);
1281	*p++ = cpu_to_be32(resp->p_name_max);
1282	p = xdr_encode_bool(p, resp->p_no_trunc);
1283	p = xdr_encode_bool(p, resp->p_chown_restricted);
1284	p = xdr_encode_bool(p, resp->p_case_insensitive);
1285	xdr_encode_bool(p, resp->p_case_preserving);
1286
1287	return true;
1288}
1289
1290/* PATHCONF */
1291bool
1292nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1293{
1294	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1295
1296	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1297		return false;
1298	switch (resp->status) {
1299	case nfs_ok:
1300		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1301			return false;
1302		if (!svcxdr_encode_pathconf3resok(xdr, resp))
1303			return false;
1304		break;
1305	default:
1306		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1307			return false;
1308	}
1309
1310	return true;
1311}
1312
1313/* COMMIT */
1314bool
1315nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1316{
1317	struct nfsd3_commitres *resp = rqstp->rq_resp;
1318
1319	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1320		return false;
1321	switch (resp->status) {
1322	case nfs_ok:
1323		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1324			return false;
1325		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1326			return false;
1327		break;
1328	default:
1329		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1330			return false;
1331	}
1332
1333	return true;
1334}
1335
1336/*
1337 * XDR release functions
1338 */
1339void
1340nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1341{
1342	struct nfsd3_attrstat *resp = rqstp->rq_resp;
1343
1344	fh_put(&resp->fh);
1345}
1346
1347void
1348nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1349{
1350	struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1351
1352	fh_put(&resp->fh1);
1353	fh_put(&resp->fh2);
1354}
1355