aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs3xdr.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-12-14 09:56:30 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-12-16 12:37:23 -0500
commite4f9323409369a3aeb01885c0c4409d2eeec794a (patch)
tree67fffcae54825264e5d908ef72ffb89870670bbd /fs/nfs/nfs3xdr.c
parent9d5a64343925a152e1907c652a0d71d6640868b3 (diff)
NFS: Introduce new-style XDR decoding functions for NFSv2
We'd like to prevent local buffer overflows caused by malicious or broken servers. New xdr_stream style decoders can do that. For efficiency, we also eventually want to be able to pass xdr_streams from call_decode() to all XDR decoding functions, rather than building an xdr_stream in every XDR decoding function in the kernel. Static helper functions are left without the "inline" directive. This allows the compiler to choose automatically how to optimize these for size or speed. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r--fs/nfs/nfs3xdr.c1524
1 files changed, 1445 insertions, 79 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 119844d0b4d5..0f07c6d55131 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -104,13 +104,6 @@ static const umode_t nfs_type2fmt[] = {
104 [NF3FIFO] = S_IFIFO, 104 [NF3FIFO] = S_IFIFO,
105}; 105};
106 106
107static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
108{
109 dprintk("nfs: %s: prematurely hit end of receive buffer. "
110 "Remaining buffer length is %tu words.\n",
111 func, xdr->end - xdr->p);
112}
113
114/* 107/*
115 * While encoding arguments, set up the reply buffer in advance to 108 * While encoding arguments, set up the reply buffer in advance to
116 * receive reply data directly into the page cache. 109 * receive reply data directly into the page cache.
@@ -126,6 +119,16 @@ static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
126 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); 119 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
127} 120}
128 121
122/*
123 * Handle decode buffer overflows out-of-line.
124 */
125static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
126{
127 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
128 "Remaining buffer length is %tu words.\n",
129 func, xdr->end - xdr->p);
130}
131
129 132
130/* 133/*
131 * Common NFS XDR functions as inlines 134 * Common NFS XDR functions as inlines
@@ -284,6 +287,44 @@ static void encode_uint32(struct xdr_stream *xdr, u32 value)
284 *p = cpu_to_be32(value); 287 *p = cpu_to_be32(value);
285} 288}
286 289
290static int decode_uint32(struct xdr_stream *xdr, u32 *value)
291{
292 __be32 *p;
293
294 p = xdr_inline_decode(xdr, 4);
295 if (unlikely(p == NULL))
296 goto out_overflow;
297 *value = be32_to_cpup(p);
298 return 0;
299out_overflow:
300 print_overflow_msg(__func__, xdr);
301 return -EIO;
302}
303
304static int decode_uint64(struct xdr_stream *xdr, u64 *value)
305{
306 __be32 *p;
307
308 p = xdr_inline_decode(xdr, 8);
309 if (unlikely(p == NULL))
310 goto out_overflow;
311 xdr_decode_hyper(p, value);
312 return 0;
313out_overflow:
314 print_overflow_msg(__func__, xdr);
315 return -EIO;
316}
317
318/*
319 * fileid3
320 *
321 * typedef uint64 fileid3;
322 */
323static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
324{
325 return decode_uint64(xdr, fileid);
326}
327
287/* 328/*
288 * filename3 329 * filename3
289 * 330 *
@@ -299,6 +340,33 @@ static void encode_filename3(struct xdr_stream *xdr,
299 xdr_encode_opaque(p, name, length); 340 xdr_encode_opaque(p, name, length);
300} 341}
301 342
343static int decode_inline_filename3(struct xdr_stream *xdr,
344 const char **name, u32 *length)
345{
346 __be32 *p;
347 u32 count;
348
349 p = xdr_inline_decode(xdr, 4);
350 if (unlikely(p == NULL))
351 goto out_overflow;
352 count = be32_to_cpup(p);
353 if (count > NFS3_MAXNAMLEN)
354 goto out_nametoolong;
355 p = xdr_inline_decode(xdr, count);
356 if (unlikely(p == NULL))
357 goto out_overflow;
358 *name = (const char *)p;
359 *length = count;
360 return 0;
361
362out_nametoolong:
363 dprintk("NFS: returned filename too long: %u\n", count);
364 return -ENAMETOOLONG;
365out_overflow:
366 print_overflow_msg(__func__, xdr);
367 return -EIO;
368}
369
302/* 370/*
303 * nfspath3 371 * nfspath3
304 * 372 *
@@ -312,6 +380,39 @@ static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
312 xdr_write_pages(xdr, pages, 0, length); 380 xdr_write_pages(xdr, pages, 0, length);
313} 381}
314 382
383static int decode_nfspath3(struct xdr_stream *xdr)
384{
385 u32 recvd, count;
386 size_t hdrlen;
387 __be32 *p;
388
389 p = xdr_inline_decode(xdr, 4);
390 if (unlikely(p == NULL))
391 goto out_overflow;
392 count = be32_to_cpup(p);
393 if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
394 goto out_nametoolong;
395 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
396 recvd = xdr->buf->len - hdrlen;
397 if (unlikely(count > recvd))
398 goto out_cheating;
399
400 xdr_read_pages(xdr, count);
401 xdr_terminate_string(xdr->buf, count);
402 return 0;
403
404out_nametoolong:
405 dprintk("NFS: returned pathname too long: %u\n", count);
406 return -ENAMETOOLONG;
407out_cheating:
408 dprintk("NFS: server cheating in pathname result: "
409 "count %u > recvd %u\n", count, recvd);
410 return -EIO;
411out_overflow:
412 print_overflow_msg(__func__, xdr);
413 return -EIO;
414}
415
315/* 416/*
316 * cookie3 417 * cookie3
317 * 418 *
@@ -322,6 +423,11 @@ static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
322 return xdr_encode_hyper(p, cookie); 423 return xdr_encode_hyper(p, cookie);
323} 424}
324 425
426static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
427{
428 return decode_uint64(xdr, cookie);
429}
430
325/* 431/*
326 * cookieverf3 432 * cookieverf3
327 * 433 *
@@ -333,6 +439,20 @@ static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
333 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE); 439 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
334} 440}
335 441
442static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
443{
444 __be32 *p;
445
446 p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
447 if (unlikely(p == NULL))
448 goto out_overflow;
449 memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
450 return 0;
451out_overflow:
452 print_overflow_msg(__func__, xdr);
453 return -EIO;
454}
455
336/* 456/*
337 * createverf3 457 * createverf3
338 * 458 *
@@ -346,6 +466,54 @@ static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
346 memcpy(p, verifier, NFS3_CREATEVERFSIZE); 466 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
347} 467}
348 468
469static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
470{
471 __be32 *p;
472
473 p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
474 if (unlikely(p == NULL))
475 goto out_overflow;
476 memcpy(verifier, p, NFS3_WRITEVERFSIZE);
477 return 0;
478out_overflow:
479 print_overflow_msg(__func__, xdr);
480 return -EIO;
481}
482
483/*
484 * size3
485 *
486 * typedef uint64 size3;
487 */
488static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
489{
490 return xdr_decode_hyper(p, size);
491}
492
493/*
494 * nfsstat3
495 *
496 * enum nfsstat3 {
497 * NFS3_OK = 0,
498 * ...
499 * }
500 */
501#define NFS3_OK NFS_OK
502
503static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
504{
505 __be32 *p;
506
507 p = xdr_inline_decode(xdr, 4);
508 if (unlikely(p == NULL))
509 goto out_overflow;
510 *status = be32_to_cpup(p);
511 return 0;
512out_overflow:
513 print_overflow_msg(__func__, xdr);
514 return -EIO;
515}
516
349/* 517/*
350 * ftype3 518 * ftype3
351 * 519 *
@@ -398,6 +566,36 @@ static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
398 xdr_encode_opaque(p, fh->data, fh->size); 566 xdr_encode_opaque(p, fh->data, fh->size);
399} 567}
400 568
569static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
570{
571 u32 length;
572 __be32 *p;
573
574 p = xdr_inline_decode(xdr, 4);
575 if (unlikely(p == NULL))
576 goto out_overflow;
577 length = be32_to_cpup(p++);
578 if (unlikely(length > NFS3_FHSIZE))
579 goto out_toobig;
580 p = xdr_inline_decode(xdr, length);
581 if (unlikely(p == NULL))
582 goto out_overflow;
583 fh->size = length;
584 memcpy(fh->data, p, length);
585 return 0;
586out_toobig:
587 dprintk("NFS: file handle size (%u) too big\n", length);
588 return -E2BIG;
589out_overflow:
590 print_overflow_msg(__func__, xdr);
591 return -EIO;
592}
593
594static void zero_nfs_fh3(struct nfs_fh *fh)
595{
596 memset(fh, 0, sizeof(*fh));
597}
598
401/* 599/*
402 * nfstime3 600 * nfstime3
403 * 601 *
@@ -541,6 +739,153 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
541} 739}
542 740
543/* 741/*
742 * fattr3
743 *
744 * struct fattr3 {
745 * ftype3 type;
746 * mode3 mode;
747 * uint32 nlink;
748 * uid3 uid;
749 * gid3 gid;
750 * size3 size;
751 * size3 used;
752 * specdata3 rdev;
753 * uint64 fsid;
754 * fileid3 fileid;
755 * nfstime3 atime;
756 * nfstime3 mtime;
757 * nfstime3 ctime;
758 * };
759 */
760static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
761{
762 __be32 *p;
763
764 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
765 if (unlikely(p == NULL))
766 goto out_overflow;
767 xdr_decode_fattr(p, fattr);
768 return 0;
769out_overflow:
770 print_overflow_msg(__func__, xdr);
771 return -EIO;
772}
773
774/*
775 * post_op_attr
776 *
777 * union post_op_attr switch (bool attributes_follow) {
778 * case TRUE:
779 * fattr3 attributes;
780 * case FALSE:
781 * void;
782 * };
783 */
784static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
785{
786 __be32 *p;
787
788 p = xdr_inline_decode(xdr, 4);
789 if (unlikely(p == NULL))
790 goto out_overflow;
791 if (*p != xdr_zero)
792 return decode_fattr3(xdr, fattr);
793 return 0;
794out_overflow:
795 print_overflow_msg(__func__, xdr);
796 return -EIO;
797}
798
799/*
800 * wcc_attr
801 * struct wcc_attr {
802 * size3 size;
803 * nfstime3 mtime;
804 * nfstime3 ctime;
805 * };
806 */
807static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
808{
809 __be32 *p;
810
811 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
812 if (unlikely(p == NULL))
813 goto out_overflow;
814 xdr_decode_wcc_attr(p, fattr);
815 return 0;
816out_overflow:
817 print_overflow_msg(__func__, xdr);
818 return -EIO;
819}
820
821/*
822 * pre_op_attr
823 * union pre_op_attr switch (bool attributes_follow) {
824 * case TRUE:
825 * wcc_attr attributes;
826 * case FALSE:
827 * void;
828 * };
829 *
830 * wcc_data
831 *
832 * struct wcc_data {
833 * pre_op_attr before;
834 * post_op_attr after;
835 * };
836 */
837static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
838{
839 __be32 *p;
840
841 p = xdr_inline_decode(xdr, 4);
842 if (unlikely(p == NULL))
843 goto out_overflow;
844 if (*p != xdr_zero)
845 return decode_wcc_attr(xdr, fattr);
846 return 0;
847out_overflow:
848 print_overflow_msg(__func__, xdr);
849 return -EIO;
850}
851
852static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
853{
854 int error;
855
856 error = decode_pre_op_attr(xdr, fattr);
857 if (unlikely(error))
858 goto out;
859 error = decode_post_op_attr(xdr, fattr);
860out:
861 return error;
862}
863
864/*
865 * post_op_fh3
866 *
867 * union post_op_fh3 switch (bool handle_follows) {
868 * case TRUE:
869 * nfs_fh3 handle;
870 * case FALSE:
871 * void;
872 * };
873 */
874static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
875{
876 __be32 *p = xdr_inline_decode(xdr, 4);
877 if (unlikely(p == NULL))
878 goto out_overflow;
879 if (*p != xdr_zero)
880 return decode_nfs_fh3(xdr, fh);
881 zero_nfs_fh3(fh);
882 return 0;
883out_overflow:
884 print_overflow_msg(__func__, xdr);
885 return -EIO;
886}
887
888/*
544 * diropargs3 889 * diropargs3
545 * 890 *
546 * struct diropargs3 { 891 * struct diropargs3 {
@@ -1108,78 +1453,6 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
1108 return pglen; 1453 return pglen;
1109} 1454}
1110 1455
1111__be32 *
1112nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
1113{
1114 __be32 *p;
1115 struct nfs_entry old = *entry;
1116
1117 p = xdr_inline_decode(xdr, 4);
1118 if (unlikely(!p))
1119 goto out_overflow;
1120 if (!ntohl(*p++)) {
1121 p = xdr_inline_decode(xdr, 4);
1122 if (unlikely(!p))
1123 goto out_overflow;
1124 if (!ntohl(*p++))
1125 return ERR_PTR(-EAGAIN);
1126 entry->eof = 1;
1127 return ERR_PTR(-EBADCOOKIE);
1128 }
1129
1130 p = xdr_inline_decode(xdr, 12);
1131 if (unlikely(!p))
1132 goto out_overflow;
1133 p = xdr_decode_hyper(p, &entry->ino);
1134 entry->len = ntohl(*p++);
1135
1136 p = xdr_inline_decode(xdr, entry->len + 8);
1137 if (unlikely(!p))
1138 goto out_overflow;
1139 entry->name = (const char *) p;
1140 p += XDR_QUADLEN(entry->len);
1141 entry->prev_cookie = entry->cookie;
1142 p = xdr_decode_hyper(p, &entry->cookie);
1143
1144 entry->d_type = DT_UNKNOWN;
1145 if (plus) {
1146 entry->fattr->valid = 0;
1147 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
1148 if (IS_ERR(p))
1149 goto out_overflow_exit;
1150 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1151 /* In fact, a post_op_fh3: */
1152 p = xdr_inline_decode(xdr, 4);
1153 if (unlikely(!p))
1154 goto out_overflow;
1155 if (*p++) {
1156 p = xdr_decode_fhandle_stream(xdr, entry->fh);
1157 if (IS_ERR(p))
1158 goto out_overflow_exit;
1159 /* Ugh -- server reply was truncated */
1160 if (p == NULL) {
1161 dprintk("NFS: FH truncated\n");
1162 *entry = old;
1163 return ERR_PTR(-EAGAIN);
1164 }
1165 } else
1166 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
1167 }
1168
1169 p = xdr_inline_peek(xdr, 8);
1170 if (p != NULL)
1171 entry->eof = !p[0] && p[1];
1172 else
1173 entry->eof = 0;
1174
1175 return p;
1176
1177out_overflow:
1178 print_overflow_msg(__func__, xdr);
1179out_overflow_exit:
1180 return ERR_PTR(-EAGAIN);
1181}
1182
1183/* 1456/*
1184 * 3.3.21 COMMIT3args 1457 * 3.3.21 COMMIT3args
1185 * 1458 *
@@ -1275,6 +1548,40 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1275} 1548}
1276 1549
1277/* 1550/*
1551 * 3.3.1 GETATTR3res
1552 *
1553 * struct GETATTR3resok {
1554 * fattr3 obj_attributes;
1555 * };
1556 *
1557 * union GETATTR3res switch (nfsstat3 status) {
1558 * case NFS3_OK:
1559 * GETATTR3resok resok;
1560 * default:
1561 * void;
1562 * };
1563 */
1564static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, __be32 *p,
1565 struct nfs_fattr *result)
1566{
1567 struct xdr_stream xdr;
1568 enum nfs_stat status;
1569 int error;
1570
1571 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1572 error = decode_nfsstat3(&xdr, &status);
1573 if (unlikely(error))
1574 goto out;
1575 if (status != NFS3_OK)
1576 goto out_default;
1577 error = decode_fattr3(&xdr, result);
1578out:
1579 return error;
1580out_default:
1581 return nfs_stat_to_errno(status);
1582}
1583
1584/*
1278 * Decode status+wcc_data reply 1585 * Decode status+wcc_data reply
1279 * SATTR, REMOVE, RMDIR 1586 * SATTR, REMOVE, RMDIR
1280 */ 1587 */
@@ -1289,6 +1596,46 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1289 return status; 1596 return status;
1290} 1597}
1291 1598
1599/*
1600 * 3.3.2 SETATTR3res
1601 *
1602 * struct SETATTR3resok {
1603 * wcc_data obj_wcc;
1604 * };
1605 *
1606 * struct SETATTR3resfail {
1607 * wcc_data obj_wcc;
1608 * };
1609 *
1610 * union SETATTR3res switch (nfsstat3 status) {
1611 * case NFS3_OK:
1612 * SETATTR3resok resok;
1613 * default:
1614 * SETATTR3resfail resfail;
1615 * };
1616 */
1617static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, __be32 *p,
1618 struct nfs_fattr *result)
1619{
1620 struct xdr_stream xdr;
1621 enum nfs_stat status;
1622 int error;
1623
1624 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1625 error = decode_nfsstat3(&xdr, &status);
1626 if (unlikely(error))
1627 goto out;
1628 error = decode_wcc_data(&xdr, result);
1629 if (unlikely(error))
1630 goto out;
1631 if (status != NFS3_OK)
1632 goto out_status;
1633out:
1634 return error;
1635out_status:
1636 return nfs_stat_to_errno(status);
1637}
1638
1292static int 1639static int
1293nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) 1640nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1294{ 1641{
@@ -1315,6 +1662,55 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1315} 1662}
1316 1663
1317/* 1664/*
1665 * 3.3.3 LOOKUP3res
1666 *
1667 * struct LOOKUP3resok {
1668 * nfs_fh3 object;
1669 * post_op_attr obj_attributes;
1670 * post_op_attr dir_attributes;
1671 * };
1672 *
1673 * struct LOOKUP3resfail {
1674 * post_op_attr dir_attributes;
1675 * };
1676 *
1677 * union LOOKUP3res switch (nfsstat3 status) {
1678 * case NFS3_OK:
1679 * LOOKUP3resok resok;
1680 * default:
1681 * LOOKUP3resfail resfail;
1682 * };
1683 */
1684static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, __be32 *p,
1685 struct nfs3_diropres *result)
1686{
1687 struct xdr_stream xdr;
1688 enum nfs_stat status;
1689 int error;
1690
1691 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1692 error = decode_nfsstat3(&xdr, &status);
1693 if (unlikely(error))
1694 goto out;
1695 if (status != NFS3_OK)
1696 goto out_default;
1697 error = decode_nfs_fh3(&xdr, result->fh);
1698 if (unlikely(error))
1699 goto out;
1700 error = decode_post_op_attr(&xdr, result->fattr);
1701 if (unlikely(error))
1702 goto out;
1703 error = decode_post_op_attr(&xdr, result->dir_attr);
1704out:
1705 return error;
1706out_default:
1707 error = decode_post_op_attr(&xdr, result->dir_attr);
1708 if (unlikely(error))
1709 goto out;
1710 return nfs_stat_to_errno(status);
1711}
1712
1713/*
1318 * Decode ACCESS reply 1714 * Decode ACCESS reply
1319 */ 1715 */
1320static int 1716static int
@@ -1330,6 +1726,48 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1330} 1726}
1331 1727
1332/* 1728/*
1729 * 3.3.4 ACCESS3res
1730 *
1731 * struct ACCESS3resok {
1732 * post_op_attr obj_attributes;
1733 * uint32 access;
1734 * };
1735 *
1736 * struct ACCESS3resfail {
1737 * post_op_attr obj_attributes;
1738 * };
1739 *
1740 * union ACCESS3res switch (nfsstat3 status) {
1741 * case NFS3_OK:
1742 * ACCESS3resok resok;
1743 * default:
1744 * ACCESS3resfail resfail;
1745 * };
1746 */
1747static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, __be32 *p,
1748 struct nfs3_accessres *result)
1749{
1750 struct xdr_stream xdr;
1751 enum nfs_stat status;
1752 int error;
1753
1754 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1755 error = decode_nfsstat3(&xdr, &status);
1756 if (unlikely(error))
1757 goto out;
1758 error = decode_post_op_attr(&xdr, result->fattr);
1759 if (unlikely(error))
1760 goto out;
1761 if (status != NFS3_OK)
1762 goto out_default;
1763 error = decode_uint32(&xdr, &result->access);
1764out:
1765 return error;
1766out_default:
1767 return nfs_stat_to_errno(status);
1768}
1769
1770/*
1333 * Decode READLINK reply 1771 * Decode READLINK reply
1334 */ 1772 */
1335static int 1773static int
@@ -1376,6 +1814,48 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1376} 1814}
1377 1815
1378/* 1816/*
1817 * 3.3.5 READLINK3res
1818 *
1819 * struct READLINK3resok {
1820 * post_op_attr symlink_attributes;
1821 * nfspath3 data;
1822 * };
1823 *
1824 * struct READLINK3resfail {
1825 * post_op_attr symlink_attributes;
1826 * };
1827 *
1828 * union READLINK3res switch (nfsstat3 status) {
1829 * case NFS3_OK:
1830 * READLINK3resok resok;
1831 * default:
1832 * READLINK3resfail resfail;
1833 * };
1834 */
1835static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, __be32 *p,
1836 struct nfs_fattr *result)
1837{
1838 struct xdr_stream xdr;
1839 enum nfs_stat status;
1840 int error;
1841
1842 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1843 error = decode_nfsstat3(&xdr, &status);
1844 if (unlikely(error))
1845 goto out;
1846 error = decode_post_op_attr(&xdr, result);
1847 if (unlikely(error))
1848 goto out;
1849 if (status != NFS3_OK)
1850 goto out_default;
1851 error = decode_nfspath3(&xdr);
1852out:
1853 return error;
1854out_default:
1855 return nfs_stat_to_errno(status);
1856}
1857
1858/*
1379 * Decode READ reply 1859 * Decode READ reply
1380 */ 1860 */
1381static int 1861static int
@@ -1429,6 +1909,90 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1429} 1909}
1430 1910
1431/* 1911/*
1912 * 3.3.6 READ3res
1913 *
1914 * struct READ3resok {
1915 * post_op_attr file_attributes;
1916 * count3 count;
1917 * bool eof;
1918 * opaque data<>;
1919 * };
1920 *
1921 * struct READ3resfail {
1922 * post_op_attr file_attributes;
1923 * };
1924 *
1925 * union READ3res switch (nfsstat3 status) {
1926 * case NFS3_OK:
1927 * READ3resok resok;
1928 * default:
1929 * READ3resfail resfail;
1930 * };
1931 */
1932static int decode_read3resok(struct xdr_stream *xdr,
1933 struct nfs_readres *result)
1934{
1935 u32 eof, count, ocount, recvd;
1936 size_t hdrlen;
1937 __be32 *p;
1938
1939 p = xdr_inline_decode(xdr, 4 + 4 + 4);
1940 if (unlikely(p == NULL))
1941 goto out_overflow;
1942 count = be32_to_cpup(p++);
1943 eof = be32_to_cpup(p++);
1944 ocount = be32_to_cpup(p++);
1945 if (unlikely(ocount != count))
1946 goto out_mismatch;
1947 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1948 recvd = xdr->buf->len - hdrlen;
1949 if (unlikely(count > recvd))
1950 goto out_cheating;
1951
1952out:
1953 xdr_read_pages(xdr, count);
1954 result->eof = eof;
1955 result->count = count;
1956 return count;
1957out_mismatch:
1958 dprintk("NFS: READ count doesn't match length of opaque: "
1959 "count %u != ocount %u\n", count, ocount);
1960 return -EIO;
1961out_cheating:
1962 dprintk("NFS: server cheating in read result: "
1963 "count %u > recvd %u\n", count, recvd);
1964 count = recvd;
1965 eof = 0;
1966 goto out;
1967out_overflow:
1968 print_overflow_msg(__func__, xdr);
1969 return -EIO;
1970}
1971
1972static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, __be32 *p,
1973 struct nfs_readres *result)
1974{
1975 struct xdr_stream xdr;
1976 enum nfs_stat status;
1977 int error;
1978
1979 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1980 error = decode_nfsstat3(&xdr, &status);
1981 if (unlikely(error))
1982 goto out;
1983 error = decode_post_op_attr(&xdr, result->fattr);
1984 if (unlikely(error))
1985 goto out;
1986 if (status != NFS3_OK)
1987 goto out_status;
1988 error = decode_read3resok(&xdr, result);
1989out:
1990 return error;
1991out_status:
1992 return nfs_stat_to_errno(status);
1993}
1994
1995/*
1432 * Decode WRITE response 1996 * Decode WRITE response
1433 */ 1997 */
1434static int 1998static int
@@ -1451,6 +2015,78 @@ nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1451} 2015}
1452 2016
1453/* 2017/*
2018 * 3.3.7 WRITE3res
2019 *
2020 * enum stable_how {
2021 * UNSTABLE = 0,
2022 * DATA_SYNC = 1,
2023 * FILE_SYNC = 2
2024 * };
2025 *
2026 * struct WRITE3resok {
2027 * wcc_data file_wcc;
2028 * count3 count;
2029 * stable_how committed;
2030 * writeverf3 verf;
2031 * };
2032 *
2033 * struct WRITE3resfail {
2034 * wcc_data file_wcc;
2035 * };
2036 *
2037 * union WRITE3res switch (nfsstat3 status) {
2038 * case NFS3_OK:
2039 * WRITE3resok resok;
2040 * default:
2041 * WRITE3resfail resfail;
2042 * };
2043 */
2044static int decode_write3resok(struct xdr_stream *xdr,
2045 struct nfs_writeres *result)
2046{
2047 __be32 *p;
2048
2049 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
2050 if (unlikely(p == NULL))
2051 goto out_overflow;
2052 result->count = be32_to_cpup(p++);
2053 result->verf->committed = be32_to_cpup(p++);
2054 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
2055 goto out_badvalue;
2056 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
2057 return result->count;
2058out_badvalue:
2059 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
2060 return -EIO;
2061out_overflow:
2062 print_overflow_msg(__func__, xdr);
2063 return -EIO;
2064}
2065
2066static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, __be32 *p,
2067 struct nfs_writeres *result)
2068{
2069 struct xdr_stream xdr;
2070 enum nfs_stat status;
2071 int error;
2072
2073 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2074 error = decode_nfsstat3(&xdr, &status);
2075 if (unlikely(error))
2076 goto out;
2077 error = decode_wcc_data(&xdr, result->fattr);
2078 if (unlikely(error))
2079 goto out;
2080 if (status != NFS3_OK)
2081 goto out_status;
2082 error = decode_write3resok(&xdr, result);
2083out:
2084 return error;
2085out_status:
2086 return nfs_stat_to_errno(status);
2087}
2088
2089/*
1454 * Decode a CREATE response 2090 * Decode a CREATE response
1455 */ 2091 */
1456static int 2092static int
@@ -1478,6 +2114,111 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1478} 2114}
1479 2115
1480/* 2116/*
2117 * 3.3.8 CREATE3res
2118 *
2119 * struct CREATE3resok {
2120 * post_op_fh3 obj;
2121 * post_op_attr obj_attributes;
2122 * wcc_data dir_wcc;
2123 * };
2124 *
2125 * struct CREATE3resfail {
2126 * wcc_data dir_wcc;
2127 * };
2128 *
2129 * union CREATE3res switch (nfsstat3 status) {
2130 * case NFS3_OK:
2131 * CREATE3resok resok;
2132 * default:
2133 * CREATE3resfail resfail;
2134 * };
2135 */
2136static int decode_create3resok(struct xdr_stream *xdr,
2137 struct nfs3_diropres *result)
2138{
2139 int error;
2140
2141 error = decode_post_op_fh3(xdr, result->fh);
2142 if (unlikely(error))
2143 goto out;
2144 error = decode_post_op_attr(xdr, result->fattr);
2145 if (unlikely(error))
2146 goto out;
2147 /* The server isn't required to return a file handle.
2148 * If it didn't, force the client to perform a LOOKUP
2149 * to determine the correct file handle and attribute
2150 * values for the new object. */
2151 if (result->fh->size == 0)
2152 result->fattr->valid = 0;
2153 error = decode_wcc_data(xdr, result->dir_attr);
2154out:
2155 return error;
2156}
2157
2158static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, __be32 *p,
2159 struct nfs3_diropres *result)
2160{
2161 struct xdr_stream xdr;
2162 enum nfs_stat status;
2163 int error;
2164
2165 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2166 error = decode_nfsstat3(&xdr, &status);
2167 if (unlikely(error))
2168 goto out;
2169 if (status != NFS3_OK)
2170 goto out_default;
2171 error = decode_create3resok(&xdr, result);
2172out:
2173 return error;
2174out_default:
2175 error = decode_wcc_data(&xdr, result->dir_attr);
2176 if (unlikely(error))
2177 goto out;
2178 return nfs_stat_to_errno(status);
2179}
2180
2181/*
2182 * 3.3.12 REMOVE3res
2183 *
2184 * struct REMOVE3resok {
2185 * wcc_data dir_wcc;
2186 * };
2187 *
2188 * struct REMOVE3resfail {
2189 * wcc_data dir_wcc;
2190 * };
2191 *
2192 * union REMOVE3res switch (nfsstat3 status) {
2193 * case NFS3_OK:
2194 * REMOVE3resok resok;
2195 * default:
2196 * REMOVE3resfail resfail;
2197 * };
2198 */
2199static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, __be32 *p,
2200 struct nfs_removeres *result)
2201{
2202 struct xdr_stream xdr;
2203 enum nfs_stat status;
2204 int error;
2205
2206 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2207 error = decode_nfsstat3(&xdr, &status);
2208 if (unlikely(error))
2209 goto out;
2210 error = decode_wcc_data(&xdr, result->dir_attr);
2211 if (unlikely(error))
2212 goto out;
2213 if (status != NFS3_OK)
2214 goto out_status;
2215out:
2216 return error;
2217out_status:
2218 return nfs_stat_to_errno(status);
2219}
2220
2221/*
1481 * Decode RENAME reply 2222 * Decode RENAME reply
1482 */ 2223 */
1483static int 2224static int
@@ -1493,6 +2234,51 @@ nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
1493} 2234}
1494 2235
1495/* 2236/*
2237 * 3.3.14 RENAME3res
2238 *
2239 * struct RENAME3resok {
2240 * wcc_data fromdir_wcc;
2241 * wcc_data todir_wcc;
2242 * };
2243 *
2244 * struct RENAME3resfail {
2245 * wcc_data fromdir_wcc;
2246 * wcc_data todir_wcc;
2247 * };
2248 *
2249 * union RENAME3res switch (nfsstat3 status) {
2250 * case NFS3_OK:
2251 * RENAME3resok resok;
2252 * default:
2253 * RENAME3resfail resfail;
2254 * };
2255 */
2256static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, __be32 *p,
2257 struct nfs_renameres *result)
2258{
2259 struct xdr_stream xdr;
2260 enum nfs_stat status;
2261 int error;
2262
2263 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2264 error = decode_nfsstat3(&xdr, &status);
2265 if (unlikely(error))
2266 goto out;
2267 error = decode_wcc_data(&xdr, result->old_fattr);
2268 if (unlikely(error))
2269 goto out;
2270 error = decode_wcc_data(&xdr, result->new_fattr);
2271 if (unlikely(error))
2272 goto out;
2273 if (status != NFS3_OK)
2274 goto out_status;
2275out:
2276 return error;
2277out_status:
2278 return nfs_stat_to_errno(status);
2279}
2280
2281/*
1496 * Decode LINK reply 2282 * Decode LINK reply
1497 */ 2283 */
1498static int 2284static int
@@ -1508,6 +2294,249 @@ nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1508} 2294}
1509 2295
1510/* 2296/*
2297 * 3.3.15 LINK3res
2298 *
2299 * struct LINK3resok {
2300 * post_op_attr file_attributes;
2301 * wcc_data linkdir_wcc;
2302 * };
2303 *
2304 * struct LINK3resfail {
2305 * post_op_attr file_attributes;
2306 * wcc_data linkdir_wcc;
2307 * };
2308 *
2309 * union LINK3res switch (nfsstat3 status) {
2310 * case NFS3_OK:
2311 * LINK3resok resok;
2312 * default:
2313 * LINK3resfail resfail;
2314 * };
2315 */
2316static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, __be32 *p,
2317 struct nfs3_linkres *result)
2318{
2319 struct xdr_stream xdr;
2320 enum nfs_stat status;
2321 int error;
2322
2323 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2324 error = decode_nfsstat3(&xdr, &status);
2325 if (unlikely(error))
2326 goto out;
2327 error = decode_post_op_attr(&xdr, result->fattr);
2328 if (unlikely(error))
2329 goto out;
2330 error = decode_wcc_data(&xdr, result->dir_attr);
2331 if (unlikely(error))
2332 goto out;
2333 if (status != NFS3_OK)
2334 goto out_status;
2335out:
2336 return error;
2337out_status:
2338 return nfs_stat_to_errno(status);
2339}
2340
2341/**
2342 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
2343 * the local page cache
2344 * @xdr: XDR stream where entry resides
2345 * @entry: buffer to fill in with entry data
2346 * @server: nfs_server data for this directory
2347 * @plus: boolean indicating whether this should be a readdirplus entry
2348 *
2349 * Returns the position of the next item in the buffer, or an ERR_PTR.
2350 *
2351 * This function is not invoked during READDIR reply decoding, but
2352 * rather whenever an application invokes the getdents(2) system call
2353 * on a directory already in our cache.
2354 *
2355 * 3.3.16 entry3
2356 *
2357 * struct entry3 {
2358 * fileid3 fileid;
2359 * filename3 name;
2360 * cookie3 cookie;
2361 * fhandle3 filehandle;
2362 * post_op_attr3 attributes;
2363 * entry3 *nextentry;
2364 * };
2365 *
2366 * 3.3.17 entryplus3
2367 * struct entryplus3 {
2368 * fileid3 fileid;
2369 * filename3 name;
2370 * cookie3 cookie;
2371 * post_op_attr name_attributes;
2372 * post_op_fh3 name_handle;
2373 * entryplus3 *nextentry;
2374 * };
2375 */
2376__be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2377 struct nfs_server *server, int plus)
2378{
2379 struct nfs_entry old = *entry;
2380 __be32 *p;
2381 int error;
2382
2383 p = xdr_inline_decode(xdr, 4);
2384 if (unlikely(p == NULL))
2385 goto out_overflow;
2386 if (*p == xdr_zero) {
2387 p = xdr_inline_decode(xdr, 4);
2388 if (unlikely(p == NULL))
2389 goto out_overflow;
2390 if (*p == xdr_zero)
2391 return ERR_PTR(-EAGAIN);
2392 entry->eof = 1;
2393 return ERR_PTR(-EBADCOOKIE);
2394 }
2395
2396 error = decode_fileid3(xdr, &entry->ino);
2397 if (unlikely(error))
2398 return ERR_PTR(error);
2399
2400 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2401 if (unlikely(error))
2402 return ERR_PTR(error);
2403
2404 entry->prev_cookie = entry->cookie;
2405 error = decode_cookie3(xdr, &entry->cookie);
2406 if (unlikely(error))
2407 return ERR_PTR(error);
2408
2409 entry->d_type = DT_UNKNOWN;
2410
2411 if (plus) {
2412 entry->fattr->valid = 0;
2413 error = decode_post_op_attr(xdr, entry->fattr);
2414 if (unlikely(error))
2415 return ERR_PTR(error);
2416 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2417 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2418
2419 /* In fact, a post_op_fh3: */
2420 p = xdr_inline_decode(xdr, 4);
2421 if (unlikely(p == NULL))
2422 goto out_overflow;
2423 if (*p != xdr_zero) {
2424 error = decode_nfs_fh3(xdr, entry->fh);
2425 if (unlikely(error)) {
2426 if (error == -E2BIG)
2427 goto out_truncated;
2428 return ERR_PTR(error);
2429 }
2430 } else
2431 zero_nfs_fh3(entry->fh);
2432 }
2433
2434 /* Peek at the next entry to see if we're at EOD */
2435 p = xdr_inline_peek(xdr, 4 + 4);
2436 entry->eof = 0;
2437 if (p != NULL)
2438 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
2439 return p;
2440
2441out_overflow:
2442 print_overflow_msg(__func__, xdr);
2443 return ERR_PTR(-EAGAIN);
2444out_truncated:
2445 dprintk("NFS: directory entry contains invalid file handle\n");
2446 *entry = old;
2447 return ERR_PTR(-EAGAIN);
2448}
2449
2450/*
2451 * 3.3.16 READDIR3res
2452 *
2453 * struct dirlist3 {
2454 * entry3 *entries;
2455 * bool eof;
2456 * };
2457 *
2458 * struct READDIR3resok {
2459 * post_op_attr dir_attributes;
2460 * cookieverf3 cookieverf;
2461 * dirlist3 reply;
2462 * };
2463 *
2464 * struct READDIR3resfail {
2465 * post_op_attr dir_attributes;
2466 * };
2467 *
2468 * union READDIR3res switch (nfsstat3 status) {
2469 * case NFS3_OK:
2470 * READDIR3resok resok;
2471 * default:
2472 * READDIR3resfail resfail;
2473 * };
2474 *
2475 * Read the directory contents into the page cache, but otherwise
2476 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2477 * during subsequent nfs_readdir() calls.
2478 */
2479static int decode_dirlist3(struct xdr_stream *xdr)
2480{
2481 u32 recvd, pglen;
2482 size_t hdrlen;
2483
2484 pglen = xdr->buf->page_len;
2485 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2486 recvd = xdr->buf->len - hdrlen;
2487 if (unlikely(pglen > recvd))
2488 goto out_cheating;
2489out:
2490 xdr_read_pages(xdr, pglen);
2491 return pglen;
2492out_cheating:
2493 dprintk("NFS: server cheating in readdir result: "
2494 "pglen %u > recvd %u\n", pglen, recvd);
2495 pglen = recvd;
2496 goto out;
2497}
2498
2499static int decode_readdir3resok(struct xdr_stream *xdr,
2500 struct nfs3_readdirres *result)
2501{
2502 int error;
2503
2504 error = decode_post_op_attr(xdr, result->dir_attr);
2505 if (unlikely(error))
2506 goto out;
2507 /* XXX: do we need to check if result->verf != NULL ? */
2508 error = decode_cookieverf3(xdr, result->verf);
2509 if (unlikely(error))
2510 goto out;
2511 error = decode_dirlist3(xdr);
2512out:
2513 return error;
2514}
2515
2516static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, __be32 *p,
2517 struct nfs3_readdirres *result)
2518{
2519 struct xdr_stream xdr;
2520 enum nfs_stat status;
2521 int error;
2522
2523 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2524 error = decode_nfsstat3(&xdr, &status);
2525 if (unlikely(error))
2526 goto out;
2527 if (status != NFS3_OK)
2528 goto out_default;
2529 error = decode_readdir3resok(&xdr, result);
2530out:
2531 return error;
2532out_default:
2533 error = decode_post_op_attr(&xdr, result->dir_attr);
2534 if (unlikely(error))
2535 goto out;
2536 return nfs_stat_to_errno(status);
2537}
2538
2539/*
1511 * Decode FSSTAT reply 2540 * Decode FSSTAT reply
1512 */ 2541 */
1513static int 2542static int
@@ -1533,6 +2562,75 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1533} 2562}
1534 2563
1535/* 2564/*
2565 * 3.3.18 FSSTAT3res
2566 *
2567 * struct FSSTAT3resok {
2568 * post_op_attr obj_attributes;
2569 * size3 tbytes;
2570 * size3 fbytes;
2571 * size3 abytes;
2572 * size3 tfiles;
2573 * size3 ffiles;
2574 * size3 afiles;
2575 * uint32 invarsec;
2576 * };
2577 *
2578 * struct FSSTAT3resfail {
2579 * post_op_attr obj_attributes;
2580 * };
2581 *
2582 * union FSSTAT3res switch (nfsstat3 status) {
2583 * case NFS3_OK:
2584 * FSSTAT3resok resok;
2585 * default:
2586 * FSSTAT3resfail resfail;
2587 * };
2588 */
2589static int decode_fsstat3resok(struct xdr_stream *xdr,
2590 struct nfs_fsstat *result)
2591{
2592 __be32 *p;
2593
2594 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2595 if (unlikely(p == NULL))
2596 goto out_overflow;
2597 p = xdr_decode_size3(p, &result->tbytes);
2598 p = xdr_decode_size3(p, &result->fbytes);
2599 p = xdr_decode_size3(p, &result->abytes);
2600 p = xdr_decode_size3(p, &result->tfiles);
2601 p = xdr_decode_size3(p, &result->ffiles);
2602 xdr_decode_size3(p, &result->afiles);
2603 /* ignore invarsec */
2604 return 0;
2605out_overflow:
2606 print_overflow_msg(__func__, xdr);
2607 return -EIO;
2608}
2609
2610static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, __be32 *p,
2611 struct nfs_fsstat *result)
2612{
2613 struct xdr_stream xdr;
2614 enum nfs_stat status;
2615 int error;
2616
2617 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2618 error = decode_nfsstat3(&xdr, &status);
2619 if (unlikely(error))
2620 goto out;
2621 error = decode_post_op_attr(&xdr, result->fattr);
2622 if (unlikely(error))
2623 goto out;
2624 if (status != NFS3_OK)
2625 goto out_status;
2626 error = decode_fsstat3resok(&xdr, result);
2627out:
2628 return error;
2629out_status:
2630 return nfs_stat_to_errno(status);
2631}
2632
2633/*
1536 * Decode FSINFO reply 2634 * Decode FSINFO reply
1537 */ 2635 */
1538static int 2636static int
@@ -1562,6 +2660,83 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1562} 2660}
1563 2661
1564/* 2662/*
2663 * 3.3.19 FSINFO3res
2664 *
2665 * struct FSINFO3resok {
2666 * post_op_attr obj_attributes;
2667 * uint32 rtmax;
2668 * uint32 rtpref;
2669 * uint32 rtmult;
2670 * uint32 wtmax;
2671 * uint32 wtpref;
2672 * uint32 wtmult;
2673 * uint32 dtpref;
2674 * size3 maxfilesize;
2675 * nfstime3 time_delta;
2676 * uint32 properties;
2677 * };
2678 *
2679 * struct FSINFO3resfail {
2680 * post_op_attr obj_attributes;
2681 * };
2682 *
2683 * union FSINFO3res switch (nfsstat3 status) {
2684 * case NFS3_OK:
2685 * FSINFO3resok resok;
2686 * default:
2687 * FSINFO3resfail resfail;
2688 * };
2689 */
2690static int decode_fsinfo3resok(struct xdr_stream *xdr,
2691 struct nfs_fsinfo *result)
2692{
2693 __be32 *p;
2694
2695 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2696 if (unlikely(p == NULL))
2697 goto out_overflow;
2698 result->rtmax = be32_to_cpup(p++);
2699 result->rtpref = be32_to_cpup(p++);
2700 result->rtmult = be32_to_cpup(p++);
2701 result->wtmax = be32_to_cpup(p++);
2702 result->wtpref = be32_to_cpup(p++);
2703 result->wtmult = be32_to_cpup(p++);
2704 result->dtpref = be32_to_cpup(p++);
2705 p = xdr_decode_size3(p, &result->maxfilesize);
2706 xdr_decode_time3(p, &result->time_delta);
2707
2708 /* ignore properties */
2709 result->lease_time = 0;
2710 return 0;
2711out_overflow:
2712 print_overflow_msg(__func__, xdr);
2713 return -EIO;
2714}
2715
2716static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, __be32 *p,
2717 struct nfs_fsinfo *result)
2718{
2719 struct xdr_stream xdr;
2720 enum nfs_stat status;
2721 int error;
2722
2723 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2724 error = decode_nfsstat3(&xdr, &status);
2725 if (unlikely(error))
2726 goto out;
2727 error = decode_post_op_attr(&xdr, result->fattr);
2728 if (unlikely(error))
2729 goto out;
2730 if (status != NFS3_OK)
2731 goto out_status;
2732 error = decode_fsinfo3resok(&xdr, result);
2733out:
2734 return error;
2735out_status:
2736 return nfs_stat_to_errno(status);
2737}
2738
2739/*
1565 * Decode PATHCONF reply 2740 * Decode PATHCONF reply
1566 */ 2741 */
1567static int 2742static int
@@ -1582,6 +2757,70 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1582} 2757}
1583 2758
1584/* 2759/*
2760 * 3.3.20 PATHCONF3res
2761 *
2762 * struct PATHCONF3resok {
2763 * post_op_attr obj_attributes;
2764 * uint32 linkmax;
2765 * uint32 name_max;
2766 * bool no_trunc;
2767 * bool chown_restricted;
2768 * bool case_insensitive;
2769 * bool case_preserving;
2770 * };
2771 *
2772 * struct PATHCONF3resfail {
2773 * post_op_attr obj_attributes;
2774 * };
2775 *
2776 * union PATHCONF3res switch (nfsstat3 status) {
2777 * case NFS3_OK:
2778 * PATHCONF3resok resok;
2779 * default:
2780 * PATHCONF3resfail resfail;
2781 * };
2782 */
2783static int decode_pathconf3resok(struct xdr_stream *xdr,
2784 struct nfs_pathconf *result)
2785{
2786 __be32 *p;
2787
2788 p = xdr_inline_decode(xdr, 4 * 6);
2789 if (unlikely(p == NULL))
2790 goto out_overflow;
2791 result->max_link = be32_to_cpup(p++);
2792 result->max_namelen = be32_to_cpup(p);
2793 /* ignore remaining fields */
2794 return 0;
2795out_overflow:
2796 print_overflow_msg(__func__, xdr);
2797 return -EIO;
2798}
2799
2800static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, __be32 *p,
2801 struct nfs_pathconf *result)
2802{
2803 struct xdr_stream xdr;
2804 enum nfs_stat status;
2805 int error;
2806
2807 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2808 error = decode_nfsstat3(&xdr, &status);
2809 if (unlikely(error))
2810 goto out;
2811 error = decode_post_op_attr(&xdr, result->fattr);
2812 if (unlikely(error))
2813 goto out;
2814 if (status != NFS3_OK)
2815 goto out_status;
2816 error = decode_pathconf3resok(&xdr, result);
2817out:
2818 return error;
2819out_status:
2820 return nfs_stat_to_errno(status);
2821}
2822
2823/*
1585 * Decode COMMIT reply 2824 * Decode COMMIT reply
1586 */ 2825 */
1587static int 2826static int
@@ -1599,6 +2838,48 @@ nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1599 return 0; 2838 return 0;
1600} 2839}
1601 2840
2841/*
2842 * 3.3.21 COMMIT3res
2843 *
2844 * struct COMMIT3resok {
2845 * wcc_data file_wcc;
2846 * writeverf3 verf;
2847 * };
2848 *
2849 * struct COMMIT3resfail {
2850 * wcc_data file_wcc;
2851 * };
2852 *
2853 * union COMMIT3res switch (nfsstat3 status) {
2854 * case NFS3_OK:
2855 * COMMIT3resok resok;
2856 * default:
2857 * COMMIT3resfail resfail;
2858 * };
2859 */
2860static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, __be32 *p,
2861 struct nfs_writeres *result)
2862{
2863 struct xdr_stream xdr;
2864 enum nfs_stat status;
2865 int error;
2866
2867 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2868 error = decode_nfsstat3(&xdr, &status);
2869 if (unlikely(error))
2870 goto out;
2871 error = decode_wcc_data(&xdr, result->fattr);
2872 if (unlikely(error))
2873 goto out;
2874 if (status != NFS3_OK)
2875 goto out_status;
2876 error = decode_writeverf3(&xdr, result->verf->verifier);
2877out:
2878 return error;
2879out_status:
2880 return nfs_stat_to_errno(status);
2881}
2882
1602#ifdef CONFIG_NFS_V3_ACL 2883#ifdef CONFIG_NFS_V3_ACL
1603/* 2884/*
1604 * Decode GETACL reply 2885 * Decode GETACL reply
@@ -1632,6 +2913,70 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1632 return (err > 0) ? 0 : err; 2913 return (err > 0) ? 0 : err;
1633} 2914}
1634 2915
2916static inline int decode_getacl3resok(struct xdr_stream *xdr,
2917 struct nfs3_getaclres *result)
2918{
2919 struct posix_acl **acl;
2920 unsigned int *aclcnt;
2921 size_t hdrlen;
2922 int error;
2923
2924 error = decode_post_op_attr(xdr, result->fattr);
2925 if (unlikely(error))
2926 goto out;
2927 error = decode_uint32(xdr, &result->mask);
2928 if (unlikely(error))
2929 goto out;
2930 error = -EINVAL;
2931 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2932 goto out;
2933
2934 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2935
2936 acl = NULL;
2937 if (result->mask & NFS_ACL)
2938 acl = &result->acl_access;
2939 aclcnt = NULL;
2940 if (result->mask & NFS_ACLCNT)
2941 aclcnt = &result->acl_access_count;
2942 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2943 if (unlikely(error <= 0))
2944 goto out;
2945
2946 acl = NULL;
2947 if (result->mask & NFS_DFACL)
2948 acl = &result->acl_default;
2949 aclcnt = NULL;
2950 if (result->mask & NFS_DFACLCNT)
2951 aclcnt = &result->acl_default_count;
2952 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2953 if (unlikely(error <= 0))
2954 return error;
2955 error = 0;
2956out:
2957 return error;
2958}
2959
2960static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, __be32 *p,
2961 struct nfs3_getaclres *result)
2962{
2963 struct xdr_stream xdr;
2964 enum nfs_stat status;
2965 int error;
2966
2967 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2968 error = decode_nfsstat3(&xdr, &status);
2969 if (unlikely(error))
2970 goto out;
2971 if (status != NFS3_OK)
2972 goto out_default;
2973 error = decode_getacl3resok(&xdr, result);
2974out:
2975 return error;
2976out_default:
2977 return nfs_stat_to_errno(status);
2978}
2979
1635/* 2980/*
1636 * Decode setacl reply. 2981 * Decode setacl reply.
1637 */ 2982 */
@@ -1645,6 +2990,27 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1645 xdr_decode_post_op_attr(p, fattr); 2990 xdr_decode_post_op_attr(p, fattr);
1646 return 0; 2991 return 0;
1647} 2992}
2993
2994static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, __be32 *p,
2995 struct nfs_fattr *result)
2996{
2997 struct xdr_stream xdr;
2998 enum nfs_stat status;
2999 int error;
3000
3001 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
3002 error = decode_nfsstat3(&xdr, &status);
3003 if (unlikely(error))
3004 goto out;
3005 if (status != NFS3_OK)
3006 goto out_default;
3007 error = decode_post_op_attr(&xdr, result);
3008out:
3009 return error;
3010out_default:
3011 return nfs_stat_to_errno(status);
3012}
3013
1648#endif /* CONFIG_NFS_V3_ACL */ 3014#endif /* CONFIG_NFS_V3_ACL */
1649 3015
1650#define PROC(proc, argtype, restype, timer) \ 3016#define PROC(proc, argtype, restype, timer) \