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