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