1 /* 2 * linux/fs/nfs/nfs3xdr.c 3 * 4 * XDR functions to encode/decode NFSv3 RPC arguments and results. 5 * 6 * Copyright (C) 1996, 1997 Olaf Kirch 7 */ 8 9 #include <linux/param.h> 10 #include <linux/time.h> 11 #include <linux/mm.h> 12 #include <linux/errno.h> 13 #include <linux/string.h> 14 #include <linux/in.h> 15 #include <linux/pagemap.h> 16 #include <linux/proc_fs.h> 17 #include <linux/kdev_t.h> 18 #include <linux/sunrpc/clnt.h> 19 #include <linux/nfs.h> 20 #include <linux/nfs3.h> 21 #include <linux/nfs_fs.h> 22 #include <linux/nfsacl.h> 23 #include "internal.h" 24 25 #define NFSDBG_FACILITY NFSDBG_XDR 26 27 /* Mapping from NFS error code to "errno" error code. */ 28 #define errno_NFSERR_IO EIO 29 30 /* 31 * Declare the space requirements for NFS arguments and replies as 32 * number of 32bit-words 33 */ 34 #define NFS3_fhandle_sz (1+16) 35 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ 36 #define NFS3_sattr_sz (15) 37 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) 38 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) 39 #define NFS3_fattr_sz (21) 40 #define NFS3_wcc_attr_sz (6) 41 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) 42 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) 43 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz) 44 #define NFS3_fsstat_sz 45 #define NFS3_fsinfo_sz 46 #define NFS3_pathconf_sz 47 #define NFS3_entry_sz (NFS3_filename_sz+3) 48 49 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) 50 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) 51 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz) 52 #define NFS3_accessargs_sz (NFS3_fh_sz+1) 53 #define NFS3_readlinkargs_sz (NFS3_fh_sz) 54 #define NFS3_readargs_sz (NFS3_fh_sz+3) 55 #define NFS3_writeargs_sz (NFS3_fh_sz+5) 56 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) 57 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) 58 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) 59 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) 60 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) 61 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) 62 #define NFS3_readdirargs_sz (NFS3_fh_sz+2) 63 #define NFS3_commitargs_sz (NFS3_fh_sz+3) 64 65 #define NFS3_attrstat_sz (1+NFS3_fattr_sz) 66 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz) 67 #define NFS3_removeres_sz (NFS3_wccstat_sz) 68 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) 69 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) 70 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) 71 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) 72 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) 73 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) 74 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) 75 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) 76 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) 77 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) 78 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) 79 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) 80 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) 81 82 #define ACL3_getaclargs_sz (NFS3_fh_sz+1) 83 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \ 84 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) 85 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \ 86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE)) 87 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) 88 89 /* 90 * Map file type to S_IFMT bits 91 */ 92 static const umode_t nfs_type2fmt[] = { 93 [NF3BAD] = 0, 94 [NF3REG] = S_IFREG, 95 [NF3DIR] = S_IFDIR, 96 [NF3BLK] = S_IFBLK, 97 [NF3CHR] = S_IFCHR, 98 [NF3LNK] = S_IFLNK, 99 [NF3SOCK] = S_IFSOCK, 100 [NF3FIFO] = S_IFIFO, 101 }; 102 103 /* 104 * Common NFS XDR functions as inlines 105 */ 106 static inline __be32 * 107 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh) 108 { 109 return xdr_encode_array(p, fh->data, fh->size); 110 } 111 112 static inline __be32 * 113 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh) 114 { 115 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { 116 memcpy(fh->data, p, fh->size); 117 return p + XDR_QUADLEN(fh->size); 118 } 119 return NULL; 120 } 121 122 /* 123 * Encode/decode time. 124 */ 125 static inline __be32 * 126 xdr_encode_time3(__be32 *p, struct timespec *timep) 127 { 128 *p++ = htonl(timep->tv_sec); 129 *p++ = htonl(timep->tv_nsec); 130 return p; 131 } 132 133 static inline __be32 * 134 xdr_decode_time3(__be32 *p, struct timespec *timep) 135 { 136 timep->tv_sec = ntohl(*p++); 137 timep->tv_nsec = ntohl(*p++); 138 return p; 139 } 140 141 static __be32 * 142 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) 143 { 144 unsigned int type, major, minor; 145 umode_t fmode; 146 147 type = ntohl(*p++); 148 if (type > NF3FIFO) 149 type = NF3NON; 150 fmode = nfs_type2fmt[type]; 151 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; 152 fattr->nlink = ntohl(*p++); 153 fattr->uid = ntohl(*p++); 154 fattr->gid = ntohl(*p++); 155 p = xdr_decode_hyper(p, &fattr->size); 156 p = xdr_decode_hyper(p, &fattr->du.nfs3.used); 157 158 /* Turn remote device info into Linux-specific dev_t */ 159 major = ntohl(*p++); 160 minor = ntohl(*p++); 161 fattr->rdev = MKDEV(major, minor); 162 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor) 163 fattr->rdev = 0; 164 165 p = xdr_decode_hyper(p, &fattr->fsid.major); 166 fattr->fsid.minor = 0; 167 p = xdr_decode_hyper(p, &fattr->fileid); 168 p = xdr_decode_time3(p, &fattr->atime); 169 p = xdr_decode_time3(p, &fattr->mtime); 170 p = xdr_decode_time3(p, &fattr->ctime); 171 172 /* Update the mode bits */ 173 fattr->valid |= NFS_ATTR_FATTR_V3; 174 return p; 175 } 176 177 static inline __be32 * 178 xdr_encode_sattr(__be32 *p, struct iattr *attr) 179 { 180 if (attr->ia_valid & ATTR_MODE) { 181 *p++ = xdr_one; 182 *p++ = htonl(attr->ia_mode & S_IALLUGO); 183 } else { 184 *p++ = xdr_zero; 185 } 186 if (attr->ia_valid & ATTR_UID) { 187 *p++ = xdr_one; 188 *p++ = htonl(attr->ia_uid); 189 } else { 190 *p++ = xdr_zero; 191 } 192 if (attr->ia_valid & ATTR_GID) { 193 *p++ = xdr_one; 194 *p++ = htonl(attr->ia_gid); 195 } else { 196 *p++ = xdr_zero; 197 } 198 if (attr->ia_valid & ATTR_SIZE) { 199 *p++ = xdr_one; 200 p = xdr_encode_hyper(p, (__u64) attr->ia_size); 201 } else { 202 *p++ = xdr_zero; 203 } 204 if (attr->ia_valid & ATTR_ATIME_SET) { 205 *p++ = xdr_two; 206 p = xdr_encode_time3(p, &attr->ia_atime); 207 } else if (attr->ia_valid & ATTR_ATIME) { 208 *p++ = xdr_one; 209 } else { 210 *p++ = xdr_zero; 211 } 212 if (attr->ia_valid & ATTR_MTIME_SET) { 213 *p++ = xdr_two; 214 p = xdr_encode_time3(p, &attr->ia_mtime); 215 } else if (attr->ia_valid & ATTR_MTIME) { 216 *p++ = xdr_one; 217 } else { 218 *p++ = xdr_zero; 219 } 220 return p; 221 } 222 223 static inline __be32 * 224 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr) 225 { 226 p = xdr_decode_hyper(p, &fattr->pre_size); 227 p = xdr_decode_time3(p, &fattr->pre_mtime); 228 p = xdr_decode_time3(p, &fattr->pre_ctime); 229 fattr->valid |= NFS_ATTR_FATTR_PRESIZE 230 | NFS_ATTR_FATTR_PREMTIME 231 | NFS_ATTR_FATTR_PRECTIME; 232 return p; 233 } 234 235 static inline __be32 * 236 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr) 237 { 238 if (*p++) 239 p = xdr_decode_fattr(p, fattr); 240 return p; 241 } 242 243 static inline __be32 * 244 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr) 245 { 246 if (*p++) 247 return xdr_decode_wcc_attr(p, fattr); 248 return p; 249 } 250 251 252 static inline __be32 * 253 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr) 254 { 255 p = xdr_decode_pre_op_attr(p, fattr); 256 return xdr_decode_post_op_attr(p, fattr); 257 } 258 259 /* 260 * NFS encode functions 261 */ 262 263 /* 264 * Encode file handle argument 265 */ 266 static int 267 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) 268 { 269 p = xdr_encode_fhandle(p, fh); 270 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 271 return 0; 272 } 273 274 /* 275 * Encode SETATTR arguments 276 */ 277 static int 278 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) 279 { 280 p = xdr_encode_fhandle(p, args->fh); 281 p = xdr_encode_sattr(p, args->sattr); 282 *p++ = htonl(args->guard); 283 if (args->guard) 284 p = xdr_encode_time3(p, &args->guardtime); 285 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 286 return 0; 287 } 288 289 /* 290 * Encode directory ops argument 291 */ 292 static int 293 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args) 294 { 295 p = xdr_encode_fhandle(p, args->fh); 296 p = xdr_encode_array(p, args->name, args->len); 297 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 298 return 0; 299 } 300 301 /* 302 * Encode REMOVE argument 303 */ 304 static int 305 nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args) 306 { 307 p = xdr_encode_fhandle(p, args->fh); 308 p = xdr_encode_array(p, args->name.name, args->name.len); 309 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 310 return 0; 311 } 312 313 /* 314 * Encode access() argument 315 */ 316 static int 317 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args) 318 { 319 p = xdr_encode_fhandle(p, args->fh); 320 *p++ = htonl(args->access); 321 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 322 return 0; 323 } 324 325 /* 326 * Arguments to a READ call. Since we read data directly into the page 327 * cache, we also set up the reply iovec here so that iov[1] points 328 * exactly to the page we want to fetch. 329 */ 330 static int 331 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 332 { 333 struct rpc_auth *auth = req->rq_cred->cr_auth; 334 unsigned int replen; 335 u32 count = args->count; 336 337 p = xdr_encode_fhandle(p, args->fh); 338 p = xdr_encode_hyper(p, args->offset); 339 *p++ = htonl(count); 340 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 341 342 /* Inline the page array */ 343 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; 344 xdr_inline_pages(&req->rq_rcv_buf, replen, 345 args->pages, args->pgbase, count); 346 req->rq_rcv_buf.flags |= XDRBUF_READ; 347 return 0; 348 } 349 350 /* 351 * Write arguments. Splice the buffer to be written into the iovec. 352 */ 353 static int 354 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 355 { 356 struct xdr_buf *sndbuf = &req->rq_snd_buf; 357 u32 count = args->count; 358 359 p = xdr_encode_fhandle(p, args->fh); 360 p = xdr_encode_hyper(p, args->offset); 361 *p++ = htonl(count); 362 *p++ = htonl(args->stable); 363 *p++ = htonl(count); 364 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 365 366 /* Copy the page array */ 367 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 368 sndbuf->flags |= XDRBUF_WRITE; 369 return 0; 370 } 371 372 /* 373 * Encode CREATE arguments 374 */ 375 static int 376 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) 377 { 378 p = xdr_encode_fhandle(p, args->fh); 379 p = xdr_encode_array(p, args->name, args->len); 380 381 *p++ = htonl(args->createmode); 382 if (args->createmode == NFS3_CREATE_EXCLUSIVE) { 383 *p++ = args->verifier[0]; 384 *p++ = args->verifier[1]; 385 } else 386 p = xdr_encode_sattr(p, args->sattr); 387 388 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 389 return 0; 390 } 391 392 /* 393 * Encode MKDIR arguments 394 */ 395 static int 396 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) 397 { 398 p = xdr_encode_fhandle(p, args->fh); 399 p = xdr_encode_array(p, args->name, args->len); 400 p = xdr_encode_sattr(p, args->sattr); 401 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 402 return 0; 403 } 404 405 /* 406 * Encode SYMLINK arguments 407 */ 408 static int 409 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) 410 { 411 p = xdr_encode_fhandle(p, args->fromfh); 412 p = xdr_encode_array(p, args->fromname, args->fromlen); 413 p = xdr_encode_sattr(p, args->sattr); 414 *p++ = htonl(args->pathlen); 415 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 416 417 /* Copy the page */ 418 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); 419 return 0; 420 } 421 422 /* 423 * Encode MKNOD arguments 424 */ 425 static int 426 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) 427 { 428 p = xdr_encode_fhandle(p, args->fh); 429 p = xdr_encode_array(p, args->name, args->len); 430 *p++ = htonl(args->type); 431 p = xdr_encode_sattr(p, args->sattr); 432 if (args->type == NF3CHR || args->type == NF3BLK) { 433 *p++ = htonl(MAJOR(args->rdev)); 434 *p++ = htonl(MINOR(args->rdev)); 435 } 436 437 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 438 return 0; 439 } 440 441 /* 442 * Encode RENAME arguments 443 */ 444 static int 445 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args) 446 { 447 p = xdr_encode_fhandle(p, args->fromfh); 448 p = xdr_encode_array(p, args->fromname, args->fromlen); 449 p = xdr_encode_fhandle(p, args->tofh); 450 p = xdr_encode_array(p, args->toname, args->tolen); 451 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 452 return 0; 453 } 454 455 /* 456 * Encode LINK arguments 457 */ 458 static int 459 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) 460 { 461 p = xdr_encode_fhandle(p, args->fromfh); 462 p = xdr_encode_fhandle(p, args->tofh); 463 p = xdr_encode_array(p, args->toname, args->tolen); 464 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 465 return 0; 466 } 467 468 /* 469 * Encode arguments to readdir call 470 */ 471 static int 472 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) 473 { 474 struct rpc_auth *auth = req->rq_cred->cr_auth; 475 unsigned int replen; 476 u32 count = args->count; 477 478 p = xdr_encode_fhandle(p, args->fh); 479 p = xdr_encode_hyper(p, args->cookie); 480 *p++ = args->verf[0]; 481 *p++ = args->verf[1]; 482 if (args->plus) { 483 /* readdirplus: need dircount + buffer size. 484 * We just make sure we make dircount big enough */ 485 *p++ = htonl(count >> 3); 486 } 487 *p++ = htonl(count); 488 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 489 490 /* Inline the page array */ 491 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2; 492 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count); 493 return 0; 494 } 495 496 /* 497 * Decode the result of a readdir call. 498 * We just check for syntactical correctness. 499 */ 500 static int 501 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res) 502 { 503 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 504 struct kvec *iov = rcvbuf->head; 505 struct page **page; 506 size_t hdrlen; 507 u32 len, recvd, pglen; 508 int status, nr = 0; 509 __be32 *entry, *end, *kaddr; 510 511 status = ntohl(*p++); 512 /* Decode post_op_attrs */ 513 p = xdr_decode_post_op_attr(p, res->dir_attr); 514 if (status) 515 return nfs_stat_to_errno(status); 516 /* Decode verifier cookie */ 517 if (res->verf) { 518 res->verf[0] = *p++; 519 res->verf[1] = *p++; 520 } else { 521 p += 2; 522 } 523 524 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 525 if (iov->iov_len < hdrlen) { 526 dprintk("NFS: READDIR reply header overflowed:" 527 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 528 return -errno_NFSERR_IO; 529 } else if (iov->iov_len != hdrlen) { 530 dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); 531 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 532 } 533 534 pglen = rcvbuf->page_len; 535 recvd = rcvbuf->len - hdrlen; 536 if (pglen > recvd) 537 pglen = recvd; 538 page = rcvbuf->pages; 539 kaddr = p = kmap_atomic(*page, KM_USER0); 540 end = (__be32 *)((char *)p + pglen); 541 entry = p; 542 543 /* Make sure the packet actually has a value_follows and EOF entry */ 544 if ((entry + 1) > end) 545 goto short_pkt; 546 547 for (; *p++; nr++) { 548 if (p + 3 > end) 549 goto short_pkt; 550 p += 2; /* inode # */ 551 len = ntohl(*p++); /* string length */ 552 p += XDR_QUADLEN(len) + 2; /* name + cookie */ 553 if (len > NFS3_MAXNAMLEN) { 554 dprintk("NFS: giant filename in readdir (len 0x%x)!\n", 555 len); 556 goto err_unmap; 557 } 558 559 if (res->plus) { 560 /* post_op_attr */ 561 if (p + 2 > end) 562 goto short_pkt; 563 if (*p++) { 564 p += 21; 565 if (p + 1 > end) 566 goto short_pkt; 567 } 568 /* post_op_fh3 */ 569 if (*p++) { 570 if (p + 1 > end) 571 goto short_pkt; 572 len = ntohl(*p++); 573 if (len > NFS3_FHSIZE) { 574 dprintk("NFS: giant filehandle in " 575 "readdir (len 0x%x)!\n", len); 576 goto err_unmap; 577 } 578 p += XDR_QUADLEN(len); 579 } 580 } 581 582 if (p + 2 > end) 583 goto short_pkt; 584 entry = p; 585 } 586 587 /* 588 * Apparently some server sends responses that are a valid size, but 589 * contain no entries, and have value_follows==0 and EOF==0. For 590 * those, just set the EOF marker. 591 */ 592 if (!nr && entry[1] == 0) { 593 dprintk("NFS: readdir reply truncated!\n"); 594 entry[1] = 1; 595 } 596 out: 597 kunmap_atomic(kaddr, KM_USER0); 598 return nr; 599 short_pkt: 600 /* 601 * When we get a short packet there are 2 possibilities. We can 602 * return an error, or fix up the response to look like a valid 603 * response and return what we have so far. If there are no 604 * entries and the packet was short, then return -EIO. If there 605 * are valid entries in the response, return them and pretend that 606 * the call was successful, but incomplete. The caller can retry the 607 * readdir starting at the last cookie. 608 */ 609 entry[0] = entry[1] = 0; 610 if (!nr) 611 nr = -errno_NFSERR_IO; 612 goto out; 613 err_unmap: 614 nr = -errno_NFSERR_IO; 615 goto out; 616 } 617 618 __be32 * 619 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 620 { 621 struct nfs_entry old = *entry; 622 623 if (!*p++) { 624 if (!*p) 625 return ERR_PTR(-EAGAIN); 626 entry->eof = 1; 627 return ERR_PTR(-EBADCOOKIE); 628 } 629 630 p = xdr_decode_hyper(p, &entry->ino); 631 entry->len = ntohl(*p++); 632 entry->name = (const char *) p; 633 p += XDR_QUADLEN(entry->len); 634 entry->prev_cookie = entry->cookie; 635 p = xdr_decode_hyper(p, &entry->cookie); 636 637 if (plus) { 638 entry->fattr->valid = 0; 639 p = xdr_decode_post_op_attr(p, entry->fattr); 640 /* In fact, a post_op_fh3: */ 641 if (*p++) { 642 p = xdr_decode_fhandle(p, entry->fh); 643 /* Ugh -- server reply was truncated */ 644 if (p == NULL) { 645 dprintk("NFS: FH truncated\n"); 646 *entry = old; 647 return ERR_PTR(-EAGAIN); 648 } 649 } else 650 memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); 651 } 652 653 entry->eof = !p[0] && p[1]; 654 return p; 655 } 656 657 /* 658 * Encode COMMIT arguments 659 */ 660 static int 661 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 662 { 663 p = xdr_encode_fhandle(p, args->fh); 664 p = xdr_encode_hyper(p, args->offset); 665 *p++ = htonl(args->count); 666 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 667 return 0; 668 } 669 670 #ifdef CONFIG_NFS_V3_ACL 671 /* 672 * Encode GETACL arguments 673 */ 674 static int 675 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, 676 struct nfs3_getaclargs *args) 677 { 678 struct rpc_auth *auth = req->rq_cred->cr_auth; 679 unsigned int replen; 680 681 p = xdr_encode_fhandle(p, args->fh); 682 *p++ = htonl(args->mask); 683 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 684 685 if (args->mask & (NFS_ACL | NFS_DFACL)) { 686 /* Inline the page array */ 687 replen = (RPC_REPHDRSIZE + auth->au_rslack + 688 ACL3_getaclres_sz) << 2; 689 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, 690 NFSACL_MAXPAGES << PAGE_SHIFT); 691 } 692 return 0; 693 } 694 695 /* 696 * Encode SETACL arguments 697 */ 698 static int 699 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, 700 struct nfs3_setaclargs *args) 701 { 702 struct xdr_buf *buf = &req->rq_snd_buf; 703 unsigned int base; 704 int err; 705 706 p = xdr_encode_fhandle(p, NFS_FH(args->inode)); 707 *p++ = htonl(args->mask); 708 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 709 base = req->rq_slen; 710 711 if (args->npages != 0) 712 xdr_encode_pages(buf, args->pages, 0, args->len); 713 else 714 req->rq_slen = xdr_adjust_iovec(req->rq_svec, 715 p + XDR_QUADLEN(args->len)); 716 717 err = nfsacl_encode(buf, base, args->inode, 718 (args->mask & NFS_ACL) ? 719 args->acl_access : NULL, 1, 0); 720 if (err > 0) 721 err = nfsacl_encode(buf, base + err, args->inode, 722 (args->mask & NFS_DFACL) ? 723 args->acl_default : NULL, 1, 724 NFS_ACL_DEFAULT); 725 return (err > 0) ? 0 : err; 726 } 727 #endif /* CONFIG_NFS_V3_ACL */ 728 729 /* 730 * NFS XDR decode functions 731 */ 732 733 /* 734 * Decode attrstat reply. 735 */ 736 static int 737 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 738 { 739 int status; 740 741 if ((status = ntohl(*p++))) 742 return nfs_stat_to_errno(status); 743 xdr_decode_fattr(p, fattr); 744 return 0; 745 } 746 747 /* 748 * Decode status+wcc_data reply 749 * SATTR, REMOVE, RMDIR 750 */ 751 static int 752 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 753 { 754 int status; 755 756 if ((status = ntohl(*p++))) 757 status = nfs_stat_to_errno(status); 758 xdr_decode_wcc_data(p, fattr); 759 return status; 760 } 761 762 static int 763 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) 764 { 765 return nfs3_xdr_wccstat(req, p, res->dir_attr); 766 } 767 768 /* 769 * Decode LOOKUP reply 770 */ 771 static int 772 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 773 { 774 int status; 775 776 if ((status = ntohl(*p++))) { 777 status = nfs_stat_to_errno(status); 778 } else { 779 if (!(p = xdr_decode_fhandle(p, res->fh))) 780 return -errno_NFSERR_IO; 781 p = xdr_decode_post_op_attr(p, res->fattr); 782 } 783 xdr_decode_post_op_attr(p, res->dir_attr); 784 return status; 785 } 786 787 /* 788 * Decode ACCESS reply 789 */ 790 static int 791 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) 792 { 793 int status = ntohl(*p++); 794 795 p = xdr_decode_post_op_attr(p, res->fattr); 796 if (status) 797 return nfs_stat_to_errno(status); 798 res->access = ntohl(*p++); 799 return 0; 800 } 801 802 static int 803 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) 804 { 805 struct rpc_auth *auth = req->rq_cred->cr_auth; 806 unsigned int replen; 807 808 p = xdr_encode_fhandle(p, args->fh); 809 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 810 811 /* Inline the page array */ 812 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2; 813 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 814 return 0; 815 } 816 817 /* 818 * Decode READLINK reply 819 */ 820 static int 821 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 822 { 823 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 824 struct kvec *iov = rcvbuf->head; 825 size_t hdrlen; 826 u32 len, recvd; 827 char *kaddr; 828 int status; 829 830 status = ntohl(*p++); 831 p = xdr_decode_post_op_attr(p, fattr); 832 833 if (status != 0) 834 return nfs_stat_to_errno(status); 835 836 /* Convert length of symlink */ 837 len = ntohl(*p++); 838 if (len >= rcvbuf->page_len) { 839 dprintk("nfs: server returned giant symlink!\n"); 840 return -ENAMETOOLONG; 841 } 842 843 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 844 if (iov->iov_len < hdrlen) { 845 dprintk("NFS: READLINK reply header overflowed:" 846 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 847 return -errno_NFSERR_IO; 848 } else if (iov->iov_len != hdrlen) { 849 dprintk("NFS: READLINK header is short. " 850 "iovec will be shifted.\n"); 851 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 852 } 853 recvd = req->rq_rcv_buf.len - hdrlen; 854 if (recvd < len) { 855 dprintk("NFS: server cheating in readlink reply: " 856 "count %u > recvd %u\n", len, recvd); 857 return -EIO; 858 } 859 860 /* NULL terminate the string we got */ 861 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0); 862 kaddr[len+rcvbuf->page_base] = '\0'; 863 kunmap_atomic(kaddr, KM_USER0); 864 return 0; 865 } 866 867 /* 868 * Decode READ reply 869 */ 870 static int 871 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 872 { 873 struct kvec *iov = req->rq_rcv_buf.head; 874 size_t hdrlen; 875 u32 count, ocount, recvd; 876 int status; 877 878 status = ntohl(*p++); 879 p = xdr_decode_post_op_attr(p, res->fattr); 880 881 if (status != 0) 882 return nfs_stat_to_errno(status); 883 884 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant 885 * in that it puts the count both in the res struct and in the 886 * opaque data count. */ 887 count = ntohl(*p++); 888 res->eof = ntohl(*p++); 889 ocount = ntohl(*p++); 890 891 if (ocount != count) { 892 dprintk("NFS: READ count doesn't match RPC opaque count.\n"); 893 return -errno_NFSERR_IO; 894 } 895 896 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 897 if (iov->iov_len < hdrlen) { 898 dprintk("NFS: READ reply header overflowed:" 899 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 900 return -errno_NFSERR_IO; 901 } else if (iov->iov_len != hdrlen) { 902 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 903 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 904 } 905 906 recvd = req->rq_rcv_buf.len - hdrlen; 907 if (count > recvd) { 908 dprintk("NFS: server cheating in read reply: " 909 "count %u > recvd %u\n", count, recvd); 910 count = recvd; 911 res->eof = 0; 912 } 913 914 if (count < res->count) 915 res->count = count; 916 917 return count; 918 } 919 920 /* 921 * Decode WRITE response 922 */ 923 static int 924 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 925 { 926 int status; 927 928 status = ntohl(*p++); 929 p = xdr_decode_wcc_data(p, res->fattr); 930 931 if (status != 0) 932 return nfs_stat_to_errno(status); 933 934 res->count = ntohl(*p++); 935 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); 936 res->verf->verifier[0] = *p++; 937 res->verf->verifier[1] = *p++; 938 939 return res->count; 940 } 941 942 /* 943 * Decode a CREATE response 944 */ 945 static int 946 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 947 { 948 int status; 949 950 status = ntohl(*p++); 951 if (status == 0) { 952 if (*p++) { 953 if (!(p = xdr_decode_fhandle(p, res->fh))) 954 return -errno_NFSERR_IO; 955 p = xdr_decode_post_op_attr(p, res->fattr); 956 } else { 957 memset(res->fh, 0, sizeof(*res->fh)); 958 /* Do decode post_op_attr but set it to NULL */ 959 p = xdr_decode_post_op_attr(p, res->fattr); 960 res->fattr->valid = 0; 961 } 962 } else { 963 status = nfs_stat_to_errno(status); 964 } 965 p = xdr_decode_wcc_data(p, res->dir_attr); 966 return status; 967 } 968 969 /* 970 * Decode RENAME reply 971 */ 972 static int 973 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res) 974 { 975 int status; 976 977 if ((status = ntohl(*p++)) != 0) 978 status = nfs_stat_to_errno(status); 979 p = xdr_decode_wcc_data(p, res->fromattr); 980 p = xdr_decode_wcc_data(p, res->toattr); 981 return status; 982 } 983 984 /* 985 * Decode LINK reply 986 */ 987 static int 988 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res) 989 { 990 int status; 991 992 if ((status = ntohl(*p++)) != 0) 993 status = nfs_stat_to_errno(status); 994 p = xdr_decode_post_op_attr(p, res->fattr); 995 p = xdr_decode_wcc_data(p, res->dir_attr); 996 return status; 997 } 998 999 /* 1000 * Decode FSSTAT reply 1001 */ 1002 static int 1003 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) 1004 { 1005 int status; 1006 1007 status = ntohl(*p++); 1008 1009 p = xdr_decode_post_op_attr(p, res->fattr); 1010 if (status != 0) 1011 return nfs_stat_to_errno(status); 1012 1013 p = xdr_decode_hyper(p, &res->tbytes); 1014 p = xdr_decode_hyper(p, &res->fbytes); 1015 p = xdr_decode_hyper(p, &res->abytes); 1016 p = xdr_decode_hyper(p, &res->tfiles); 1017 p = xdr_decode_hyper(p, &res->ffiles); 1018 p = xdr_decode_hyper(p, &res->afiles); 1019 1020 /* ignore invarsec */ 1021 return 0; 1022 } 1023 1024 /* 1025 * Decode FSINFO reply 1026 */ 1027 static int 1028 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) 1029 { 1030 int status; 1031 1032 status = ntohl(*p++); 1033 1034 p = xdr_decode_post_op_attr(p, res->fattr); 1035 if (status != 0) 1036 return nfs_stat_to_errno(status); 1037 1038 res->rtmax = ntohl(*p++); 1039 res->rtpref = ntohl(*p++); 1040 res->rtmult = ntohl(*p++); 1041 res->wtmax = ntohl(*p++); 1042 res->wtpref = ntohl(*p++); 1043 res->wtmult = ntohl(*p++); 1044 res->dtpref = ntohl(*p++); 1045 p = xdr_decode_hyper(p, &res->maxfilesize); 1046 1047 /* ignore time_delta and properties */ 1048 res->lease_time = 0; 1049 return 0; 1050 } 1051 1052 /* 1053 * Decode PATHCONF reply 1054 */ 1055 static int 1056 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) 1057 { 1058 int status; 1059 1060 status = ntohl(*p++); 1061 1062 p = xdr_decode_post_op_attr(p, res->fattr); 1063 if (status != 0) 1064 return nfs_stat_to_errno(status); 1065 res->max_link = ntohl(*p++); 1066 res->max_namelen = ntohl(*p++); 1067 1068 /* ignore remaining fields */ 1069 return 0; 1070 } 1071 1072 /* 1073 * Decode COMMIT reply 1074 */ 1075 static int 1076 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 1077 { 1078 int status; 1079 1080 status = ntohl(*p++); 1081 p = xdr_decode_wcc_data(p, res->fattr); 1082 if (status != 0) 1083 return nfs_stat_to_errno(status); 1084 1085 res->verf->verifier[0] = *p++; 1086 res->verf->verifier[1] = *p++; 1087 return 0; 1088 } 1089 1090 #ifdef CONFIG_NFS_V3_ACL 1091 /* 1092 * Decode GETACL reply 1093 */ 1094 static int 1095 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p, 1096 struct nfs3_getaclres *res) 1097 { 1098 struct xdr_buf *buf = &req->rq_rcv_buf; 1099 int status = ntohl(*p++); 1100 struct posix_acl **acl; 1101 unsigned int *aclcnt; 1102 int err, base; 1103 1104 if (status != 0) 1105 return nfs_stat_to_errno(status); 1106 p = xdr_decode_post_op_attr(p, res->fattr); 1107 res->mask = ntohl(*p++); 1108 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 1109 return -EINVAL; 1110 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; 1111 1112 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; 1113 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; 1114 err = nfsacl_decode(buf, base, aclcnt, acl); 1115 1116 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; 1117 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; 1118 if (err > 0) 1119 err = nfsacl_decode(buf, base + err, aclcnt, acl); 1120 return (err > 0) ? 0 : err; 1121 } 1122 1123 /* 1124 * Decode setacl reply. 1125 */ 1126 static int 1127 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1128 { 1129 int status = ntohl(*p++); 1130 1131 if (status) 1132 return nfs_stat_to_errno(status); 1133 xdr_decode_post_op_attr(p, fattr); 1134 return 0; 1135 } 1136 #endif /* CONFIG_NFS_V3_ACL */ 1137 1138 #define PROC(proc, argtype, restype, timer) \ 1139 [NFS3PROC_##proc] = { \ 1140 .p_proc = NFS3PROC_##proc, \ 1141 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \ 1142 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \ 1143 .p_arglen = NFS3_##argtype##_sz, \ 1144 .p_replen = NFS3_##restype##_sz, \ 1145 .p_timer = timer, \ 1146 .p_statidx = NFS3PROC_##proc, \ 1147 .p_name = #proc, \ 1148 } 1149 1150 struct rpc_procinfo nfs3_procedures[] = { 1151 PROC(GETATTR, fhandle, attrstat, 1), 1152 PROC(SETATTR, sattrargs, wccstat, 0), 1153 PROC(LOOKUP, diropargs, lookupres, 2), 1154 PROC(ACCESS, accessargs, accessres, 1), 1155 PROC(READLINK, readlinkargs, readlinkres, 3), 1156 PROC(READ, readargs, readres, 3), 1157 PROC(WRITE, writeargs, writeres, 4), 1158 PROC(CREATE, createargs, createres, 0), 1159 PROC(MKDIR, mkdirargs, createres, 0), 1160 PROC(SYMLINK, symlinkargs, createres, 0), 1161 PROC(MKNOD, mknodargs, createres, 0), 1162 PROC(REMOVE, removeargs, removeres, 0), 1163 PROC(RMDIR, diropargs, wccstat, 0), 1164 PROC(RENAME, renameargs, renameres, 0), 1165 PROC(LINK, linkargs, linkres, 0), 1166 PROC(READDIR, readdirargs, readdirres, 3), 1167 PROC(READDIRPLUS, readdirargs, readdirres, 3), 1168 PROC(FSSTAT, fhandle, fsstatres, 0), 1169 PROC(FSINFO, fhandle, fsinfores, 0), 1170 PROC(PATHCONF, fhandle, pathconfres, 0), 1171 PROC(COMMIT, commitargs, commitres, 5), 1172 }; 1173 1174 struct rpc_version nfs_version3 = { 1175 .number = 3, 1176 .nrprocs = ARRAY_SIZE(nfs3_procedures), 1177 .procs = nfs3_procedures 1178 }; 1179 1180 #ifdef CONFIG_NFS_V3_ACL 1181 static struct rpc_procinfo nfs3_acl_procedures[] = { 1182 [ACLPROC3_GETACL] = { 1183 .p_proc = ACLPROC3_GETACL, 1184 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, 1185 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, 1186 .p_arglen = ACL3_getaclargs_sz, 1187 .p_replen = ACL3_getaclres_sz, 1188 .p_timer = 1, 1189 .p_name = "GETACL", 1190 }, 1191 [ACLPROC3_SETACL] = { 1192 .p_proc = ACLPROC3_SETACL, 1193 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, 1194 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, 1195 .p_arglen = ACL3_setaclargs_sz, 1196 .p_replen = ACL3_setaclres_sz, 1197 .p_timer = 0, 1198 .p_name = "SETACL", 1199 }, 1200 }; 1201 1202 struct rpc_version nfsacl_version3 = { 1203 .number = 3, 1204 .nrprocs = sizeof(nfs3_acl_procedures)/ 1205 sizeof(nfs3_acl_procedures[0]), 1206 .procs = nfs3_acl_procedures, 1207 }; 1208 #endif /* CONFIG_NFS_V3_ACL */ 1209