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