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