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