Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/nfs/nfs2xdr.c
4 : : *
5 : : * XDR functions to encode/decode NFS RPC arguments and results.
6 : : *
7 : : * Copyright (C) 1992, 1993, 1994 Rick Sladkey
8 : : * Copyright (C) 1996 Olaf Kirch
9 : : * 04 Aug 1998 Ion Badulescu <ionut@cs.columbia.edu>
10 : : * FIFO's need special handling in NFSv2
11 : : */
12 : :
13 : : #include <linux/param.h>
14 : : #include <linux/time.h>
15 : : #include <linux/mm.h>
16 : : #include <linux/errno.h>
17 : : #include <linux/string.h>
18 : : #include <linux/in.h>
19 : : #include <linux/pagemap.h>
20 : : #include <linux/proc_fs.h>
21 : : #include <linux/sunrpc/clnt.h>
22 : : #include <linux/nfs.h>
23 : : #include <linux/nfs2.h>
24 : : #include <linux/nfs_fs.h>
25 : : #include "nfstrace.h"
26 : : #include "internal.h"
27 : :
28 : : #define NFSDBG_FACILITY NFSDBG_XDR
29 : :
30 : : /* Mapping from NFS error code to "errno" error code. */
31 : : #define errno_NFSERR_IO EIO
32 : :
33 : : /*
34 : : * Declare the space requirements for NFS arguments and replies as
35 : : * number of 32bit-words
36 : : */
37 : : #define NFS_fhandle_sz (8)
38 : : #define NFS_sattr_sz (8)
39 : : #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
40 : : #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
41 : : #define NFS_fattr_sz (17)
42 : : #define NFS_info_sz (5)
43 : : #define NFS_entry_sz (NFS_filename_sz+3)
44 : :
45 : : #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
46 : : #define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
47 : : #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
48 : : #define NFS_readlinkargs_sz (NFS_fhandle_sz)
49 : : #define NFS_readargs_sz (NFS_fhandle_sz+3)
50 : : #define NFS_writeargs_sz (NFS_fhandle_sz+4)
51 : : #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
52 : : #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
53 : : #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
54 : : #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz)
55 : : #define NFS_readdirargs_sz (NFS_fhandle_sz+2)
56 : :
57 : : #define NFS_attrstat_sz (1+NFS_fattr_sz)
58 : : #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
59 : : #define NFS_readlinkres_sz (2+1)
60 : : #define NFS_readres_sz (1+NFS_fattr_sz+1+1)
61 : : #define NFS_writeres_sz (NFS_attrstat_sz)
62 : : #define NFS_stat_sz (1)
63 : : #define NFS_readdirres_sz (1+1)
64 : : #define NFS_statfsres_sz (1+NFS_info_sz)
65 : :
66 : : static int nfs_stat_to_errno(enum nfs_stat);
67 : :
68 : : /*
69 : : * Encode/decode NFSv2 basic data types
70 : : *
71 : : * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
72 : : * "NFS: Network File System Protocol Specification".
73 : : *
74 : : * Not all basic data types have their own encoding and decoding
75 : : * functions. For run-time efficiency, some data types are encoded
76 : : * or decoded inline.
77 : : */
78 : :
79 : : static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt)
80 : : {
81 : 0 : if (clnt && clnt->cl_cred)
82 : 0 : return clnt->cl_cred->user_ns;
83 : : return &init_user_ns;
84 : : }
85 : :
86 : : static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp)
87 : : {
88 : 0 : if (rqstp->rq_task)
89 : 0 : return rpc_userns(rqstp->rq_task->tk_client);
90 : : return &init_user_ns;
91 : : }
92 : :
93 : : /*
94 : : * typedef opaque nfsdata<>;
95 : : */
96 : 0 : static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
97 : : {
98 : : u32 recvd, count;
99 : : __be32 *p;
100 : :
101 : 0 : p = xdr_inline_decode(xdr, 4);
102 : 0 : if (unlikely(!p))
103 : : return -EIO;
104 : : count = be32_to_cpup(p);
105 : 0 : recvd = xdr_read_pages(xdr, count);
106 : 0 : if (unlikely(count > recvd))
107 : : goto out_cheating;
108 : : out:
109 : 0 : result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */
110 : 0 : result->count = count;
111 : 0 : return count;
112 : : out_cheating:
113 : : dprintk("NFS: server cheating in read result: "
114 : : "count %u > recvd %u\n", count, recvd);
115 : : count = recvd;
116 : 0 : goto out;
117 : : }
118 : :
119 : : /*
120 : : * enum stat {
121 : : * NFS_OK = 0,
122 : : * NFSERR_PERM = 1,
123 : : * NFSERR_NOENT = 2,
124 : : * NFSERR_IO = 5,
125 : : * NFSERR_NXIO = 6,
126 : : * NFSERR_ACCES = 13,
127 : : * NFSERR_EXIST = 17,
128 : : * NFSERR_NODEV = 19,
129 : : * NFSERR_NOTDIR = 20,
130 : : * NFSERR_ISDIR = 21,
131 : : * NFSERR_FBIG = 27,
132 : : * NFSERR_NOSPC = 28,
133 : : * NFSERR_ROFS = 30,
134 : : * NFSERR_NAMETOOLONG = 63,
135 : : * NFSERR_NOTEMPTY = 66,
136 : : * NFSERR_DQUOT = 69,
137 : : * NFSERR_STALE = 70,
138 : : * NFSERR_WFLUSH = 99
139 : : * };
140 : : */
141 : 0 : static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
142 : : {
143 : : __be32 *p;
144 : :
145 : 0 : p = xdr_inline_decode(xdr, 4);
146 : 0 : if (unlikely(!p))
147 : : return -EIO;
148 : 0 : if (unlikely(*p != cpu_to_be32(NFS_OK)))
149 : : goto out_status;
150 : 0 : *status = 0;
151 : 0 : return 0;
152 : : out_status:
153 : 0 : *status = be32_to_cpup(p);
154 : 0 : trace_nfs_xdr_status(xdr, (int)*status);
155 : 0 : return 0;
156 : : }
157 : :
158 : : /*
159 : : * 2.3.2. ftype
160 : : *
161 : : * enum ftype {
162 : : * NFNON = 0,
163 : : * NFREG = 1,
164 : : * NFDIR = 2,
165 : : * NFBLK = 3,
166 : : * NFCHR = 4,
167 : : * NFLNK = 5
168 : : * };
169 : : *
170 : : */
171 : : static __be32 *xdr_decode_ftype(__be32 *p, u32 *type)
172 : : {
173 : : *type = be32_to_cpup(p++);
174 : 0 : if (unlikely(*type > NF2FIFO))
175 : : *type = NFBAD;
176 : : return p;
177 : : }
178 : :
179 : : /*
180 : : * 2.3.3. fhandle
181 : : *
182 : : * typedef opaque fhandle[FHSIZE];
183 : : */
184 : 0 : static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
185 : : {
186 : : __be32 *p;
187 : :
188 : 0 : p = xdr_reserve_space(xdr, NFS2_FHSIZE);
189 : 0 : memcpy(p, fh->data, NFS2_FHSIZE);
190 : 0 : }
191 : :
192 : 0 : static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
193 : : {
194 : : __be32 *p;
195 : :
196 : 0 : p = xdr_inline_decode(xdr, NFS2_FHSIZE);
197 : 0 : if (unlikely(!p))
198 : : return -EIO;
199 : 0 : fh->size = NFS2_FHSIZE;
200 : 0 : memcpy(fh->data, p, NFS2_FHSIZE);
201 : 0 : return 0;
202 : : }
203 : :
204 : : /*
205 : : * 2.3.4. timeval
206 : : *
207 : : * struct timeval {
208 : : * unsigned int seconds;
209 : : * unsigned int useconds;
210 : : * };
211 : : */
212 : : static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep)
213 : : {
214 : 0 : *p++ = cpu_to_be32(timep->tv_sec);
215 : 0 : if (timep->tv_nsec != 0)
216 : 0 : *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
217 : : else
218 : 0 : *p++ = cpu_to_be32(0);
219 : : return p;
220 : : }
221 : :
222 : : /*
223 : : * Passing the invalid value useconds=1000000 is a Sun convention for
224 : : * "set to current server time". It's needed to make permissions checks
225 : : * for the "touch" program across v2 mounts to Solaris and Irix servers
226 : : * work correctly. See description of sattr in section 6.1 of "NFS
227 : : * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
228 : : */
229 : : static __be32 *xdr_encode_current_server_time(__be32 *p,
230 : : const struct timespec *timep)
231 : : {
232 : 0 : *p++ = cpu_to_be32(timep->tv_sec);
233 : 0 : *p++ = cpu_to_be32(1000000);
234 : : return p;
235 : : }
236 : :
237 : : static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep)
238 : : {
239 : 0 : timep->tv_sec = be32_to_cpup(p++);
240 : 0 : timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC;
241 : : return p;
242 : : }
243 : :
244 : : /*
245 : : * 2.3.5. fattr
246 : : *
247 : : * struct fattr {
248 : : * ftype type;
249 : : * unsigned int mode;
250 : : * unsigned int nlink;
251 : : * unsigned int uid;
252 : : * unsigned int gid;
253 : : * unsigned int size;
254 : : * unsigned int blocksize;
255 : : * unsigned int rdev;
256 : : * unsigned int blocks;
257 : : * unsigned int fsid;
258 : : * unsigned int fileid;
259 : : * timeval atime;
260 : : * timeval mtime;
261 : : * timeval ctime;
262 : : * };
263 : : *
264 : : */
265 : 0 : static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
266 : : struct user_namespace *userns)
267 : : {
268 : : u32 rdev, type;
269 : : __be32 *p;
270 : :
271 : 0 : p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
272 : 0 : if (unlikely(!p))
273 : : return -EIO;
274 : :
275 : 0 : fattr->valid |= NFS_ATTR_FATTR_V2;
276 : :
277 : : p = xdr_decode_ftype(p, &type);
278 : :
279 : 0 : fattr->mode = be32_to_cpup(p++);
280 : 0 : fattr->nlink = be32_to_cpup(p++);
281 : 0 : fattr->uid = make_kuid(userns, be32_to_cpup(p++));
282 : 0 : if (!uid_valid(fattr->uid))
283 : : goto out_uid;
284 : 0 : fattr->gid = make_kgid(userns, be32_to_cpup(p++));
285 : 0 : if (!gid_valid(fattr->gid))
286 : : goto out_gid;
287 : :
288 : 0 : fattr->size = be32_to_cpup(p++);
289 : 0 : fattr->du.nfs2.blocksize = be32_to_cpup(p++);
290 : :
291 : : rdev = be32_to_cpup(p++);
292 : 0 : fattr->rdev = new_decode_dev(rdev);
293 : 0 : if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
294 : 0 : fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
295 : 0 : fattr->rdev = 0;
296 : : }
297 : :
298 : 0 : fattr->du.nfs2.blocks = be32_to_cpup(p++);
299 : 0 : fattr->fsid.major = be32_to_cpup(p++);
300 : 0 : fattr->fsid.minor = 0;
301 : 0 : fattr->fileid = be32_to_cpup(p++);
302 : :
303 : : p = xdr_decode_time(p, &fattr->atime);
304 : : p = xdr_decode_time(p, &fattr->mtime);
305 : : xdr_decode_time(p, &fattr->ctime);
306 : 0 : fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
307 : :
308 : 0 : return 0;
309 : : out_uid:
310 : : dprintk("NFS: returned invalid uid\n");
311 : : return -EINVAL;
312 : : out_gid:
313 : : dprintk("NFS: returned invalid gid\n");
314 : : return -EINVAL;
315 : : }
316 : :
317 : : /*
318 : : * 2.3.6. sattr
319 : : *
320 : : * struct sattr {
321 : : * unsigned int mode;
322 : : * unsigned int uid;
323 : : * unsigned int gid;
324 : : * unsigned int size;
325 : : * timeval atime;
326 : : * timeval mtime;
327 : : * };
328 : : */
329 : :
330 : : #define NFS2_SATTR_NOT_SET (0xffffffff)
331 : :
332 : : static __be32 *xdr_time_not_set(__be32 *p)
333 : : {
334 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
335 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
336 : : return p;
337 : : }
338 : :
339 : 0 : static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr,
340 : : struct user_namespace *userns)
341 : : {
342 : : struct timespec ts;
343 : : __be32 *p;
344 : :
345 : 0 : p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
346 : :
347 : 0 : if (attr->ia_valid & ATTR_MODE)
348 : 0 : *p++ = cpu_to_be32(attr->ia_mode);
349 : : else
350 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
351 : 0 : if (attr->ia_valid & ATTR_UID)
352 : 0 : *p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
353 : : else
354 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
355 : 0 : if (attr->ia_valid & ATTR_GID)
356 : 0 : *p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
357 : : else
358 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
359 : 0 : if (attr->ia_valid & ATTR_SIZE)
360 : 0 : *p++ = cpu_to_be32((u32)attr->ia_size);
361 : : else
362 : 0 : *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
363 : :
364 : 0 : if (attr->ia_valid & ATTR_ATIME_SET) {
365 : : ts = timespec64_to_timespec(attr->ia_atime);
366 : : p = xdr_encode_time(p, &ts);
367 : 0 : } else if (attr->ia_valid & ATTR_ATIME) {
368 : : ts = timespec64_to_timespec(attr->ia_atime);
369 : : p = xdr_encode_current_server_time(p, &ts);
370 : : } else
371 : : p = xdr_time_not_set(p);
372 : 0 : if (attr->ia_valid & ATTR_MTIME_SET) {
373 : : ts = timespec64_to_timespec(attr->ia_mtime);
374 : : xdr_encode_time(p, &ts);
375 : 0 : } else if (attr->ia_valid & ATTR_MTIME) {
376 : : ts = timespec64_to_timespec(attr->ia_mtime);
377 : : xdr_encode_current_server_time(p, &ts);
378 : : } else
379 : : xdr_time_not_set(p);
380 : 0 : }
381 : :
382 : : /*
383 : : * 2.3.7. filename
384 : : *
385 : : * typedef string filename<MAXNAMLEN>;
386 : : */
387 : 0 : static void encode_filename(struct xdr_stream *xdr,
388 : : const char *name, u32 length)
389 : : {
390 : : __be32 *p;
391 : :
392 : 0 : WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
393 : 0 : p = xdr_reserve_space(xdr, 4 + length);
394 : 0 : xdr_encode_opaque(p, name, length);
395 : 0 : }
396 : :
397 : 0 : static int decode_filename_inline(struct xdr_stream *xdr,
398 : : const char **name, u32 *length)
399 : : {
400 : : __be32 *p;
401 : : u32 count;
402 : :
403 : 0 : p = xdr_inline_decode(xdr, 4);
404 : 0 : if (unlikely(!p))
405 : : return -EIO;
406 : : count = be32_to_cpup(p);
407 : 0 : if (count > NFS3_MAXNAMLEN)
408 : : goto out_nametoolong;
409 : 0 : p = xdr_inline_decode(xdr, count);
410 : 0 : if (unlikely(!p))
411 : : return -EIO;
412 : 0 : *name = (const char *)p;
413 : 0 : *length = count;
414 : 0 : return 0;
415 : : out_nametoolong:
416 : : dprintk("NFS: returned filename too long: %u\n", count);
417 : : return -ENAMETOOLONG;
418 : : }
419 : :
420 : : /*
421 : : * 2.3.8. path
422 : : *
423 : : * typedef string path<MAXPATHLEN>;
424 : : */
425 : 0 : static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
426 : : {
427 : : __be32 *p;
428 : :
429 : 0 : p = xdr_reserve_space(xdr, 4);
430 : 0 : *p = cpu_to_be32(length);
431 : 0 : xdr_write_pages(xdr, pages, 0, length);
432 : 0 : }
433 : :
434 : 0 : static int decode_path(struct xdr_stream *xdr)
435 : : {
436 : : u32 length, recvd;
437 : : __be32 *p;
438 : :
439 : 0 : p = xdr_inline_decode(xdr, 4);
440 : 0 : if (unlikely(!p))
441 : : return -EIO;
442 : : length = be32_to_cpup(p);
443 : 0 : if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
444 : : goto out_size;
445 : 0 : recvd = xdr_read_pages(xdr, length);
446 : 0 : if (unlikely(length > recvd))
447 : : goto out_cheating;
448 : 0 : xdr_terminate_string(xdr->buf, length);
449 : 0 : return 0;
450 : : out_size:
451 : : dprintk("NFS: returned pathname too long: %u\n", length);
452 : : return -ENAMETOOLONG;
453 : : out_cheating:
454 : : dprintk("NFS: server cheating in pathname result: "
455 : : "length %u > received %u\n", length, recvd);
456 : : return -EIO;
457 : : }
458 : :
459 : : /*
460 : : * 2.3.9. attrstat
461 : : *
462 : : * union attrstat switch (stat status) {
463 : : * case NFS_OK:
464 : : * fattr attributes;
465 : : * default:
466 : : * void;
467 : : * };
468 : : */
469 : 0 : static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
470 : : __u32 *op_status,
471 : : struct user_namespace *userns)
472 : : {
473 : : enum nfs_stat status;
474 : : int error;
475 : :
476 : 0 : error = decode_stat(xdr, &status);
477 : 0 : if (unlikely(error))
478 : : goto out;
479 : 0 : if (op_status)
480 : 0 : *op_status = status;
481 : 0 : if (status != NFS_OK)
482 : : goto out_default;
483 : 0 : error = decode_fattr(xdr, result, userns);
484 : : out:
485 : 0 : return error;
486 : : out_default:
487 : 0 : return nfs_stat_to_errno(status);
488 : : }
489 : :
490 : : /*
491 : : * 2.3.10. diropargs
492 : : *
493 : : * struct diropargs {
494 : : * fhandle dir;
495 : : * filename name;
496 : : * };
497 : : */
498 : : static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
499 : : const char *name, u32 length)
500 : : {
501 : 0 : encode_fhandle(xdr, fh);
502 : 0 : encode_filename(xdr, name, length);
503 : : }
504 : :
505 : : /*
506 : : * 2.3.11. diropres
507 : : *
508 : : * union diropres switch (stat status) {
509 : : * case NFS_OK:
510 : : * struct {
511 : : * fhandle file;
512 : : * fattr attributes;
513 : : * } diropok;
514 : : * default:
515 : : * void;
516 : : * };
517 : : */
518 : 0 : static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result,
519 : : struct user_namespace *userns)
520 : : {
521 : : int error;
522 : :
523 : 0 : error = decode_fhandle(xdr, result->fh);
524 : 0 : if (unlikely(error))
525 : : goto out;
526 : 0 : error = decode_fattr(xdr, result->fattr, userns);
527 : : out:
528 : 0 : return error;
529 : : }
530 : :
531 : 0 : static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result,
532 : : struct user_namespace *userns)
533 : : {
534 : : enum nfs_stat status;
535 : : int error;
536 : :
537 : 0 : error = decode_stat(xdr, &status);
538 : 0 : if (unlikely(error))
539 : : goto out;
540 : 0 : if (status != NFS_OK)
541 : : goto out_default;
542 : 0 : error = decode_diropok(xdr, result, userns);
543 : : out:
544 : 0 : return error;
545 : : out_default:
546 : 0 : return nfs_stat_to_errno(status);
547 : : }
548 : :
549 : :
550 : : /*
551 : : * NFSv2 XDR encode functions
552 : : *
553 : : * NFSv2 argument types are defined in section 2.2 of RFC 1094:
554 : : * "NFS: Network File System Protocol Specification".
555 : : */
556 : :
557 : 0 : static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
558 : : struct xdr_stream *xdr,
559 : : const void *data)
560 : : {
561 : : const struct nfs_fh *fh = data;
562 : :
563 : 0 : encode_fhandle(xdr, fh);
564 : 0 : }
565 : :
566 : : /*
567 : : * 2.2.3. sattrargs
568 : : *
569 : : * struct sattrargs {
570 : : * fhandle file;
571 : : * sattr attributes;
572 : : * };
573 : : */
574 : 0 : static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
575 : : struct xdr_stream *xdr,
576 : : const void *data)
577 : : {
578 : : const struct nfs_sattrargs *args = data;
579 : :
580 : 0 : encode_fhandle(xdr, args->fh);
581 : 0 : encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
582 : 0 : }
583 : :
584 : 0 : static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
585 : : struct xdr_stream *xdr,
586 : : const void *data)
587 : : {
588 : : const struct nfs_diropargs *args = data;
589 : :
590 : 0 : encode_diropargs(xdr, args->fh, args->name, args->len);
591 : 0 : }
592 : :
593 : 0 : static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
594 : : struct xdr_stream *xdr,
595 : : const void *data)
596 : : {
597 : : const struct nfs_readlinkargs *args = data;
598 : :
599 : 0 : encode_fhandle(xdr, args->fh);
600 : 0 : rpc_prepare_reply_pages(req, args->pages, args->pgbase,
601 : : args->pglen, NFS_readlinkres_sz);
602 : 0 : }
603 : :
604 : : /*
605 : : * 2.2.7. readargs
606 : : *
607 : : * struct readargs {
608 : : * fhandle file;
609 : : * unsigned offset;
610 : : * unsigned count;
611 : : * unsigned totalcount;
612 : : * };
613 : : */
614 : 0 : static void encode_readargs(struct xdr_stream *xdr,
615 : : const struct nfs_pgio_args *args)
616 : : {
617 : 0 : u32 offset = args->offset;
618 : 0 : u32 count = args->count;
619 : : __be32 *p;
620 : :
621 : 0 : encode_fhandle(xdr, args->fh);
622 : :
623 : 0 : p = xdr_reserve_space(xdr, 4 + 4 + 4);
624 : 0 : *p++ = cpu_to_be32(offset);
625 : 0 : *p++ = cpu_to_be32(count);
626 : 0 : *p = cpu_to_be32(count);
627 : 0 : }
628 : :
629 : 0 : static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
630 : : struct xdr_stream *xdr,
631 : : const void *data)
632 : : {
633 : : const struct nfs_pgio_args *args = data;
634 : :
635 : 0 : encode_readargs(xdr, args);
636 : 0 : rpc_prepare_reply_pages(req, args->pages, args->pgbase,
637 : : args->count, NFS_readres_sz);
638 : 0 : req->rq_rcv_buf.flags |= XDRBUF_READ;
639 : 0 : }
640 : :
641 : : /*
642 : : * 2.2.9. writeargs
643 : : *
644 : : * struct writeargs {
645 : : * fhandle file;
646 : : * unsigned beginoffset;
647 : : * unsigned offset;
648 : : * unsigned totalcount;
649 : : * nfsdata data;
650 : : * };
651 : : */
652 : 0 : static void encode_writeargs(struct xdr_stream *xdr,
653 : : const struct nfs_pgio_args *args)
654 : : {
655 : 0 : u32 offset = args->offset;
656 : 0 : u32 count = args->count;
657 : : __be32 *p;
658 : :
659 : 0 : encode_fhandle(xdr, args->fh);
660 : :
661 : 0 : p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
662 : 0 : *p++ = cpu_to_be32(offset);
663 : 0 : *p++ = cpu_to_be32(offset);
664 : 0 : *p++ = cpu_to_be32(count);
665 : :
666 : : /* nfsdata */
667 : 0 : *p = cpu_to_be32(count);
668 : 0 : xdr_write_pages(xdr, args->pages, args->pgbase, count);
669 : 0 : }
670 : :
671 : 0 : static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
672 : : struct xdr_stream *xdr,
673 : : const void *data)
674 : : {
675 : : const struct nfs_pgio_args *args = data;
676 : :
677 : 0 : encode_writeargs(xdr, args);
678 : 0 : xdr->buf->flags |= XDRBUF_WRITE;
679 : 0 : }
680 : :
681 : : /*
682 : : * 2.2.10. createargs
683 : : *
684 : : * struct createargs {
685 : : * diropargs where;
686 : : * sattr attributes;
687 : : * };
688 : : */
689 : 0 : static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
690 : : struct xdr_stream *xdr,
691 : : const void *data)
692 : : {
693 : : const struct nfs_createargs *args = data;
694 : :
695 : 0 : encode_diropargs(xdr, args->fh, args->name, args->len);
696 : 0 : encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
697 : 0 : }
698 : :
699 : 0 : static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
700 : : struct xdr_stream *xdr,
701 : : const void *data)
702 : : {
703 : : const struct nfs_removeargs *args = data;
704 : :
705 : 0 : encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
706 : 0 : }
707 : :
708 : : /*
709 : : * 2.2.12. renameargs
710 : : *
711 : : * struct renameargs {
712 : : * diropargs from;
713 : : * diropargs to;
714 : : * };
715 : : */
716 : 0 : static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
717 : : struct xdr_stream *xdr,
718 : : const void *data)
719 : : {
720 : : const struct nfs_renameargs *args = data;
721 : 0 : const struct qstr *old = args->old_name;
722 : 0 : const struct qstr *new = args->new_name;
723 : :
724 : 0 : encode_diropargs(xdr, args->old_dir, old->name, old->len);
725 : 0 : encode_diropargs(xdr, args->new_dir, new->name, new->len);
726 : 0 : }
727 : :
728 : : /*
729 : : * 2.2.13. linkargs
730 : : *
731 : : * struct linkargs {
732 : : * fhandle from;
733 : : * diropargs to;
734 : : * };
735 : : */
736 : 0 : static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
737 : : struct xdr_stream *xdr,
738 : : const void *data)
739 : : {
740 : : const struct nfs_linkargs *args = data;
741 : :
742 : 0 : encode_fhandle(xdr, args->fromfh);
743 : 0 : encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
744 : 0 : }
745 : :
746 : : /*
747 : : * 2.2.14. symlinkargs
748 : : *
749 : : * struct symlinkargs {
750 : : * diropargs from;
751 : : * path to;
752 : : * sattr attributes;
753 : : * };
754 : : */
755 : 0 : static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
756 : : struct xdr_stream *xdr,
757 : : const void *data)
758 : : {
759 : : const struct nfs_symlinkargs *args = data;
760 : :
761 : 0 : encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
762 : 0 : encode_path(xdr, args->pages, args->pathlen);
763 : 0 : encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
764 : 0 : }
765 : :
766 : : /*
767 : : * 2.2.17. readdirargs
768 : : *
769 : : * struct readdirargs {
770 : : * fhandle dir;
771 : : * nfscookie cookie;
772 : : * unsigned count;
773 : : * };
774 : : */
775 : 0 : static void encode_readdirargs(struct xdr_stream *xdr,
776 : : const struct nfs_readdirargs *args)
777 : : {
778 : : __be32 *p;
779 : :
780 : 0 : encode_fhandle(xdr, args->fh);
781 : :
782 : 0 : p = xdr_reserve_space(xdr, 4 + 4);
783 : 0 : *p++ = cpu_to_be32(args->cookie);
784 : 0 : *p = cpu_to_be32(args->count);
785 : 0 : }
786 : :
787 : 0 : static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
788 : : struct xdr_stream *xdr,
789 : : const void *data)
790 : : {
791 : : const struct nfs_readdirargs *args = data;
792 : :
793 : 0 : encode_readdirargs(xdr, args);
794 : 0 : rpc_prepare_reply_pages(req, args->pages, 0,
795 : : args->count, NFS_readdirres_sz);
796 : 0 : }
797 : :
798 : : /*
799 : : * NFSv2 XDR decode functions
800 : : *
801 : : * NFSv2 result types are defined in section 2.2 of RFC 1094:
802 : : * "NFS: Network File System Protocol Specification".
803 : : */
804 : :
805 : 0 : static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
806 : : void *__unused)
807 : : {
808 : : enum nfs_stat status;
809 : : int error;
810 : :
811 : 0 : error = decode_stat(xdr, &status);
812 : 0 : if (unlikely(error))
813 : : goto out;
814 : 0 : if (status != NFS_OK)
815 : : goto out_default;
816 : : out:
817 : : return error;
818 : : out_default:
819 : 0 : return nfs_stat_to_errno(status);
820 : : }
821 : :
822 : 0 : static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
823 : : void *result)
824 : : {
825 : 0 : return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req));
826 : : }
827 : :
828 : 0 : static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
829 : : void *result)
830 : : {
831 : 0 : return decode_diropres(xdr, result, rpc_rqst_userns(req));
832 : : }
833 : :
834 : : /*
835 : : * 2.2.6. readlinkres
836 : : *
837 : : * union readlinkres switch (stat status) {
838 : : * case NFS_OK:
839 : : * path data;
840 : : * default:
841 : : * void;
842 : : * };
843 : : */
844 : 0 : static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
845 : : struct xdr_stream *xdr, void *__unused)
846 : : {
847 : : enum nfs_stat status;
848 : : int error;
849 : :
850 : 0 : error = decode_stat(xdr, &status);
851 : 0 : if (unlikely(error))
852 : : goto out;
853 : 0 : if (status != NFS_OK)
854 : : goto out_default;
855 : 0 : error = decode_path(xdr);
856 : : out:
857 : 0 : return error;
858 : : out_default:
859 : 0 : return nfs_stat_to_errno(status);
860 : : }
861 : :
862 : : /*
863 : : * 2.2.7. readres
864 : : *
865 : : * union readres switch (stat status) {
866 : : * case NFS_OK:
867 : : * fattr attributes;
868 : : * nfsdata data;
869 : : * default:
870 : : * void;
871 : : * };
872 : : */
873 : 0 : static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
874 : : void *data)
875 : : {
876 : : struct nfs_pgio_res *result = data;
877 : : enum nfs_stat status;
878 : : int error;
879 : :
880 : 0 : error = decode_stat(xdr, &status);
881 : 0 : if (unlikely(error))
882 : : goto out;
883 : 0 : result->op_status = status;
884 : 0 : if (status != NFS_OK)
885 : : goto out_default;
886 : 0 : error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req));
887 : 0 : if (unlikely(error))
888 : : goto out;
889 : 0 : error = decode_nfsdata(xdr, result);
890 : : out:
891 : 0 : return error;
892 : : out_default:
893 : 0 : return nfs_stat_to_errno(status);
894 : : }
895 : :
896 : 0 : static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
897 : : void *data)
898 : : {
899 : : struct nfs_pgio_res *result = data;
900 : :
901 : : /* All NFSv2 writes are "file sync" writes */
902 : 0 : result->verf->committed = NFS_FILE_SYNC;
903 : 0 : return decode_attrstat(xdr, result->fattr, &result->op_status,
904 : : rpc_rqst_userns(req));
905 : : }
906 : :
907 : : /**
908 : : * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
909 : : * the local page cache.
910 : : * @xdr: XDR stream where entry resides
911 : : * @entry: buffer to fill in with entry data
912 : : * @plus: boolean indicating whether this should be a readdirplus entry
913 : : *
914 : : * Returns zero if successful, otherwise a negative errno value is
915 : : * returned.
916 : : *
917 : : * This function is not invoked during READDIR reply decoding, but
918 : : * rather whenever an application invokes the getdents(2) system call
919 : : * on a directory already in our cache.
920 : : *
921 : : * 2.2.17. entry
922 : : *
923 : : * struct entry {
924 : : * unsigned fileid;
925 : : * filename name;
926 : : * nfscookie cookie;
927 : : * entry *nextentry;
928 : : * };
929 : : */
930 : 0 : int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
931 : : bool plus)
932 : : {
933 : : __be32 *p;
934 : : int error;
935 : :
936 : 0 : p = xdr_inline_decode(xdr, 4);
937 : 0 : if (unlikely(!p))
938 : : return -EAGAIN;
939 : 0 : if (*p++ == xdr_zero) {
940 : 0 : p = xdr_inline_decode(xdr, 4);
941 : 0 : if (unlikely(!p))
942 : : return -EAGAIN;
943 : 0 : if (*p++ == xdr_zero)
944 : : return -EAGAIN;
945 : 0 : entry->eof = 1;
946 : 0 : return -EBADCOOKIE;
947 : : }
948 : :
949 : 0 : p = xdr_inline_decode(xdr, 4);
950 : 0 : if (unlikely(!p))
951 : : return -EAGAIN;
952 : 0 : entry->ino = be32_to_cpup(p);
953 : :
954 : 0 : error = decode_filename_inline(xdr, &entry->name, &entry->len);
955 : 0 : if (unlikely(error))
956 : : return error;
957 : :
958 : : /*
959 : : * The type (size and byte order) of nfscookie isn't defined in
960 : : * RFC 1094. This implementation assumes that it's an XDR uint32.
961 : : */
962 : 0 : entry->prev_cookie = entry->cookie;
963 : 0 : p = xdr_inline_decode(xdr, 4);
964 : 0 : if (unlikely(!p))
965 : : return -EAGAIN;
966 : 0 : entry->cookie = be32_to_cpup(p);
967 : :
968 : 0 : entry->d_type = DT_UNKNOWN;
969 : :
970 : 0 : return 0;
971 : : }
972 : :
973 : : /*
974 : : * 2.2.17. readdirres
975 : : *
976 : : * union readdirres switch (stat status) {
977 : : * case NFS_OK:
978 : : * struct {
979 : : * entry *entries;
980 : : * bool eof;
981 : : * } readdirok;
982 : : * default:
983 : : * void;
984 : : * };
985 : : *
986 : : * Read the directory contents into the page cache, but don't
987 : : * touch them. The actual decoding is done by nfs2_decode_dirent()
988 : : * during subsequent nfs_readdir() calls.
989 : : */
990 : : static int decode_readdirok(struct xdr_stream *xdr)
991 : : {
992 : 0 : return xdr_read_pages(xdr, xdr->buf->page_len);
993 : : }
994 : :
995 : 0 : static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
996 : : struct xdr_stream *xdr, void *__unused)
997 : : {
998 : : enum nfs_stat status;
999 : : int error;
1000 : :
1001 : 0 : error = decode_stat(xdr, &status);
1002 : 0 : if (unlikely(error))
1003 : : goto out;
1004 : 0 : if (status != NFS_OK)
1005 : : goto out_default;
1006 : : error = decode_readdirok(xdr);
1007 : : out:
1008 : 0 : return error;
1009 : : out_default:
1010 : 0 : return nfs_stat_to_errno(status);
1011 : : }
1012 : :
1013 : : /*
1014 : : * 2.2.18. statfsres
1015 : : *
1016 : : * union statfsres (stat status) {
1017 : : * case NFS_OK:
1018 : : * struct {
1019 : : * unsigned tsize;
1020 : : * unsigned bsize;
1021 : : * unsigned blocks;
1022 : : * unsigned bfree;
1023 : : * unsigned bavail;
1024 : : * } info;
1025 : : * default:
1026 : : * void;
1027 : : * };
1028 : : */
1029 : 0 : static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1030 : : {
1031 : : __be32 *p;
1032 : :
1033 : 0 : p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1034 : 0 : if (unlikely(!p))
1035 : : return -EIO;
1036 : 0 : result->tsize = be32_to_cpup(p++);
1037 : 0 : result->bsize = be32_to_cpup(p++);
1038 : 0 : result->blocks = be32_to_cpup(p++);
1039 : 0 : result->bfree = be32_to_cpup(p++);
1040 : 0 : result->bavail = be32_to_cpup(p);
1041 : 0 : return 0;
1042 : : }
1043 : :
1044 : 0 : static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
1045 : : void *result)
1046 : : {
1047 : : enum nfs_stat status;
1048 : : int error;
1049 : :
1050 : 0 : error = decode_stat(xdr, &status);
1051 : 0 : if (unlikely(error))
1052 : : goto out;
1053 : 0 : if (status != NFS_OK)
1054 : : goto out_default;
1055 : 0 : error = decode_info(xdr, result);
1056 : : out:
1057 : 0 : return error;
1058 : : out_default:
1059 : 0 : return nfs_stat_to_errno(status);
1060 : : }
1061 : :
1062 : :
1063 : : /*
1064 : : * We need to translate between nfs status return values and
1065 : : * the local errno values which may not be the same.
1066 : : */
1067 : : static const struct {
1068 : : int stat;
1069 : : int errno;
1070 : : } nfs_errtbl[] = {
1071 : : { NFS_OK, 0 },
1072 : : { NFSERR_PERM, -EPERM },
1073 : : { NFSERR_NOENT, -ENOENT },
1074 : : { NFSERR_IO, -errno_NFSERR_IO},
1075 : : { NFSERR_NXIO, -ENXIO },
1076 : : /* { NFSERR_EAGAIN, -EAGAIN }, */
1077 : : { NFSERR_ACCES, -EACCES },
1078 : : { NFSERR_EXIST, -EEXIST },
1079 : : { NFSERR_XDEV, -EXDEV },
1080 : : { NFSERR_NODEV, -ENODEV },
1081 : : { NFSERR_NOTDIR, -ENOTDIR },
1082 : : { NFSERR_ISDIR, -EISDIR },
1083 : : { NFSERR_INVAL, -EINVAL },
1084 : : { NFSERR_FBIG, -EFBIG },
1085 : : { NFSERR_NOSPC, -ENOSPC },
1086 : : { NFSERR_ROFS, -EROFS },
1087 : : { NFSERR_MLINK, -EMLINK },
1088 : : { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
1089 : : { NFSERR_NOTEMPTY, -ENOTEMPTY },
1090 : : { NFSERR_DQUOT, -EDQUOT },
1091 : : { NFSERR_STALE, -ESTALE },
1092 : : { NFSERR_REMOTE, -EREMOTE },
1093 : : #ifdef EWFLUSH
1094 : : { NFSERR_WFLUSH, -EWFLUSH },
1095 : : #endif
1096 : : { NFSERR_BADHANDLE, -EBADHANDLE },
1097 : : { NFSERR_NOT_SYNC, -ENOTSYNC },
1098 : : { NFSERR_BAD_COOKIE, -EBADCOOKIE },
1099 : : { NFSERR_NOTSUPP, -ENOTSUPP },
1100 : : { NFSERR_TOOSMALL, -ETOOSMALL },
1101 : : { NFSERR_SERVERFAULT, -EREMOTEIO },
1102 : : { NFSERR_BADTYPE, -EBADTYPE },
1103 : : { NFSERR_JUKEBOX, -EJUKEBOX },
1104 : : { -1, -EIO }
1105 : : };
1106 : :
1107 : : /**
1108 : : * nfs_stat_to_errno - convert an NFS status code to a local errno
1109 : : * @status: NFS status code to convert
1110 : : *
1111 : : * Returns a local errno value, or -EIO if the NFS status code is
1112 : : * not recognized. This function is used jointly by NFSv2 and NFSv3.
1113 : : */
1114 : : static int nfs_stat_to_errno(enum nfs_stat status)
1115 : : {
1116 : : int i;
1117 : :
1118 : 0 : for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1119 : 0 : if (nfs_errtbl[i].stat == (int)status)
1120 : 0 : return nfs_errtbl[i].errno;
1121 : : }
1122 : : dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1123 : 0 : return nfs_errtbl[i].errno;
1124 : : }
1125 : :
1126 : : #define PROC(proc, argtype, restype, timer) \
1127 : : [NFSPROC_##proc] = { \
1128 : : .p_proc = NFSPROC_##proc, \
1129 : : .p_encode = nfs2_xdr_enc_##argtype, \
1130 : : .p_decode = nfs2_xdr_dec_##restype, \
1131 : : .p_arglen = NFS_##argtype##_sz, \
1132 : : .p_replen = NFS_##restype##_sz, \
1133 : : .p_timer = timer, \
1134 : : .p_statidx = NFSPROC_##proc, \
1135 : : .p_name = #proc, \
1136 : : }
1137 : : const struct rpc_procinfo nfs_procedures[] = {
1138 : : PROC(GETATTR, fhandle, attrstat, 1),
1139 : : PROC(SETATTR, sattrargs, attrstat, 0),
1140 : : PROC(LOOKUP, diropargs, diropres, 2),
1141 : : PROC(READLINK, readlinkargs, readlinkres, 3),
1142 : : PROC(READ, readargs, readres, 3),
1143 : : PROC(WRITE, writeargs, writeres, 4),
1144 : : PROC(CREATE, createargs, diropres, 0),
1145 : : PROC(REMOVE, removeargs, stat, 0),
1146 : : PROC(RENAME, renameargs, stat, 0),
1147 : : PROC(LINK, linkargs, stat, 0),
1148 : : PROC(SYMLINK, symlinkargs, stat, 0),
1149 : : PROC(MKDIR, createargs, diropres, 0),
1150 : : PROC(RMDIR, diropargs, stat, 0),
1151 : : PROC(READDIR, readdirargs, readdirres, 3),
1152 : : PROC(STATFS, fhandle, statfsres, 0),
1153 : : };
1154 : :
1155 : : static unsigned int nfs_version2_counts[ARRAY_SIZE(nfs_procedures)];
1156 : : const struct rpc_version nfs_version2 = {
1157 : : .number = 2,
1158 : : .nrprocs = ARRAY_SIZE(nfs_procedures),
1159 : : .procs = nfs_procedures,
1160 : : .counts = nfs_version2_counts,
1161 : : };
|