1 /* 2 * Server-side XDR for NFSv4 3 * 4 * Copyright (c) 2002 The Regents of the University of Michigan. 5 * All rights reserved. 6 * 7 * Kendrick Smith <kmsmith@umich.edu> 8 * Andy Adamson <andros@umich.edu> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * TODO: Neil Brown made the following observation: We currently 36 * initially reserve NFSD_BUFSIZE space on the transmit queue and 37 * never release any of that until the request is complete. 38 * It would be good to calculate a new maximum response size while 39 * decoding the COMPOUND, and call svc_reserve with this number 40 * at the end of nfs4svc_decode_compoundargs. 41 */ 42 43 #include <linux/param.h> 44 #include <linux/smp.h> 45 #include <linux/fs.h> 46 #include <linux/namei.h> 47 #include <linux/vfs.h> 48 #include <linux/sunrpc/xdr.h> 49 #include <linux/sunrpc/svc.h> 50 #include <linux/sunrpc/clnt.h> 51 #include <linux/nfsd/nfsd.h> 52 #include <linux/nfsd/state.h> 53 #include <linux/nfsd/xdr4.h> 54 #include <linux/nfsd_idmap.h> 55 #include <linux/nfs4.h> 56 #include <linux/nfs4_acl.h> 57 #include <linux/sunrpc/gss_api.h> 58 #include <linux/sunrpc/svcauth_gss.h> 59 60 #define NFSDDBG_FACILITY NFSDDBG_XDR 61 62 /* 63 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing 64 * directory in order to indicate to the client that a filesystem boundary is present 65 * We use a fixed fsid for a referral 66 */ 67 #define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL 68 #define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL 69 70 static __be32 71 check_filename(char *str, int len, __be32 err) 72 { 73 int i; 74 75 if (len == 0) 76 return nfserr_inval; 77 if (isdotent(str, len)) 78 return err; 79 for (i = 0; i < len; i++) 80 if (str[i] == '/') 81 return err; 82 return 0; 83 } 84 85 /* 86 * START OF "GENERIC" DECODE ROUTINES. 87 * These may look a little ugly since they are imported from a "generic" 88 * set of XDR encode/decode routines which are intended to be shared by 89 * all of our NFSv4 implementations (OpenBSD, MacOS X...). 90 * 91 * If the pain of reading these is too great, it should be a straightforward 92 * task to translate them into Linux-specific versions which are more 93 * consistent with the style used in NFSv2/v3... 94 */ 95 #define DECODE_HEAD \ 96 __be32 *p; \ 97 __be32 status 98 #define DECODE_TAIL \ 99 status = 0; \ 100 out: \ 101 return status; \ 102 xdr_error: \ 103 dprintk("NFSD: xdr error (%s:%d)\n", \ 104 __FILE__, __LINE__); \ 105 status = nfserr_bad_xdr; \ 106 goto out 107 108 #define READ32(x) (x) = ntohl(*p++) 109 #define READ64(x) do { \ 110 (x) = (u64)ntohl(*p++) << 32; \ 111 (x) |= ntohl(*p++); \ 112 } while (0) 113 #define READTIME(x) do { \ 114 p++; \ 115 (x) = ntohl(*p++); \ 116 p++; \ 117 } while (0) 118 #define READMEM(x,nbytes) do { \ 119 x = (char *)p; \ 120 p += XDR_QUADLEN(nbytes); \ 121 } while (0) 122 #define SAVEMEM(x,nbytes) do { \ 123 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ 124 savemem(argp, p, nbytes) : \ 125 (char *)p)) { \ 126 dprintk("NFSD: xdr error (%s:%d)\n", \ 127 __FILE__, __LINE__); \ 128 goto xdr_error; \ 129 } \ 130 p += XDR_QUADLEN(nbytes); \ 131 } while (0) 132 #define COPYMEM(x,nbytes) do { \ 133 memcpy((x), p, nbytes); \ 134 p += XDR_QUADLEN(nbytes); \ 135 } while (0) 136 137 /* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */ 138 #define READ_BUF(nbytes) do { \ 139 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \ 140 p = argp->p; \ 141 argp->p += XDR_QUADLEN(nbytes); \ 142 } else if (!(p = read_buf(argp, nbytes))) { \ 143 dprintk("NFSD: xdr error (%s:%d)\n", \ 144 __FILE__, __LINE__); \ 145 goto xdr_error; \ 146 } \ 147 } while (0) 148 149 static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 150 { 151 /* We want more bytes than seem to be available. 152 * Maybe we need a new page, maybe we have just run out 153 */ 154 unsigned int avail = (char *)argp->end - (char *)argp->p; 155 __be32 *p; 156 if (avail + argp->pagelen < nbytes) 157 return NULL; 158 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ 159 return NULL; 160 /* ok, we can do it with the current plus the next page */ 161 if (nbytes <= sizeof(argp->tmp)) 162 p = argp->tmp; 163 else { 164 kfree(argp->tmpp); 165 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); 166 if (!p) 167 return NULL; 168 169 } 170 /* 171 * The following memcpy is safe because read_buf is always 172 * called with nbytes > avail, and the two cases above both 173 * guarantee p points to at least nbytes bytes. 174 */ 175 memcpy(p, argp->p, avail); 176 /* step to next page */ 177 argp->p = page_address(argp->pagelist[0]); 178 argp->pagelist++; 179 if (argp->pagelen < PAGE_SIZE) { 180 argp->end = p + (argp->pagelen>>2); 181 argp->pagelen = 0; 182 } else { 183 argp->end = p + (PAGE_SIZE>>2); 184 argp->pagelen -= PAGE_SIZE; 185 } 186 memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); 187 argp->p += XDR_QUADLEN(nbytes - avail); 188 return p; 189 } 190 191 static int 192 defer_free(struct nfsd4_compoundargs *argp, 193 void (*release)(const void *), void *p) 194 { 195 struct tmpbuf *tb; 196 197 tb = kmalloc(sizeof(*tb), GFP_KERNEL); 198 if (!tb) 199 return -ENOMEM; 200 tb->buf = p; 201 tb->release = release; 202 tb->next = argp->to_free; 203 argp->to_free = tb; 204 return 0; 205 } 206 207 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) 208 { 209 if (p == argp->tmp) { 210 p = kmalloc(nbytes, GFP_KERNEL); 211 if (!p) 212 return NULL; 213 memcpy(p, argp->tmp, nbytes); 214 } else { 215 BUG_ON(p != argp->tmpp); 216 argp->tmpp = NULL; 217 } 218 if (defer_free(argp, kfree, p)) { 219 kfree(p); 220 return NULL; 221 } else 222 return (char *)p; 223 } 224 225 static __be32 226 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) 227 { 228 u32 bmlen; 229 DECODE_HEAD; 230 231 bmval[0] = 0; 232 bmval[1] = 0; 233 234 READ_BUF(4); 235 READ32(bmlen); 236 if (bmlen > 1000) 237 goto xdr_error; 238 239 READ_BUF(bmlen << 2); 240 if (bmlen > 0) 241 READ32(bmval[0]); 242 if (bmlen > 1) 243 READ32(bmval[1]); 244 245 DECODE_TAIL; 246 } 247 248 static __be32 249 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr, 250 struct nfs4_acl **acl) 251 { 252 int expected_len, len = 0; 253 u32 dummy32; 254 char *buf; 255 int host_err; 256 257 DECODE_HEAD; 258 iattr->ia_valid = 0; 259 if ((status = nfsd4_decode_bitmap(argp, bmval))) 260 return status; 261 262 /* 263 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP; 264 * read-only attributes return ERR_INVAL. 265 */ 266 if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) 267 return nfserr_attrnotsupp; 268 if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1)) 269 return nfserr_inval; 270 271 READ_BUF(4); 272 READ32(expected_len); 273 274 if (bmval[0] & FATTR4_WORD0_SIZE) { 275 READ_BUF(8); 276 len += 8; 277 READ64(iattr->ia_size); 278 iattr->ia_valid |= ATTR_SIZE; 279 } 280 if (bmval[0] & FATTR4_WORD0_ACL) { 281 int nace; 282 struct nfs4_ace *ace; 283 284 READ_BUF(4); len += 4; 285 READ32(nace); 286 287 if (nace > NFS4_ACL_MAX) 288 return nfserr_resource; 289 290 *acl = nfs4_acl_new(nace); 291 if (*acl == NULL) { 292 host_err = -ENOMEM; 293 goto out_nfserr; 294 } 295 defer_free(argp, kfree, *acl); 296 297 (*acl)->naces = nace; 298 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { 299 READ_BUF(16); len += 16; 300 READ32(ace->type); 301 READ32(ace->flag); 302 READ32(ace->access_mask); 303 READ32(dummy32); 304 READ_BUF(dummy32); 305 len += XDR_QUADLEN(dummy32) << 2; 306 READMEM(buf, dummy32); 307 ace->whotype = nfs4_acl_get_whotype(buf, dummy32); 308 host_err = 0; 309 if (ace->whotype != NFS4_ACL_WHO_NAMED) 310 ace->who = 0; 311 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 312 host_err = nfsd_map_name_to_gid(argp->rqstp, 313 buf, dummy32, &ace->who); 314 else 315 host_err = nfsd_map_name_to_uid(argp->rqstp, 316 buf, dummy32, &ace->who); 317 if (host_err) 318 goto out_nfserr; 319 } 320 } else 321 *acl = NULL; 322 if (bmval[1] & FATTR4_WORD1_MODE) { 323 READ_BUF(4); 324 len += 4; 325 READ32(iattr->ia_mode); 326 iattr->ia_mode &= (S_IFMT | S_IALLUGO); 327 iattr->ia_valid |= ATTR_MODE; 328 } 329 if (bmval[1] & FATTR4_WORD1_OWNER) { 330 READ_BUF(4); 331 len += 4; 332 READ32(dummy32); 333 READ_BUF(dummy32); 334 len += (XDR_QUADLEN(dummy32) << 2); 335 READMEM(buf, dummy32); 336 if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) 337 goto out_nfserr; 338 iattr->ia_valid |= ATTR_UID; 339 } 340 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { 341 READ_BUF(4); 342 len += 4; 343 READ32(dummy32); 344 READ_BUF(dummy32); 345 len += (XDR_QUADLEN(dummy32) << 2); 346 READMEM(buf, dummy32); 347 if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) 348 goto out_nfserr; 349 iattr->ia_valid |= ATTR_GID; 350 } 351 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 352 READ_BUF(4); 353 len += 4; 354 READ32(dummy32); 355 switch (dummy32) { 356 case NFS4_SET_TO_CLIENT_TIME: 357 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 358 all 32 bits of 'nseconds'. */ 359 READ_BUF(12); 360 len += 12; 361 READ32(dummy32); 362 if (dummy32) 363 return nfserr_inval; 364 READ32(iattr->ia_atime.tv_sec); 365 READ32(iattr->ia_atime.tv_nsec); 366 if (iattr->ia_atime.tv_nsec >= (u32)1000000000) 367 return nfserr_inval; 368 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); 369 break; 370 case NFS4_SET_TO_SERVER_TIME: 371 iattr->ia_valid |= ATTR_ATIME; 372 break; 373 default: 374 goto xdr_error; 375 } 376 } 377 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 378 READ_BUF(4); 379 len += 4; 380 READ32(dummy32); 381 switch (dummy32) { 382 case NFS4_SET_TO_CLIENT_TIME: 383 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 384 all 32 bits of 'nseconds'. */ 385 READ_BUF(12); 386 len += 12; 387 READ32(dummy32); 388 if (dummy32) 389 return nfserr_inval; 390 READ32(iattr->ia_mtime.tv_sec); 391 READ32(iattr->ia_mtime.tv_nsec); 392 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) 393 return nfserr_inval; 394 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); 395 break; 396 case NFS4_SET_TO_SERVER_TIME: 397 iattr->ia_valid |= ATTR_MTIME; 398 break; 399 default: 400 goto xdr_error; 401 } 402 } 403 if (len != expected_len) 404 goto xdr_error; 405 406 DECODE_TAIL; 407 408 out_nfserr: 409 status = nfserrno(host_err); 410 goto out; 411 } 412 413 static __be32 414 nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid) 415 { 416 DECODE_HEAD; 417 418 READ_BUF(sizeof(stateid_t)); 419 READ32(sid->si_generation); 420 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 421 422 DECODE_TAIL; 423 } 424 425 static __be32 426 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access) 427 { 428 DECODE_HEAD; 429 430 READ_BUF(4); 431 READ32(access->ac_req_access); 432 433 DECODE_TAIL; 434 } 435 436 static __be32 437 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) 438 { 439 DECODE_HEAD; 440 441 close->cl_stateowner = NULL; 442 READ_BUF(4); 443 READ32(close->cl_seqid); 444 return nfsd4_decode_stateid(argp, &close->cl_stateid); 445 446 DECODE_TAIL; 447 } 448 449 450 static __be32 451 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit) 452 { 453 DECODE_HEAD; 454 455 READ_BUF(12); 456 READ64(commit->co_offset); 457 READ32(commit->co_count); 458 459 DECODE_TAIL; 460 } 461 462 static __be32 463 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create) 464 { 465 DECODE_HEAD; 466 467 READ_BUF(4); 468 READ32(create->cr_type); 469 switch (create->cr_type) { 470 case NF4LNK: 471 READ_BUF(4); 472 READ32(create->cr_linklen); 473 READ_BUF(create->cr_linklen); 474 SAVEMEM(create->cr_linkname, create->cr_linklen); 475 break; 476 case NF4BLK: 477 case NF4CHR: 478 READ_BUF(8); 479 READ32(create->cr_specdata1); 480 READ32(create->cr_specdata2); 481 break; 482 case NF4SOCK: 483 case NF4FIFO: 484 case NF4DIR: 485 default: 486 break; 487 } 488 489 READ_BUF(4); 490 READ32(create->cr_namelen); 491 READ_BUF(create->cr_namelen); 492 SAVEMEM(create->cr_name, create->cr_namelen); 493 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval))) 494 return status; 495 496 if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl))) 497 goto out; 498 499 DECODE_TAIL; 500 } 501 502 static inline __be32 503 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr) 504 { 505 return nfsd4_decode_stateid(argp, &dr->dr_stateid); 506 } 507 508 static inline __be32 509 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr) 510 { 511 return nfsd4_decode_bitmap(argp, getattr->ga_bmval); 512 } 513 514 static __be32 515 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link) 516 { 517 DECODE_HEAD; 518 519 READ_BUF(4); 520 READ32(link->li_namelen); 521 READ_BUF(link->li_namelen); 522 SAVEMEM(link->li_name, link->li_namelen); 523 if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval))) 524 return status; 525 526 DECODE_TAIL; 527 } 528 529 static __be32 530 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) 531 { 532 DECODE_HEAD; 533 534 lock->lk_replay_owner = NULL; 535 /* 536 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 537 */ 538 READ_BUF(28); 539 READ32(lock->lk_type); 540 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT)) 541 goto xdr_error; 542 READ32(lock->lk_reclaim); 543 READ64(lock->lk_offset); 544 READ64(lock->lk_length); 545 READ32(lock->lk_is_new); 546 547 if (lock->lk_is_new) { 548 READ_BUF(4); 549 READ32(lock->lk_new_open_seqid); 550 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid); 551 if (status) 552 return status; 553 READ_BUF(8 + sizeof(clientid_t)); 554 READ32(lock->lk_new_lock_seqid); 555 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t)); 556 READ32(lock->lk_new_owner.len); 557 READ_BUF(lock->lk_new_owner.len); 558 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len); 559 } else { 560 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid); 561 if (status) 562 return status; 563 READ_BUF(4); 564 READ32(lock->lk_old_lock_seqid); 565 } 566 567 DECODE_TAIL; 568 } 569 570 static __be32 571 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) 572 { 573 DECODE_HEAD; 574 575 READ_BUF(32); 576 READ32(lockt->lt_type); 577 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT)) 578 goto xdr_error; 579 READ64(lockt->lt_offset); 580 READ64(lockt->lt_length); 581 COPYMEM(&lockt->lt_clientid, 8); 582 READ32(lockt->lt_owner.len); 583 READ_BUF(lockt->lt_owner.len); 584 READMEM(lockt->lt_owner.data, lockt->lt_owner.len); 585 586 DECODE_TAIL; 587 } 588 589 static __be32 590 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku) 591 { 592 DECODE_HEAD; 593 594 locku->lu_stateowner = NULL; 595 READ_BUF(8); 596 READ32(locku->lu_type); 597 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT)) 598 goto xdr_error; 599 READ32(locku->lu_seqid); 600 status = nfsd4_decode_stateid(argp, &locku->lu_stateid); 601 if (status) 602 return status; 603 READ_BUF(16); 604 READ64(locku->lu_offset); 605 READ64(locku->lu_length); 606 607 DECODE_TAIL; 608 } 609 610 static __be32 611 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup) 612 { 613 DECODE_HEAD; 614 615 READ_BUF(4); 616 READ32(lookup->lo_len); 617 READ_BUF(lookup->lo_len); 618 SAVEMEM(lookup->lo_name, lookup->lo_len); 619 if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent))) 620 return status; 621 622 DECODE_TAIL; 623 } 624 625 static __be32 626 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) 627 { 628 DECODE_HEAD; 629 630 memset(open->op_bmval, 0, sizeof(open->op_bmval)); 631 open->op_iattr.ia_valid = 0; 632 open->op_stateowner = NULL; 633 634 /* seqid, share_access, share_deny, clientid, ownerlen */ 635 READ_BUF(16 + sizeof(clientid_t)); 636 READ32(open->op_seqid); 637 READ32(open->op_share_access); 638 READ32(open->op_share_deny); 639 COPYMEM(&open->op_clientid, sizeof(clientid_t)); 640 READ32(open->op_owner.len); 641 642 /* owner, open_flag */ 643 READ_BUF(open->op_owner.len + 4); 644 SAVEMEM(open->op_owner.data, open->op_owner.len); 645 READ32(open->op_create); 646 switch (open->op_create) { 647 case NFS4_OPEN_NOCREATE: 648 break; 649 case NFS4_OPEN_CREATE: 650 READ_BUF(4); 651 READ32(open->op_createmode); 652 switch (open->op_createmode) { 653 case NFS4_CREATE_UNCHECKED: 654 case NFS4_CREATE_GUARDED: 655 if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl))) 656 goto out; 657 break; 658 case NFS4_CREATE_EXCLUSIVE: 659 READ_BUF(8); 660 COPYMEM(open->op_verf.data, 8); 661 break; 662 default: 663 goto xdr_error; 664 } 665 break; 666 default: 667 goto xdr_error; 668 } 669 670 /* open_claim */ 671 READ_BUF(4); 672 READ32(open->op_claim_type); 673 switch (open->op_claim_type) { 674 case NFS4_OPEN_CLAIM_NULL: 675 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 676 READ_BUF(4); 677 READ32(open->op_fname.len); 678 READ_BUF(open->op_fname.len); 679 SAVEMEM(open->op_fname.data, open->op_fname.len); 680 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 681 return status; 682 break; 683 case NFS4_OPEN_CLAIM_PREVIOUS: 684 READ_BUF(4); 685 READ32(open->op_delegate_type); 686 break; 687 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 688 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid); 689 if (status) 690 return status; 691 READ_BUF(4); 692 READ32(open->op_fname.len); 693 READ_BUF(open->op_fname.len); 694 SAVEMEM(open->op_fname.data, open->op_fname.len); 695 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 696 return status; 697 break; 698 default: 699 goto xdr_error; 700 } 701 702 DECODE_TAIL; 703 } 704 705 static __be32 706 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf) 707 { 708 DECODE_HEAD; 709 710 open_conf->oc_stateowner = NULL; 711 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid); 712 if (status) 713 return status; 714 READ_BUF(4); 715 READ32(open_conf->oc_seqid); 716 717 DECODE_TAIL; 718 } 719 720 static __be32 721 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down) 722 { 723 DECODE_HEAD; 724 725 open_down->od_stateowner = NULL; 726 status = nfsd4_decode_stateid(argp, &open_down->od_stateid); 727 if (status) 728 return status; 729 READ_BUF(12); 730 READ32(open_down->od_seqid); 731 READ32(open_down->od_share_access); 732 READ32(open_down->od_share_deny); 733 734 DECODE_TAIL; 735 } 736 737 static __be32 738 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) 739 { 740 DECODE_HEAD; 741 742 READ_BUF(4); 743 READ32(putfh->pf_fhlen); 744 if (putfh->pf_fhlen > NFS4_FHSIZE) 745 goto xdr_error; 746 READ_BUF(putfh->pf_fhlen); 747 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen); 748 749 DECODE_TAIL; 750 } 751 752 static __be32 753 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read) 754 { 755 DECODE_HEAD; 756 757 status = nfsd4_decode_stateid(argp, &read->rd_stateid); 758 if (status) 759 return status; 760 READ_BUF(12); 761 READ64(read->rd_offset); 762 READ32(read->rd_length); 763 764 DECODE_TAIL; 765 } 766 767 static __be32 768 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir) 769 { 770 DECODE_HEAD; 771 772 READ_BUF(24); 773 READ64(readdir->rd_cookie); 774 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data)); 775 READ32(readdir->rd_dircount); /* just in case you needed a useless field... */ 776 READ32(readdir->rd_maxcount); 777 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval))) 778 goto out; 779 780 DECODE_TAIL; 781 } 782 783 static __be32 784 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove) 785 { 786 DECODE_HEAD; 787 788 READ_BUF(4); 789 READ32(remove->rm_namelen); 790 READ_BUF(remove->rm_namelen); 791 SAVEMEM(remove->rm_name, remove->rm_namelen); 792 if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent))) 793 return status; 794 795 DECODE_TAIL; 796 } 797 798 static __be32 799 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename) 800 { 801 DECODE_HEAD; 802 803 READ_BUF(4); 804 READ32(rename->rn_snamelen); 805 READ_BUF(rename->rn_snamelen + 4); 806 SAVEMEM(rename->rn_sname, rename->rn_snamelen); 807 READ32(rename->rn_tnamelen); 808 READ_BUF(rename->rn_tnamelen); 809 SAVEMEM(rename->rn_tname, rename->rn_tnamelen); 810 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent))) 811 return status; 812 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval))) 813 return status; 814 815 DECODE_TAIL; 816 } 817 818 static __be32 819 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) 820 { 821 DECODE_HEAD; 822 823 READ_BUF(sizeof(clientid_t)); 824 COPYMEM(clientid, sizeof(clientid_t)); 825 826 DECODE_TAIL; 827 } 828 829 static __be32 830 nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, 831 struct nfsd4_secinfo *secinfo) 832 { 833 DECODE_HEAD; 834 835 READ_BUF(4); 836 READ32(secinfo->si_namelen); 837 READ_BUF(secinfo->si_namelen); 838 SAVEMEM(secinfo->si_name, secinfo->si_namelen); 839 status = check_filename(secinfo->si_name, secinfo->si_namelen, 840 nfserr_noent); 841 if (status) 842 return status; 843 DECODE_TAIL; 844 } 845 846 static __be32 847 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 848 { 849 __be32 status; 850 851 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid); 852 if (status) 853 return status; 854 return nfsd4_decode_fattr(argp, setattr->sa_bmval, 855 &setattr->sa_iattr, &setattr->sa_acl); 856 } 857 858 static __be32 859 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid) 860 { 861 DECODE_HEAD; 862 863 READ_BUF(12); 864 COPYMEM(setclientid->se_verf.data, 8); 865 READ32(setclientid->se_namelen); 866 867 READ_BUF(setclientid->se_namelen + 8); 868 SAVEMEM(setclientid->se_name, setclientid->se_namelen); 869 READ32(setclientid->se_callback_prog); 870 READ32(setclientid->se_callback_netid_len); 871 872 READ_BUF(setclientid->se_callback_netid_len + 4); 873 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); 874 READ32(setclientid->se_callback_addr_len); 875 876 READ_BUF(setclientid->se_callback_addr_len + 4); 877 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); 878 READ32(setclientid->se_callback_ident); 879 880 DECODE_TAIL; 881 } 882 883 static __be32 884 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c) 885 { 886 DECODE_HEAD; 887 888 READ_BUF(8 + sizeof(nfs4_verifier)); 889 COPYMEM(&scd_c->sc_clientid, 8); 890 COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier)); 891 892 DECODE_TAIL; 893 } 894 895 /* Also used for NVERIFY */ 896 static __be32 897 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify) 898 { 899 #if 0 900 struct nfsd4_compoundargs save = { 901 .p = argp->p, 902 .end = argp->end, 903 .rqstp = argp->rqstp, 904 }; 905 u32 ve_bmval[2]; 906 struct iattr ve_iattr; /* request */ 907 struct nfs4_acl *ve_acl; /* request */ 908 #endif 909 DECODE_HEAD; 910 911 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval))) 912 goto out; 913 914 /* For convenience's sake, we compare raw xdr'd attributes in 915 * nfsd4_proc_verify; however we still decode here just to return 916 * correct error in case of bad xdr. */ 917 #if 0 918 status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl); 919 if (status == nfserr_inval) { 920 status = nfserrno(status); 921 goto out; 922 } 923 #endif 924 READ_BUF(4); 925 READ32(verify->ve_attrlen); 926 READ_BUF(verify->ve_attrlen); 927 SAVEMEM(verify->ve_attrval, verify->ve_attrlen); 928 929 DECODE_TAIL; 930 } 931 932 static __be32 933 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) 934 { 935 int avail; 936 int v; 937 int len; 938 DECODE_HEAD; 939 940 status = nfsd4_decode_stateid(argp, &write->wr_stateid); 941 if (status) 942 return status; 943 READ_BUF(16); 944 READ64(write->wr_offset); 945 READ32(write->wr_stable_how); 946 if (write->wr_stable_how > 2) 947 goto xdr_error; 948 READ32(write->wr_buflen); 949 950 /* Sorry .. no magic macros for this.. * 951 * READ_BUF(write->wr_buflen); 952 * SAVEMEM(write->wr_buf, write->wr_buflen); 953 */ 954 avail = (char*)argp->end - (char*)argp->p; 955 if (avail + argp->pagelen < write->wr_buflen) { 956 dprintk("NFSD: xdr error (%s:%d)\n", 957 __FILE__, __LINE__); 958 goto xdr_error; 959 } 960 argp->rqstp->rq_vec[0].iov_base = p; 961 argp->rqstp->rq_vec[0].iov_len = avail; 962 v = 0; 963 len = write->wr_buflen; 964 while (len > argp->rqstp->rq_vec[v].iov_len) { 965 len -= argp->rqstp->rq_vec[v].iov_len; 966 v++; 967 argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]); 968 argp->pagelist++; 969 if (argp->pagelen >= PAGE_SIZE) { 970 argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE; 971 argp->pagelen -= PAGE_SIZE; 972 } else { 973 argp->rqstp->rq_vec[v].iov_len = argp->pagelen; 974 argp->pagelen -= len; 975 } 976 } 977 argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); 978 argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); 979 argp->rqstp->rq_vec[v].iov_len = len; 980 write->wr_vlen = v+1; 981 982 DECODE_TAIL; 983 } 984 985 static __be32 986 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner) 987 { 988 DECODE_HEAD; 989 990 READ_BUF(12); 991 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t)); 992 READ32(rlockowner->rl_owner.len); 993 READ_BUF(rlockowner->rl_owner.len); 994 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len); 995 996 DECODE_TAIL; 997 } 998 999 static __be32 1000 nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p) 1001 { 1002 return nfs_ok; 1003 } 1004 1005 static __be32 1006 nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p) 1007 { 1008 return nfserr_opnotsupp; 1009 } 1010 1011 typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *); 1012 1013 static nfsd4_dec nfsd4_dec_ops[] = { 1014 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access, 1015 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close, 1016 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit, 1017 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create, 1018 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp, 1019 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn, 1020 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr, 1021 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop, 1022 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link, 1023 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock, 1024 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt, 1025 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku, 1026 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup, 1027 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop, 1028 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1029 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open, 1030 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp, 1031 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm, 1032 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade, 1033 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh, 1034 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp, 1035 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop, 1036 [OP_READ] = (nfsd4_dec)nfsd4_decode_read, 1037 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir, 1038 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop, 1039 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove, 1040 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename, 1041 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew, 1042 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop, 1043 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop, 1044 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo, 1045 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr, 1046 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid, 1047 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm, 1048 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1049 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write, 1050 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner, 1051 }; 1052 1053 struct nfsd4_minorversion_ops { 1054 nfsd4_dec *decoders; 1055 int nops; 1056 }; 1057 1058 static struct nfsd4_minorversion_ops nfsd4_minorversion[] = { 1059 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) }, 1060 }; 1061 1062 static __be32 1063 nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1064 { 1065 DECODE_HEAD; 1066 struct nfsd4_op *op; 1067 struct nfsd4_minorversion_ops *ops; 1068 int i; 1069 1070 /* 1071 * XXX: According to spec, we should check the tag 1072 * for UTF-8 compliance. I'm postponing this for 1073 * now because it seems that some clients do use 1074 * binary tags. 1075 */ 1076 READ_BUF(4); 1077 READ32(argp->taglen); 1078 READ_BUF(argp->taglen + 8); 1079 SAVEMEM(argp->tag, argp->taglen); 1080 READ32(argp->minorversion); 1081 READ32(argp->opcnt); 1082 1083 if (argp->taglen > NFSD4_MAX_TAGLEN) 1084 goto xdr_error; 1085 if (argp->opcnt > 100) 1086 goto xdr_error; 1087 1088 if (argp->opcnt > ARRAY_SIZE(argp->iops)) { 1089 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); 1090 if (!argp->ops) { 1091 argp->ops = argp->iops; 1092 dprintk("nfsd: couldn't allocate room for COMPOUND\n"); 1093 goto xdr_error; 1094 } 1095 } 1096 1097 if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion)) 1098 argp->opcnt = 0; 1099 1100 ops = &nfsd4_minorversion[argp->minorversion]; 1101 for (i = 0; i < argp->opcnt; i++) { 1102 op = &argp->ops[i]; 1103 op->replay = NULL; 1104 1105 /* 1106 * We can't use READ_BUF() here because we need to handle 1107 * a missing opcode as an OP_WRITE + 1. So we need to check 1108 * to see if we're truly at the end of our buffer or if there 1109 * is another page we need to flip to. 1110 */ 1111 1112 if (argp->p == argp->end) { 1113 if (argp->pagelen < 4) { 1114 /* There isn't an opcode still on the wire */ 1115 op->opnum = OP_WRITE + 1; 1116 op->status = nfserr_bad_xdr; 1117 argp->opcnt = i+1; 1118 break; 1119 } 1120 1121 /* 1122 * False alarm. We just hit a page boundary, but there 1123 * is still data available. Move pointer across page 1124 * boundary. *snip from READ_BUF* 1125 */ 1126 argp->p = page_address(argp->pagelist[0]); 1127 argp->pagelist++; 1128 if (argp->pagelen < PAGE_SIZE) { 1129 argp->end = p + (argp->pagelen>>2); 1130 argp->pagelen = 0; 1131 } else { 1132 argp->end = p + (PAGE_SIZE>>2); 1133 argp->pagelen -= PAGE_SIZE; 1134 } 1135 } 1136 op->opnum = ntohl(*argp->p++); 1137 1138 if (op->opnum >= OP_ACCESS && op->opnum < ops->nops) 1139 op->status = ops->decoders[op->opnum](argp, &op->u); 1140 else { 1141 op->opnum = OP_ILLEGAL; 1142 op->status = nfserr_op_illegal; 1143 } 1144 1145 if (op->status) { 1146 argp->opcnt = i+1; 1147 break; 1148 } 1149 } 1150 1151 DECODE_TAIL; 1152 } 1153 /* 1154 * END OF "GENERIC" DECODE ROUTINES. 1155 */ 1156 1157 /* 1158 * START OF "GENERIC" ENCODE ROUTINES. 1159 * These may look a little ugly since they are imported from a "generic" 1160 * set of XDR encode/decode routines which are intended to be shared by 1161 * all of our NFSv4 implementations (OpenBSD, MacOS X...). 1162 * 1163 * If the pain of reading these is too great, it should be a straightforward 1164 * task to translate them into Linux-specific versions which are more 1165 * consistent with the style used in NFSv2/v3... 1166 */ 1167 #define ENCODE_HEAD __be32 *p 1168 1169 #define WRITE32(n) *p++ = htonl(n) 1170 #define WRITE64(n) do { \ 1171 *p++ = htonl((u32)((n) >> 32)); \ 1172 *p++ = htonl((u32)(n)); \ 1173 } while (0) 1174 #define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \ 1175 *(p + XDR_QUADLEN(nbytes) -1) = 0; \ 1176 memcpy(p, ptr, nbytes); \ 1177 p += XDR_QUADLEN(nbytes); \ 1178 }} while (0) 1179 #define WRITECINFO(c) do { \ 1180 *p++ = htonl(c.atomic); \ 1181 *p++ = htonl(c.before_ctime_sec); \ 1182 *p++ = htonl(c.before_ctime_nsec); \ 1183 *p++ = htonl(c.after_ctime_sec); \ 1184 *p++ = htonl(c.after_ctime_nsec); \ 1185 } while (0) 1186 1187 #define RESERVE_SPACE(nbytes) do { \ 1188 p = resp->p; \ 1189 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \ 1190 } while (0) 1191 #define ADJUST_ARGS() resp->p = p 1192 1193 /* 1194 * Header routine to setup seqid operation replay cache 1195 */ 1196 #define ENCODE_SEQID_OP_HEAD \ 1197 __be32 *save; \ 1198 \ 1199 save = resp->p; 1200 1201 /* 1202 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This 1203 * is where sequence id's are incremented, and the replay cache is filled. 1204 * Note that we increment sequence id's here, at the last moment, so we're sure 1205 * we know whether the error to be returned is a sequence id mutating error. 1206 */ 1207 1208 #define ENCODE_SEQID_OP_TAIL(stateowner) do { \ 1209 if (seqid_mutating_err(nfserr) && stateowner) { \ 1210 stateowner->so_seqid++; \ 1211 stateowner->so_replay.rp_status = nfserr; \ 1212 stateowner->so_replay.rp_buflen = \ 1213 (((char *)(resp)->p - (char *)save)); \ 1214 memcpy(stateowner->so_replay.rp_buf, save, \ 1215 stateowner->so_replay.rp_buflen); \ 1216 } } while (0); 1217 1218 /* Encode as an array of strings the string given with components 1219 * seperated @sep. 1220 */ 1221 static __be32 nfsd4_encode_components(char sep, char *components, 1222 __be32 **pp, int *buflen) 1223 { 1224 __be32 *p = *pp; 1225 __be32 *countp = p; 1226 int strlen, count=0; 1227 char *str, *end; 1228 1229 dprintk("nfsd4_encode_components(%s)\n", components); 1230 if ((*buflen -= 4) < 0) 1231 return nfserr_resource; 1232 WRITE32(0); /* We will fill this in with @count later */ 1233 end = str = components; 1234 while (*end) { 1235 for (; *end && (*end != sep); end++) 1236 ; /* Point to end of component */ 1237 strlen = end - str; 1238 if (strlen) { 1239 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) 1240 return nfserr_resource; 1241 WRITE32(strlen); 1242 WRITEMEM(str, strlen); 1243 count++; 1244 } 1245 else 1246 end++; 1247 str = end; 1248 } 1249 *pp = p; 1250 p = countp; 1251 WRITE32(count); 1252 return 0; 1253 } 1254 1255 /* 1256 * encode a location element of a fs_locations structure 1257 */ 1258 static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, 1259 __be32 **pp, int *buflen) 1260 { 1261 __be32 status; 1262 __be32 *p = *pp; 1263 1264 status = nfsd4_encode_components(':', location->hosts, &p, buflen); 1265 if (status) 1266 return status; 1267 status = nfsd4_encode_components('/', location->path, &p, buflen); 1268 if (status) 1269 return status; 1270 *pp = p; 1271 return 0; 1272 } 1273 1274 /* 1275 * Return the path to an export point in the pseudo filesystem namespace 1276 * Returned string is safe to use as long as the caller holds a reference 1277 * to @exp. 1278 */ 1279 static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) 1280 { 1281 struct svc_fh tmp_fh; 1282 char *path, *rootpath; 1283 1284 fh_init(&tmp_fh, NFS4_FHSIZE); 1285 *stat = exp_pseudoroot(rqstp, &tmp_fh); 1286 if (*stat) 1287 return NULL; 1288 rootpath = tmp_fh.fh_export->ex_pathname; 1289 1290 path = exp->ex_pathname; 1291 1292 if (strncmp(path, rootpath, strlen(rootpath))) { 1293 dprintk("nfsd: fs_locations failed;" 1294 "%s is not contained in %s\n", path, rootpath); 1295 *stat = nfserr_notsupp; 1296 return NULL; 1297 } 1298 1299 return path + strlen(rootpath); 1300 } 1301 1302 /* 1303 * encode a fs_locations structure 1304 */ 1305 static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, 1306 struct svc_export *exp, 1307 __be32 **pp, int *buflen) 1308 { 1309 __be32 status; 1310 int i; 1311 __be32 *p = *pp; 1312 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1313 char *root = nfsd4_path(rqstp, exp, &status); 1314 1315 if (status) 1316 return status; 1317 status = nfsd4_encode_components('/', root, &p, buflen); 1318 if (status) 1319 return status; 1320 if ((*buflen -= 4) < 0) 1321 return nfserr_resource; 1322 WRITE32(fslocs->locations_count); 1323 for (i=0; i<fslocs->locations_count; i++) { 1324 status = nfsd4_encode_fs_location4(&fslocs->locations[i], 1325 &p, buflen); 1326 if (status) 1327 return status; 1328 } 1329 *pp = p; 1330 return 0; 1331 } 1332 1333 static u32 nfs4_ftypes[16] = { 1334 NF4BAD, NF4FIFO, NF4CHR, NF4BAD, 1335 NF4DIR, NF4BAD, NF4BLK, NF4BAD, 1336 NF4REG, NF4BAD, NF4LNK, NF4BAD, 1337 NF4SOCK, NF4BAD, NF4LNK, NF4BAD, 1338 }; 1339 1340 static __be32 1341 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1342 __be32 **p, int *buflen) 1343 { 1344 int status; 1345 1346 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) 1347 return nfserr_resource; 1348 if (whotype != NFS4_ACL_WHO_NAMED) 1349 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1)); 1350 else if (group) 1351 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1)); 1352 else 1353 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1)); 1354 if (status < 0) 1355 return nfserrno(status); 1356 *p = xdr_encode_opaque(*p, NULL, status); 1357 *buflen -= (XDR_QUADLEN(status) << 2) + 4; 1358 BUG_ON(*buflen < 0); 1359 return 0; 1360 } 1361 1362 static inline __be32 1363 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen) 1364 { 1365 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen); 1366 } 1367 1368 static inline __be32 1369 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen) 1370 { 1371 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen); 1372 } 1373 1374 static inline __be32 1375 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1376 __be32 **p, int *buflen) 1377 { 1378 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); 1379 } 1380 1381 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ 1382 FATTR4_WORD0_RDATTR_ERROR) 1383 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID 1384 1385 static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) 1386 { 1387 /* As per referral draft: */ 1388 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS || 1389 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) { 1390 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR || 1391 *bmval0 & FATTR4_WORD0_FS_LOCATIONS) 1392 *rdattr_err = NFSERR_MOVED; 1393 else 1394 return nfserr_moved; 1395 } 1396 *bmval0 &= WORD0_ABSENT_FS_ATTRS; 1397 *bmval1 &= WORD1_ABSENT_FS_ATTRS; 1398 return 0; 1399 } 1400 1401 /* 1402 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 1403 * ourselves. 1404 * 1405 * @countp is the buffer size in _words_; upon successful return this becomes 1406 * replaced with the number of words written. 1407 */ 1408 __be32 1409 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 1410 struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, 1411 struct svc_rqst *rqstp, int ignore_crossmnt) 1412 { 1413 u32 bmval0 = bmval[0]; 1414 u32 bmval1 = bmval[1]; 1415 struct kstat stat; 1416 struct svc_fh tempfh; 1417 struct kstatfs statfs; 1418 int buflen = *countp << 2; 1419 __be32 *attrlenp; 1420 u32 dummy; 1421 u64 dummy64; 1422 u32 rdattr_err = 0; 1423 __be32 *p = buffer; 1424 __be32 status; 1425 int err; 1426 int aclsupport = 0; 1427 struct nfs4_acl *acl = NULL; 1428 1429 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 1430 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); 1431 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); 1432 1433 if (exp->ex_fslocs.migrated) { 1434 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err); 1435 if (status) 1436 goto out; 1437 } 1438 1439 err = vfs_getattr(exp->ex_path.mnt, dentry, &stat); 1440 if (err) 1441 goto out_nfserr; 1442 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | 1443 FATTR4_WORD0_MAXNAME)) || 1444 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | 1445 FATTR4_WORD1_SPACE_TOTAL))) { 1446 err = vfs_statfs(dentry, &statfs); 1447 if (err) 1448 goto out_nfserr; 1449 } 1450 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { 1451 fh_init(&tempfh, NFS4_FHSIZE); 1452 status = fh_compose(&tempfh, exp, dentry, NULL); 1453 if (status) 1454 goto out; 1455 fhp = &tempfh; 1456 } 1457 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT 1458 | FATTR4_WORD0_SUPPORTED_ATTRS)) { 1459 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); 1460 aclsupport = (err == 0); 1461 if (bmval0 & FATTR4_WORD0_ACL) { 1462 if (err == -EOPNOTSUPP) 1463 bmval0 &= ~FATTR4_WORD0_ACL; 1464 else if (err == -EINVAL) { 1465 status = nfserr_attrnotsupp; 1466 goto out; 1467 } else if (err != 0) 1468 goto out_nfserr; 1469 } 1470 } 1471 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 1472 if (exp->ex_fslocs.locations == NULL) { 1473 bmval0 &= ~FATTR4_WORD0_FS_LOCATIONS; 1474 } 1475 } 1476 if ((buflen -= 16) < 0) 1477 goto out_resource; 1478 1479 WRITE32(2); 1480 WRITE32(bmval0); 1481 WRITE32(bmval1); 1482 attrlenp = p++; /* to be backfilled later */ 1483 1484 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 1485 u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0; 1486 if ((buflen -= 12) < 0) 1487 goto out_resource; 1488 if (!aclsupport) 1489 word0 &= ~FATTR4_WORD0_ACL; 1490 if (!exp->ex_fslocs.locations) 1491 word0 &= ~FATTR4_WORD0_FS_LOCATIONS; 1492 WRITE32(2); 1493 WRITE32(word0); 1494 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); 1495 } 1496 if (bmval0 & FATTR4_WORD0_TYPE) { 1497 if ((buflen -= 4) < 0) 1498 goto out_resource; 1499 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12]; 1500 if (dummy == NF4BAD) 1501 goto out_serverfault; 1502 WRITE32(dummy); 1503 } 1504 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 1505 if ((buflen -= 4) < 0) 1506 goto out_resource; 1507 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) 1508 WRITE32(NFS4_FH_PERSISTENT); 1509 else 1510 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 1511 } 1512 if (bmval0 & FATTR4_WORD0_CHANGE) { 1513 /* 1514 * Note: This _must_ be consistent with the scheme for writing 1515 * change_info, so any changes made here must be reflected there 1516 * as well. (See xdr4.h:set_change_info() and the WRITECINFO() 1517 * macro above.) 1518 */ 1519 if ((buflen -= 8) < 0) 1520 goto out_resource; 1521 WRITE32(stat.ctime.tv_sec); 1522 WRITE32(stat.ctime.tv_nsec); 1523 } 1524 if (bmval0 & FATTR4_WORD0_SIZE) { 1525 if ((buflen -= 8) < 0) 1526 goto out_resource; 1527 WRITE64(stat.size); 1528 } 1529 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { 1530 if ((buflen -= 4) < 0) 1531 goto out_resource; 1532 WRITE32(1); 1533 } 1534 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { 1535 if ((buflen -= 4) < 0) 1536 goto out_resource; 1537 WRITE32(1); 1538 } 1539 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { 1540 if ((buflen -= 4) < 0) 1541 goto out_resource; 1542 WRITE32(0); 1543 } 1544 if (bmval0 & FATTR4_WORD0_FSID) { 1545 if ((buflen -= 16) < 0) 1546 goto out_resource; 1547 if (exp->ex_fslocs.migrated) { 1548 WRITE64(NFS4_REFERRAL_FSID_MAJOR); 1549 WRITE64(NFS4_REFERRAL_FSID_MINOR); 1550 } else switch(fsid_source(fhp)) { 1551 case FSIDSOURCE_FSID: 1552 WRITE64((u64)exp->ex_fsid); 1553 WRITE64((u64)0); 1554 break; 1555 case FSIDSOURCE_DEV: 1556 WRITE32(0); 1557 WRITE32(MAJOR(stat.dev)); 1558 WRITE32(0); 1559 WRITE32(MINOR(stat.dev)); 1560 break; 1561 case FSIDSOURCE_UUID: 1562 WRITEMEM(exp->ex_uuid, 16); 1563 break; 1564 } 1565 } 1566 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { 1567 if ((buflen -= 4) < 0) 1568 goto out_resource; 1569 WRITE32(0); 1570 } 1571 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 1572 if ((buflen -= 4) < 0) 1573 goto out_resource; 1574 WRITE32(NFSD_LEASE_TIME); 1575 } 1576 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 1577 if ((buflen -= 4) < 0) 1578 goto out_resource; 1579 WRITE32(rdattr_err); 1580 } 1581 if (bmval0 & FATTR4_WORD0_ACL) { 1582 struct nfs4_ace *ace; 1583 1584 if (acl == NULL) { 1585 if ((buflen -= 4) < 0) 1586 goto out_resource; 1587 1588 WRITE32(0); 1589 goto out_acl; 1590 } 1591 if ((buflen -= 4) < 0) 1592 goto out_resource; 1593 WRITE32(acl->naces); 1594 1595 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { 1596 if ((buflen -= 4*3) < 0) 1597 goto out_resource; 1598 WRITE32(ace->type); 1599 WRITE32(ace->flag); 1600 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); 1601 status = nfsd4_encode_aclname(rqstp, ace->whotype, 1602 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP, 1603 &p, &buflen); 1604 if (status == nfserr_resource) 1605 goto out_resource; 1606 if (status) 1607 goto out; 1608 } 1609 } 1610 out_acl: 1611 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { 1612 if ((buflen -= 4) < 0) 1613 goto out_resource; 1614 WRITE32(aclsupport ? 1615 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); 1616 } 1617 if (bmval0 & FATTR4_WORD0_CANSETTIME) { 1618 if ((buflen -= 4) < 0) 1619 goto out_resource; 1620 WRITE32(1); 1621 } 1622 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 1623 if ((buflen -= 4) < 0) 1624 goto out_resource; 1625 WRITE32(1); 1626 } 1627 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 1628 if ((buflen -= 4) < 0) 1629 goto out_resource; 1630 WRITE32(1); 1631 } 1632 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { 1633 if ((buflen -= 4) < 0) 1634 goto out_resource; 1635 WRITE32(1); 1636 } 1637 if (bmval0 & FATTR4_WORD0_FILEHANDLE) { 1638 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; 1639 if (buflen < 0) 1640 goto out_resource; 1641 WRITE32(fhp->fh_handle.fh_size); 1642 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); 1643 } 1644 if (bmval0 & FATTR4_WORD0_FILEID) { 1645 if ((buflen -= 8) < 0) 1646 goto out_resource; 1647 WRITE64(stat.ino); 1648 } 1649 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 1650 if ((buflen -= 8) < 0) 1651 goto out_resource; 1652 WRITE64((u64) statfs.f_ffree); 1653 } 1654 if (bmval0 & FATTR4_WORD0_FILES_FREE) { 1655 if ((buflen -= 8) < 0) 1656 goto out_resource; 1657 WRITE64((u64) statfs.f_ffree); 1658 } 1659 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { 1660 if ((buflen -= 8) < 0) 1661 goto out_resource; 1662 WRITE64((u64) statfs.f_files); 1663 } 1664 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 1665 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); 1666 if (status == nfserr_resource) 1667 goto out_resource; 1668 if (status) 1669 goto out; 1670 } 1671 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 1672 if ((buflen -= 4) < 0) 1673 goto out_resource; 1674 WRITE32(1); 1675 } 1676 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 1677 if ((buflen -= 8) < 0) 1678 goto out_resource; 1679 WRITE64(~(u64)0); 1680 } 1681 if (bmval0 & FATTR4_WORD0_MAXLINK) { 1682 if ((buflen -= 4) < 0) 1683 goto out_resource; 1684 WRITE32(255); 1685 } 1686 if (bmval0 & FATTR4_WORD0_MAXNAME) { 1687 if ((buflen -= 4) < 0) 1688 goto out_resource; 1689 WRITE32(statfs.f_namelen); 1690 } 1691 if (bmval0 & FATTR4_WORD0_MAXREAD) { 1692 if ((buflen -= 8) < 0) 1693 goto out_resource; 1694 WRITE64((u64) svc_max_payload(rqstp)); 1695 } 1696 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 1697 if ((buflen -= 8) < 0) 1698 goto out_resource; 1699 WRITE64((u64) svc_max_payload(rqstp)); 1700 } 1701 if (bmval1 & FATTR4_WORD1_MODE) { 1702 if ((buflen -= 4) < 0) 1703 goto out_resource; 1704 WRITE32(stat.mode & S_IALLUGO); 1705 } 1706 if (bmval1 & FATTR4_WORD1_NO_TRUNC) { 1707 if ((buflen -= 4) < 0) 1708 goto out_resource; 1709 WRITE32(1); 1710 } 1711 if (bmval1 & FATTR4_WORD1_NUMLINKS) { 1712 if ((buflen -= 4) < 0) 1713 goto out_resource; 1714 WRITE32(stat.nlink); 1715 } 1716 if (bmval1 & FATTR4_WORD1_OWNER) { 1717 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); 1718 if (status == nfserr_resource) 1719 goto out_resource; 1720 if (status) 1721 goto out; 1722 } 1723 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { 1724 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); 1725 if (status == nfserr_resource) 1726 goto out_resource; 1727 if (status) 1728 goto out; 1729 } 1730 if (bmval1 & FATTR4_WORD1_RAWDEV) { 1731 if ((buflen -= 8) < 0) 1732 goto out_resource; 1733 WRITE32((u32) MAJOR(stat.rdev)); 1734 WRITE32((u32) MINOR(stat.rdev)); 1735 } 1736 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { 1737 if ((buflen -= 8) < 0) 1738 goto out_resource; 1739 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; 1740 WRITE64(dummy64); 1741 } 1742 if (bmval1 & FATTR4_WORD1_SPACE_FREE) { 1743 if ((buflen -= 8) < 0) 1744 goto out_resource; 1745 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; 1746 WRITE64(dummy64); 1747 } 1748 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { 1749 if ((buflen -= 8) < 0) 1750 goto out_resource; 1751 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; 1752 WRITE64(dummy64); 1753 } 1754 if (bmval1 & FATTR4_WORD1_SPACE_USED) { 1755 if ((buflen -= 8) < 0) 1756 goto out_resource; 1757 dummy64 = (u64)stat.blocks << 9; 1758 WRITE64(dummy64); 1759 } 1760 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { 1761 if ((buflen -= 12) < 0) 1762 goto out_resource; 1763 WRITE32(0); 1764 WRITE32(stat.atime.tv_sec); 1765 WRITE32(stat.atime.tv_nsec); 1766 } 1767 if (bmval1 & FATTR4_WORD1_TIME_DELTA) { 1768 if ((buflen -= 12) < 0) 1769 goto out_resource; 1770 WRITE32(0); 1771 WRITE32(1); 1772 WRITE32(0); 1773 } 1774 if (bmval1 & FATTR4_WORD1_TIME_METADATA) { 1775 if ((buflen -= 12) < 0) 1776 goto out_resource; 1777 WRITE32(0); 1778 WRITE32(stat.ctime.tv_sec); 1779 WRITE32(stat.ctime.tv_nsec); 1780 } 1781 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { 1782 if ((buflen -= 12) < 0) 1783 goto out_resource; 1784 WRITE32(0); 1785 WRITE32(stat.mtime.tv_sec); 1786 WRITE32(stat.mtime.tv_nsec); 1787 } 1788 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 1789 if ((buflen -= 8) < 0) 1790 goto out_resource; 1791 /* 1792 * Get parent's attributes if not ignoring crossmount 1793 * and this is the root of a cross-mounted filesystem. 1794 */ 1795 if (ignore_crossmnt == 0 && 1796 exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) { 1797 err = vfs_getattr(exp->ex_path.mnt->mnt_parent, 1798 exp->ex_path.mnt->mnt_mountpoint, &stat); 1799 if (err) 1800 goto out_nfserr; 1801 } 1802 WRITE64(stat.ino); 1803 } 1804 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 1805 *countp = p - buffer; 1806 status = nfs_ok; 1807 1808 out: 1809 kfree(acl); 1810 if (fhp == &tempfh) 1811 fh_put(&tempfh); 1812 return status; 1813 out_nfserr: 1814 status = nfserrno(err); 1815 goto out; 1816 out_resource: 1817 *countp = 0; 1818 status = nfserr_resource; 1819 goto out; 1820 out_serverfault: 1821 status = nfserr_serverfault; 1822 goto out; 1823 } 1824 1825 static inline int attributes_need_mount(u32 *bmval) 1826 { 1827 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME)) 1828 return 1; 1829 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) 1830 return 1; 1831 return 0; 1832 } 1833 1834 static __be32 1835 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, 1836 const char *name, int namlen, __be32 *p, int *buflen) 1837 { 1838 struct svc_export *exp = cd->rd_fhp->fh_export; 1839 struct dentry *dentry; 1840 __be32 nfserr; 1841 int ignore_crossmnt = 0; 1842 1843 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); 1844 if (IS_ERR(dentry)) 1845 return nfserrno(PTR_ERR(dentry)); 1846 1847 exp_get(exp); 1848 /* 1849 * In the case of a mountpoint, the client may be asking for 1850 * attributes that are only properties of the underlying filesystem 1851 * as opposed to the cross-mounted file system. In such a case, 1852 * we will not follow the cross mount and will fill the attribtutes 1853 * directly from the mountpoint dentry. 1854 */ 1855 if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval)) 1856 ignore_crossmnt = 1; 1857 else if (d_mountpoint(dentry)) { 1858 int err; 1859 1860 /* 1861 * Why the heck aren't we just using nfsd_lookup?? 1862 * Different "."/".." handling? Something else? 1863 * At least, add a comment here to explain.... 1864 */ 1865 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); 1866 if (err) { 1867 nfserr = nfserrno(err); 1868 goto out_put; 1869 } 1870 nfserr = check_nfsd_access(exp, cd->rd_rqstp); 1871 if (nfserr) 1872 goto out_put; 1873 1874 } 1875 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, 1876 cd->rd_rqstp, ignore_crossmnt); 1877 out_put: 1878 dput(dentry); 1879 exp_put(exp); 1880 return nfserr; 1881 } 1882 1883 static __be32 * 1884 nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) 1885 { 1886 __be32 *attrlenp; 1887 1888 if (buflen < 6) 1889 return NULL; 1890 *p++ = htonl(2); 1891 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ 1892 *p++ = htonl(0); /* bmval1 */ 1893 1894 attrlenp = p++; 1895 *p++ = nfserr; /* no htonl */ 1896 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 1897 return p; 1898 } 1899 1900 static int 1901 nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, 1902 loff_t offset, u64 ino, unsigned int d_type) 1903 { 1904 struct readdir_cd *ccd = ccdv; 1905 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 1906 int buflen; 1907 __be32 *p = cd->buffer; 1908 __be32 nfserr = nfserr_toosmall; 1909 1910 /* In nfsv4, "." and ".." never make it onto the wire.. */ 1911 if (name && isdotent(name, namlen)) { 1912 cd->common.err = nfs_ok; 1913 return 0; 1914 } 1915 1916 if (cd->offset) 1917 xdr_encode_hyper(cd->offset, (u64) offset); 1918 1919 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen); 1920 if (buflen < 0) 1921 goto fail; 1922 1923 *p++ = xdr_one; /* mark entry present */ 1924 cd->offset = p; /* remember pointer */ 1925 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 1926 p = xdr_encode_array(p, name, namlen); /* name length & name */ 1927 1928 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen); 1929 switch (nfserr) { 1930 case nfs_ok: 1931 p += buflen; 1932 break; 1933 case nfserr_resource: 1934 nfserr = nfserr_toosmall; 1935 goto fail; 1936 case nfserr_dropit: 1937 goto fail; 1938 default: 1939 /* 1940 * If the client requested the RDATTR_ERROR attribute, 1941 * we stuff the error code into this attribute 1942 * and continue. If this attribute was not requested, 1943 * then in accordance with the spec, we fail the 1944 * entire READDIR operation(!) 1945 */ 1946 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 1947 goto fail; 1948 p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 1949 if (p == NULL) { 1950 nfserr = nfserr_toosmall; 1951 goto fail; 1952 } 1953 } 1954 cd->buflen -= (p - cd->buffer); 1955 cd->buffer = p; 1956 cd->common.err = nfs_ok; 1957 return 0; 1958 fail: 1959 cd->common.err = nfserr; 1960 return -EINVAL; 1961 } 1962 1963 static void 1964 nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid) 1965 { 1966 ENCODE_HEAD; 1967 1968 RESERVE_SPACE(sizeof(stateid_t)); 1969 WRITE32(sid->si_generation); 1970 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 1971 ADJUST_ARGS(); 1972 } 1973 1974 static __be32 1975 nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) 1976 { 1977 ENCODE_HEAD; 1978 1979 if (!nfserr) { 1980 RESERVE_SPACE(8); 1981 WRITE32(access->ac_supported); 1982 WRITE32(access->ac_resp_access); 1983 ADJUST_ARGS(); 1984 } 1985 return nfserr; 1986 } 1987 1988 static __be32 1989 nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 1990 { 1991 ENCODE_SEQID_OP_HEAD; 1992 1993 if (!nfserr) 1994 nfsd4_encode_stateid(resp, &close->cl_stateid); 1995 1996 ENCODE_SEQID_OP_TAIL(close->cl_stateowner); 1997 return nfserr; 1998 } 1999 2000 2001 static __be32 2002 nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) 2003 { 2004 ENCODE_HEAD; 2005 2006 if (!nfserr) { 2007 RESERVE_SPACE(8); 2008 WRITEMEM(commit->co_verf.data, 8); 2009 ADJUST_ARGS(); 2010 } 2011 return nfserr; 2012 } 2013 2014 static __be32 2015 nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) 2016 { 2017 ENCODE_HEAD; 2018 2019 if (!nfserr) { 2020 RESERVE_SPACE(32); 2021 WRITECINFO(create->cr_cinfo); 2022 WRITE32(2); 2023 WRITE32(create->cr_bmval[0]); 2024 WRITE32(create->cr_bmval[1]); 2025 ADJUST_ARGS(); 2026 } 2027 return nfserr; 2028 } 2029 2030 static __be32 2031 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr) 2032 { 2033 struct svc_fh *fhp = getattr->ga_fhp; 2034 int buflen; 2035 2036 if (nfserr) 2037 return nfserr; 2038 2039 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); 2040 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 2041 resp->p, &buflen, getattr->ga_bmval, 2042 resp->rqstp, 0); 2043 if (!nfserr) 2044 resp->p += buflen; 2045 return nfserr; 2046 } 2047 2048 static __be32 2049 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp) 2050 { 2051 struct svc_fh *fhp = *fhpp; 2052 unsigned int len; 2053 ENCODE_HEAD; 2054 2055 if (!nfserr) { 2056 len = fhp->fh_handle.fh_size; 2057 RESERVE_SPACE(len + 4); 2058 WRITE32(len); 2059 WRITEMEM(&fhp->fh_handle.fh_base, len); 2060 ADJUST_ARGS(); 2061 } 2062 return nfserr; 2063 } 2064 2065 /* 2066 * Including all fields other than the name, a LOCK4denied structure requires 2067 * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. 2068 */ 2069 static void 2070 nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld) 2071 { 2072 ENCODE_HEAD; 2073 2074 RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0)); 2075 WRITE64(ld->ld_start); 2076 WRITE64(ld->ld_length); 2077 WRITE32(ld->ld_type); 2078 if (ld->ld_sop) { 2079 WRITEMEM(&ld->ld_clientid, 8); 2080 WRITE32(ld->ld_sop->so_owner.len); 2081 WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len); 2082 kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner); 2083 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ 2084 WRITE64((u64)0); /* clientid */ 2085 WRITE32(0); /* length of owner name */ 2086 } 2087 ADJUST_ARGS(); 2088 } 2089 2090 static __be32 2091 nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) 2092 { 2093 ENCODE_SEQID_OP_HEAD; 2094 2095 if (!nfserr) 2096 nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); 2097 else if (nfserr == nfserr_denied) 2098 nfsd4_encode_lock_denied(resp, &lock->lk_denied); 2099 2100 ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner); 2101 return nfserr; 2102 } 2103 2104 static __be32 2105 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) 2106 { 2107 if (nfserr == nfserr_denied) 2108 nfsd4_encode_lock_denied(resp, &lockt->lt_denied); 2109 return nfserr; 2110 } 2111 2112 static __be32 2113 nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) 2114 { 2115 ENCODE_SEQID_OP_HEAD; 2116 2117 if (!nfserr) 2118 nfsd4_encode_stateid(resp, &locku->lu_stateid); 2119 2120 ENCODE_SEQID_OP_TAIL(locku->lu_stateowner); 2121 return nfserr; 2122 } 2123 2124 2125 static __be32 2126 nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) 2127 { 2128 ENCODE_HEAD; 2129 2130 if (!nfserr) { 2131 RESERVE_SPACE(20); 2132 WRITECINFO(link->li_cinfo); 2133 ADJUST_ARGS(); 2134 } 2135 return nfserr; 2136 } 2137 2138 2139 static __be32 2140 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) 2141 { 2142 ENCODE_HEAD; 2143 ENCODE_SEQID_OP_HEAD; 2144 2145 if (nfserr) 2146 goto out; 2147 2148 nfsd4_encode_stateid(resp, &open->op_stateid); 2149 RESERVE_SPACE(40); 2150 WRITECINFO(open->op_cinfo); 2151 WRITE32(open->op_rflags); 2152 WRITE32(2); 2153 WRITE32(open->op_bmval[0]); 2154 WRITE32(open->op_bmval[1]); 2155 WRITE32(open->op_delegate_type); 2156 ADJUST_ARGS(); 2157 2158 switch (open->op_delegate_type) { 2159 case NFS4_OPEN_DELEGATE_NONE: 2160 break; 2161 case NFS4_OPEN_DELEGATE_READ: 2162 nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2163 RESERVE_SPACE(20); 2164 WRITE32(open->op_recall); 2165 2166 /* 2167 * TODO: ACE's in delegations 2168 */ 2169 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2170 WRITE32(0); 2171 WRITE32(0); 2172 WRITE32(0); /* XXX: is NULL principal ok? */ 2173 ADJUST_ARGS(); 2174 break; 2175 case NFS4_OPEN_DELEGATE_WRITE: 2176 nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2177 RESERVE_SPACE(32); 2178 WRITE32(0); 2179 2180 /* 2181 * TODO: space_limit's in delegations 2182 */ 2183 WRITE32(NFS4_LIMIT_SIZE); 2184 WRITE32(~(u32)0); 2185 WRITE32(~(u32)0); 2186 2187 /* 2188 * TODO: ACE's in delegations 2189 */ 2190 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2191 WRITE32(0); 2192 WRITE32(0); 2193 WRITE32(0); /* XXX: is NULL principal ok? */ 2194 ADJUST_ARGS(); 2195 break; 2196 default: 2197 BUG(); 2198 } 2199 /* XXX save filehandle here */ 2200 out: 2201 ENCODE_SEQID_OP_TAIL(open->op_stateowner); 2202 return nfserr; 2203 } 2204 2205 static __be32 2206 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) 2207 { 2208 ENCODE_SEQID_OP_HEAD; 2209 2210 if (!nfserr) 2211 nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); 2212 2213 ENCODE_SEQID_OP_TAIL(oc->oc_stateowner); 2214 return nfserr; 2215 } 2216 2217 static __be32 2218 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) 2219 { 2220 ENCODE_SEQID_OP_HEAD; 2221 2222 if (!nfserr) 2223 nfsd4_encode_stateid(resp, &od->od_stateid); 2224 2225 ENCODE_SEQID_OP_TAIL(od->od_stateowner); 2226 return nfserr; 2227 } 2228 2229 static __be32 2230 nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, 2231 struct nfsd4_read *read) 2232 { 2233 u32 eof; 2234 int v, pn; 2235 unsigned long maxcount; 2236 long len; 2237 ENCODE_HEAD; 2238 2239 if (nfserr) 2240 return nfserr; 2241 if (resp->xbuf->page_len) 2242 return nfserr_resource; 2243 2244 RESERVE_SPACE(8); /* eof flag and byte count */ 2245 2246 maxcount = svc_max_payload(resp->rqstp); 2247 if (maxcount > read->rd_length) 2248 maxcount = read->rd_length; 2249 2250 len = maxcount; 2251 v = 0; 2252 while (len > 0) { 2253 pn = resp->rqstp->rq_resused++; 2254 resp->rqstp->rq_vec[v].iov_base = 2255 page_address(resp->rqstp->rq_respages[pn]); 2256 resp->rqstp->rq_vec[v].iov_len = 2257 len < PAGE_SIZE ? len : PAGE_SIZE; 2258 v++; 2259 len -= PAGE_SIZE; 2260 } 2261 read->rd_vlen = v; 2262 2263 nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, 2264 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, 2265 &maxcount); 2266 2267 if (nfserr == nfserr_symlink) 2268 nfserr = nfserr_inval; 2269 if (nfserr) 2270 return nfserr; 2271 eof = (read->rd_offset + maxcount >= 2272 read->rd_fhp->fh_dentry->d_inode->i_size); 2273 2274 WRITE32(eof); 2275 WRITE32(maxcount); 2276 ADJUST_ARGS(); 2277 resp->xbuf->head[0].iov_len = (char*)p 2278 - (char*)resp->xbuf->head[0].iov_base; 2279 resp->xbuf->page_len = maxcount; 2280 2281 /* Use rest of head for padding and remaining ops: */ 2282 resp->xbuf->tail[0].iov_base = p; 2283 resp->xbuf->tail[0].iov_len = 0; 2284 if (maxcount&3) { 2285 RESERVE_SPACE(4); 2286 WRITE32(0); 2287 resp->xbuf->tail[0].iov_base += maxcount&3; 2288 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2289 ADJUST_ARGS(); 2290 } 2291 return 0; 2292 } 2293 2294 static __be32 2295 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) 2296 { 2297 int maxcount; 2298 char *page; 2299 ENCODE_HEAD; 2300 2301 if (nfserr) 2302 return nfserr; 2303 if (resp->xbuf->page_len) 2304 return nfserr_resource; 2305 2306 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2307 2308 maxcount = PAGE_SIZE; 2309 RESERVE_SPACE(4); 2310 2311 /* 2312 * XXX: By default, the ->readlink() VFS op will truncate symlinks 2313 * if they would overflow the buffer. Is this kosher in NFSv4? If 2314 * not, one easy fix is: if ->readlink() precisely fills the buffer, 2315 * assume that truncation occurred, and return NFS4ERR_RESOURCE. 2316 */ 2317 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); 2318 if (nfserr == nfserr_isdir) 2319 return nfserr_inval; 2320 if (nfserr) 2321 return nfserr; 2322 2323 WRITE32(maxcount); 2324 ADJUST_ARGS(); 2325 resp->xbuf->head[0].iov_len = (char*)p 2326 - (char*)resp->xbuf->head[0].iov_base; 2327 resp->xbuf->page_len = maxcount; 2328 2329 /* Use rest of head for padding and remaining ops: */ 2330 resp->xbuf->tail[0].iov_base = p; 2331 resp->xbuf->tail[0].iov_len = 0; 2332 if (maxcount&3) { 2333 RESERVE_SPACE(4); 2334 WRITE32(0); 2335 resp->xbuf->tail[0].iov_base += maxcount&3; 2336 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2337 ADJUST_ARGS(); 2338 } 2339 return 0; 2340 } 2341 2342 static __be32 2343 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir) 2344 { 2345 int maxcount; 2346 loff_t offset; 2347 __be32 *page, *savep, *tailbase; 2348 ENCODE_HEAD; 2349 2350 if (nfserr) 2351 return nfserr; 2352 if (resp->xbuf->page_len) 2353 return nfserr_resource; 2354 2355 RESERVE_SPACE(8); /* verifier */ 2356 savep = p; 2357 2358 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ 2359 WRITE32(0); 2360 WRITE32(0); 2361 ADJUST_ARGS(); 2362 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 2363 tailbase = p; 2364 2365 maxcount = PAGE_SIZE; 2366 if (maxcount > readdir->rd_maxcount) 2367 maxcount = readdir->rd_maxcount; 2368 2369 /* 2370 * Convert from bytes to words, account for the two words already 2371 * written, make sure to leave two words at the end for the next 2372 * pointer and eof field. 2373 */ 2374 maxcount = (maxcount >> 2) - 4; 2375 if (maxcount < 0) { 2376 nfserr = nfserr_toosmall; 2377 goto err_no_verf; 2378 } 2379 2380 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2381 readdir->common.err = 0; 2382 readdir->buflen = maxcount; 2383 readdir->buffer = page; 2384 readdir->offset = NULL; 2385 2386 offset = readdir->rd_cookie; 2387 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, 2388 &offset, 2389 &readdir->common, nfsd4_encode_dirent); 2390 if (nfserr == nfs_ok && 2391 readdir->common.err == nfserr_toosmall && 2392 readdir->buffer == page) 2393 nfserr = nfserr_toosmall; 2394 if (nfserr == nfserr_symlink) 2395 nfserr = nfserr_notdir; 2396 if (nfserr) 2397 goto err_no_verf; 2398 2399 if (readdir->offset) 2400 xdr_encode_hyper(readdir->offset, offset); 2401 2402 p = readdir->buffer; 2403 *p++ = 0; /* no more entries */ 2404 *p++ = htonl(readdir->common.err == nfserr_eof); 2405 resp->xbuf->page_len = ((char*)p) - (char*)page_address( 2406 resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); 2407 2408 /* Use rest of head for padding and remaining ops: */ 2409 resp->xbuf->tail[0].iov_base = tailbase; 2410 resp->xbuf->tail[0].iov_len = 0; 2411 resp->p = resp->xbuf->tail[0].iov_base; 2412 resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; 2413 2414 return 0; 2415 err_no_verf: 2416 p = savep; 2417 ADJUST_ARGS(); 2418 return nfserr; 2419 } 2420 2421 static __be32 2422 nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) 2423 { 2424 ENCODE_HEAD; 2425 2426 if (!nfserr) { 2427 RESERVE_SPACE(20); 2428 WRITECINFO(remove->rm_cinfo); 2429 ADJUST_ARGS(); 2430 } 2431 return nfserr; 2432 } 2433 2434 static __be32 2435 nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) 2436 { 2437 ENCODE_HEAD; 2438 2439 if (!nfserr) { 2440 RESERVE_SPACE(40); 2441 WRITECINFO(rename->rn_sinfo); 2442 WRITECINFO(rename->rn_tinfo); 2443 ADJUST_ARGS(); 2444 } 2445 return nfserr; 2446 } 2447 2448 static __be32 2449 nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, 2450 struct nfsd4_secinfo *secinfo) 2451 { 2452 int i = 0; 2453 struct svc_export *exp = secinfo->si_exp; 2454 u32 nflavs; 2455 struct exp_flavor_info *flavs; 2456 struct exp_flavor_info def_flavs[2]; 2457 ENCODE_HEAD; 2458 2459 if (nfserr) 2460 goto out; 2461 if (exp->ex_nflavors) { 2462 flavs = exp->ex_flavors; 2463 nflavs = exp->ex_nflavors; 2464 } else { /* Handling of some defaults in absence of real secinfo: */ 2465 flavs = def_flavs; 2466 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) { 2467 nflavs = 2; 2468 flavs[0].pseudoflavor = RPC_AUTH_UNIX; 2469 flavs[1].pseudoflavor = RPC_AUTH_NULL; 2470 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) { 2471 nflavs = 1; 2472 flavs[0].pseudoflavor 2473 = svcauth_gss_flavor(exp->ex_client); 2474 } else { 2475 nflavs = 1; 2476 flavs[0].pseudoflavor 2477 = exp->ex_client->flavour->flavour; 2478 } 2479 } 2480 2481 RESERVE_SPACE(4); 2482 WRITE32(nflavs); 2483 ADJUST_ARGS(); 2484 for (i = 0; i < nflavs; i++) { 2485 u32 flav = flavs[i].pseudoflavor; 2486 struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); 2487 2488 if (gm) { 2489 RESERVE_SPACE(4); 2490 WRITE32(RPC_AUTH_GSS); 2491 ADJUST_ARGS(); 2492 RESERVE_SPACE(4 + gm->gm_oid.len); 2493 WRITE32(gm->gm_oid.len); 2494 WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); 2495 ADJUST_ARGS(); 2496 RESERVE_SPACE(4); 2497 WRITE32(0); /* qop */ 2498 ADJUST_ARGS(); 2499 RESERVE_SPACE(4); 2500 WRITE32(gss_pseudoflavor_to_service(gm, flav)); 2501 ADJUST_ARGS(); 2502 gss_mech_put(gm); 2503 } else { 2504 RESERVE_SPACE(4); 2505 WRITE32(flav); 2506 ADJUST_ARGS(); 2507 } 2508 } 2509 out: 2510 if (exp) 2511 exp_put(exp); 2512 return nfserr; 2513 } 2514 2515 /* 2516 * The SETATTR encode routine is special -- it always encodes a bitmap, 2517 * regardless of the error status. 2518 */ 2519 static __be32 2520 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) 2521 { 2522 ENCODE_HEAD; 2523 2524 RESERVE_SPACE(12); 2525 if (nfserr) { 2526 WRITE32(2); 2527 WRITE32(0); 2528 WRITE32(0); 2529 } 2530 else { 2531 WRITE32(2); 2532 WRITE32(setattr->sa_bmval[0]); 2533 WRITE32(setattr->sa_bmval[1]); 2534 } 2535 ADJUST_ARGS(); 2536 return nfserr; 2537 } 2538 2539 static __be32 2540 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) 2541 { 2542 ENCODE_HEAD; 2543 2544 if (!nfserr) { 2545 RESERVE_SPACE(8 + sizeof(nfs4_verifier)); 2546 WRITEMEM(&scd->se_clientid, 8); 2547 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); 2548 ADJUST_ARGS(); 2549 } 2550 else if (nfserr == nfserr_clid_inuse) { 2551 RESERVE_SPACE(8); 2552 WRITE32(0); 2553 WRITE32(0); 2554 ADJUST_ARGS(); 2555 } 2556 return nfserr; 2557 } 2558 2559 static __be32 2560 nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) 2561 { 2562 ENCODE_HEAD; 2563 2564 if (!nfserr) { 2565 RESERVE_SPACE(16); 2566 WRITE32(write->wr_bytes_written); 2567 WRITE32(write->wr_how_written); 2568 WRITEMEM(write->wr_verifier.data, 8); 2569 ADJUST_ARGS(); 2570 } 2571 return nfserr; 2572 } 2573 2574 static __be32 2575 nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) 2576 { 2577 return nfserr; 2578 } 2579 2580 typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *); 2581 2582 static nfsd4_enc nfsd4_enc_ops[] = { 2583 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access, 2584 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close, 2585 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit, 2586 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create, 2587 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop, 2588 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop, 2589 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr, 2590 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh, 2591 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link, 2592 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock, 2593 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt, 2594 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku, 2595 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop, 2596 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop, 2597 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop, 2598 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open, 2599 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop, 2600 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm, 2601 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade, 2602 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop, 2603 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop, 2604 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop, 2605 [OP_READ] = (nfsd4_enc)nfsd4_encode_read, 2606 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir, 2607 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink, 2608 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove, 2609 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename, 2610 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop, 2611 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop, 2612 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop, 2613 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo, 2614 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr, 2615 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid, 2616 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop, 2617 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop, 2618 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write, 2619 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop, 2620 }; 2621 2622 void 2623 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 2624 { 2625 __be32 *statp; 2626 ENCODE_HEAD; 2627 2628 RESERVE_SPACE(8); 2629 WRITE32(op->opnum); 2630 statp = p++; /* to be backfilled at the end */ 2631 ADJUST_ARGS(); 2632 2633 if (op->opnum == OP_ILLEGAL) 2634 goto status; 2635 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || 2636 !nfsd4_enc_ops[op->opnum]); 2637 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); 2638 status: 2639 /* 2640 * Note: We write the status directly, instead of using WRITE32(), 2641 * since it is already in network byte order. 2642 */ 2643 *statp = op->status; 2644 } 2645 2646 /* 2647 * Encode the reply stored in the stateowner reply cache 2648 * 2649 * XDR note: do not encode rp->rp_buflen: the buffer contains the 2650 * previously sent already encoded operation. 2651 * 2652 * called with nfs4_lock_state() held 2653 */ 2654 void 2655 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 2656 { 2657 ENCODE_HEAD; 2658 struct nfs4_replay *rp = op->replay; 2659 2660 BUG_ON(!rp); 2661 2662 RESERVE_SPACE(8); 2663 WRITE32(op->opnum); 2664 *p++ = rp->rp_status; /* already xdr'ed */ 2665 ADJUST_ARGS(); 2666 2667 RESERVE_SPACE(rp->rp_buflen); 2668 WRITEMEM(rp->rp_buf, rp->rp_buflen); 2669 ADJUST_ARGS(); 2670 } 2671 2672 /* 2673 * END OF "GENERIC" ENCODE ROUTINES. 2674 */ 2675 2676 int 2677 nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 2678 { 2679 return xdr_ressize_check(rqstp, p); 2680 } 2681 2682 void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) 2683 { 2684 if (args->ops != args->iops) { 2685 kfree(args->ops); 2686 args->ops = args->iops; 2687 } 2688 kfree(args->tmpp); 2689 args->tmpp = NULL; 2690 while (args->to_free) { 2691 struct tmpbuf *tb = args->to_free; 2692 args->to_free = tb->next; 2693 tb->release(tb->buf); 2694 kfree(tb); 2695 } 2696 } 2697 2698 int 2699 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) 2700 { 2701 __be32 status; 2702 2703 args->p = p; 2704 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; 2705 args->pagelist = rqstp->rq_arg.pages; 2706 args->pagelen = rqstp->rq_arg.page_len; 2707 args->tmpp = NULL; 2708 args->to_free = NULL; 2709 args->ops = args->iops; 2710 args->rqstp = rqstp; 2711 2712 status = nfsd4_decode_compound(args); 2713 if (status) { 2714 nfsd4_release_compoundargs(args); 2715 } 2716 return !status; 2717 } 2718 2719 int 2720 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp) 2721 { 2722 /* 2723 * All that remains is to write the tag and operation count... 2724 */ 2725 struct kvec *iov; 2726 p = resp->tagp; 2727 *p++ = htonl(resp->taglen); 2728 memcpy(p, resp->tag, resp->taglen); 2729 p += XDR_QUADLEN(resp->taglen); 2730 *p++ = htonl(resp->opcnt); 2731 2732 if (rqstp->rq_res.page_len) 2733 iov = &rqstp->rq_res.tail[0]; 2734 else 2735 iov = &rqstp->rq_res.head[0]; 2736 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 2737 BUG_ON(iov->iov_len > PAGE_SIZE); 2738 return 1; 2739 } 2740 2741 /* 2742 * Local variables: 2743 * c-basic-offset: 8 2744 * End: 2745 */ 2746