Reactos
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 3679 lines 91 kB view raw
1/* NFSv4.1 client for Windows 2 * Copyright � 2012 The Regents of the University of Michigan 3 * 4 * Olga Kornievskaia <aglo@umich.edu> 5 * Casey Bodley <cbodley@umich.edu> 6 * 7 * This library is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU Lesser General Public License as published by 9 * the Free Software Foundation; either version 2.1 of the License, or (at 10 * your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, but 13 * without any warranty; without even the implied warranty of merchantability 14 * or fitness for a particular purpose. See the GNU Lesser General Public 15 * License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 */ 21 22#include <windows.h> 23#include <strsafe.h> 24 25#include "nfs41_compound.h" 26#include "nfs41_ops.h" 27#include "nfs41_xdr.h" 28#include "util.h" 29#include "daemon_debug.h" 30#include "rpc/rpc.h" 31 32static bool_t encode_file_attrs( 33 fattr4 *attrs, 34 nfs41_file_info *info); 35 36static __inline int unexpected_op(uint32_t op, uint32_t expected) 37{ 38 if (op == expected) 39 return 0; 40 41 eprintf("Op table mismatch. Got %s (%d), expected %s (%d).\n", 42 nfs_opnum_to_string(op), op, 43 nfs_opnum_to_string(expected), expected); 44 return 1; 45} 46 47/* typedef uint32_t bitmap4<> */ 48bool_t xdr_bitmap4( 49 XDR *xdr, 50 bitmap4 *bitmap) 51{ 52 uint32_t i; 53 54 if (xdr->x_op == XDR_ENCODE) { 55 if (bitmap->count > 3) { 56 eprintf("encode_bitmap4: count (%d) must be <= 3\n", 57 bitmap->count); 58 return FALSE; 59 } 60 if (!xdr_u_int32_t(xdr, &bitmap->count)) 61 return FALSE; 62 63 for (i = 0; i < bitmap->count; i++) 64 if (!xdr_u_int32_t(xdr, &bitmap->arr[i])) 65 return FALSE; 66 67 } else if (xdr->x_op == XDR_DECODE) { 68 if (!xdr_u_int32_t(xdr, &bitmap->count)) 69 return FALSE; 70 if (bitmap->count > 3) { 71 eprintf("decode_bitmap4: count (%d) must be <= 3\n", 72 bitmap->count); 73 return FALSE; 74 } 75 76 for (i = 0; i < bitmap->count; i++) 77 if (!xdr_u_int32_t(xdr, &bitmap->arr[i])) 78 return FALSE; 79 } else 80 return FALSE; 81 82 return TRUE; 83} 84 85/* nfstime4 */ 86static bool_t xdr_nfstime4( 87 XDR *xdr, 88 nfstime4 *nt) 89{ 90 if (!xdr_hyper(xdr, &nt->seconds)) 91 return FALSE; 92 93 return xdr_u_int32_t(xdr, &nt->nseconds); 94} 95 96 97/* settime4 */ 98static uint32_t settime_how( 99 nfstime4 *newtime, 100 const nfstime4 *time_delta) 101{ 102 nfstime4 current; 103 get_nfs_time(&current); 104 /* get the absolute difference between current and newtime */ 105 nfstime_diff(&current, newtime, &current); 106 nfstime_abs(&current, &current); 107 /* compare the difference with time_delta */ 108 nfstime_diff(time_delta, &current, &current); 109 /* use client time if diff > delta (i.e. time_delta - current < 0) */ 110 return current.seconds < 0 ? SET_TO_CLIENT_TIME4 : SET_TO_SERVER_TIME4; 111} 112 113static bool_t xdr_settime4( 114 XDR *xdr, 115 nfstime4 *nt, 116 const nfstime4 *time_delta) 117{ 118 uint32_t how = settime_how(nt, time_delta); 119 120 if (xdr->x_op != XDR_ENCODE) /* not used for decode */ 121 return FALSE; 122 123 if (!xdr_u_int32_t(xdr, &how)) 124 return FALSE; 125 126 if (how == SET_TO_CLIENT_TIME4) 127 return xdr_nfstime4(xdr, nt); 128 129 return TRUE; 130} 131 132/* stateid4 */ 133static bool_t xdr_stateid4( 134 XDR *xdr, 135 stateid4 *si) 136{ 137 if (!xdr_u_int32_t(xdr, &si->seqid)) 138 return FALSE; 139 140 return xdr_opaque(xdr, (char *)si->other, NFS4_STATEID_OTHER); 141} 142 143/* fattr4 */ 144bool_t xdr_fattr4( 145 XDR *xdr, 146 fattr4 *fattr) 147{ 148 unsigned char *attr_vals = fattr->attr_vals; 149 150 if (!xdr_bitmap4(xdr, &fattr->attrmask)) 151 return FALSE; 152 153 return xdr_bytes(xdr, (char **)&attr_vals, &fattr->attr_vals_len, NFS4_OPAQUE_LIMIT); 154} 155 156/* nfs41_fh */ 157static bool_t xdr_fh( 158 XDR *xdr, 159 nfs41_fh *fh) 160{ 161 unsigned char *pfh = fh->fh; 162 return xdr_bytes(xdr, (char **)&pfh, &fh->len, NFS4_FHSIZE); 163} 164 165/* nfs41_fsid */ 166static bool_t xdr_fsid( 167 XDR *xdr, 168 nfs41_fsid *fsid) 169{ 170 if (!xdr_u_hyper(xdr, &fsid->major)) 171 return FALSE; 172 173 return xdr_u_hyper(xdr, &fsid->minor); 174} 175 176 177/* nfs41_component */ 178static bool_t encode_component( 179 XDR *xdr, 180 const nfs41_component *component) 181{ 182 uint32_t len = component->len; 183 return xdr_bytes(xdr, (char **)&component->name, &len, NFS4_OPAQUE_LIMIT); 184} 185 186static bool_t decode_component( 187 XDR *xdr, 188 nfs41_component *component) 189{ 190 bool_t result; 191 uint32_t len; 192 193 result = xdr_bytes(xdr, (char **)&component->name, &len, NFS4_OPAQUE_LIMIT); 194 component->len = (result == FALSE) ? 0 : (unsigned short)len; 195 return result; 196} 197 198 199/* state_owner4 */ 200static bool_t xdr_state_owner4( 201 XDR *xdr, 202 state_owner4 *so) 203{ 204 u_quad_t clientid = 0; 205 unsigned char *owner = so->owner; 206 207 /* 18.16.3. "The client can set the clientid field to any value and 208 * the server MUST ignore it. Instead the server MUST derive the 209 * client ID from the session ID of the SEQUENCE operation of the 210 * COMPOUND request. */ 211 if (xdr->x_op == XDR_ENCODE) { 212 if (!xdr_u_hyper(xdr, &clientid)) /* clientid = 0 */ 213 return FALSE; 214 } else if (xdr->x_op == XDR_DECODE) { 215 if (!xdr_u_hyper(xdr, &clientid)) 216 return FALSE; 217 } else return FALSE; 218 219 return xdr_bytes(xdr, (char **)&owner, &so->owner_len, NFS4_OPAQUE_LIMIT); 220} 221 222static bool_t xdr_layout_types( 223 XDR *xdr, 224 uint32_t *layout_type) 225{ 226 u_int32_t i, count, type; 227 228 if (xdr->x_op != XDR_DECODE) { 229 eprintf("xdr_layout_types: xdr->x_op is not XDR_DECODE! " 230 "x_op %d not supported.\n", xdr->x_op); 231 return FALSE; 232 } 233 234 *layout_type = 0; 235 236 if (!xdr_u_int32_t(xdr, &count)) 237 return FALSE; 238 239 for (i = 0; i < count; i++) { 240 if (!xdr_u_int32_t(xdr, &type)) 241 return FALSE; 242 243 *layout_type |= 1 << (type - 1); 244 } 245 return TRUE; 246} 247 248static bool_t xdr_threshold_item( 249 XDR *xdr, 250 threshold_item4 *item) 251{ 252 bitmap4 bitmap; 253 254 if (!xdr_u_int32_t(xdr, &item->type)) 255 return FALSE; 256 257 if (!xdr_bitmap4(xdr, &bitmap)) 258 return FALSE; 259 260 if (!xdr_u_int32_t(xdr, &bitmap.count)) 261 return FALSE; 262 263 if (bitmap.count) { 264 if (bitmap.arr[0] & 0x1 && !xdr_u_hyper(xdr, &item->hints[0])) 265 return FALSE; 266 if (bitmap.arr[0] & 0x2 && !xdr_u_hyper(xdr, &item->hints[1])) 267 return FALSE; 268 if (bitmap.arr[0] & 0x4 && !xdr_u_hyper(xdr, &item->hints[2])) 269 return FALSE; 270 if (bitmap.arr[0] & 0x8 && !xdr_u_hyper(xdr, &item->hints[3])) 271 return FALSE; 272 } 273 return TRUE; 274} 275 276static bool_t xdr_mdsthreshold( 277 XDR *xdr, 278 mdsthreshold4 *mdsthreshold) 279{ 280 uint32_t i; 281 282 if (!xdr_u_int32_t(xdr, &mdsthreshold->count)) 283 return FALSE; 284 285 if (mdsthreshold->count > MAX_MDSTHRESHOLD_ITEMS) 286 return FALSE; 287 288 for (i = 0; i < mdsthreshold->count; i++) 289 if (!xdr_threshold_item(xdr, &mdsthreshold->items[i])) 290 return FALSE; 291 return TRUE; 292} 293 294static bool_t xdr_nfsace4( 295 XDR *xdr, 296 nfsace4 *ace) 297{ 298 char *who = ace->who; 299 300 if (!xdr_u_int32_t(xdr, &ace->acetype)) 301 return FALSE; 302 303 if (!xdr_u_int32_t(xdr, &ace->aceflag)) 304 return FALSE; 305 306 if (!xdr_u_int32_t(xdr, &ace->acemask)) 307 return FALSE; 308 309 /* 'who' is a static array, so don't try to free it */ 310 if (xdr->x_op == XDR_FREE) 311 return TRUE; 312 313 return xdr_string(xdr, &who, NFS4_OPAQUE_LIMIT); 314} 315 316static bool_t xdr_nfsdacl41( 317 XDR *xdr, 318 nfsacl41 *acl) 319{ 320 if (!xdr_u_int32_t(xdr, &acl->flag)) 321 return FALSE; 322 323 return xdr_array(xdr, (char**)&acl->aces, &acl->count, 324 32, sizeof(nfsace4), (xdrproc_t)xdr_nfsace4); 325} 326 327static bool_t xdr_nfsacl41( 328 XDR *xdr, 329 nfsacl41 *acl) 330{ 331 return xdr_array(xdr, (char**)&acl->aces, &acl->count, 332 32, sizeof(nfsace4), (xdrproc_t)xdr_nfsace4); 333} 334 335void nfsacl41_free(nfsacl41 *acl) 336{ 337 XDR xdr = { XDR_FREE }; 338 xdr_nfsacl41(&xdr, acl); 339} 340 341/* pathname4 342 * decode a variable array of components into a nfs41_abs_path */ 343static bool_t decode_pathname4( 344 XDR *xdr, 345 nfs41_abs_path *path) 346{ 347 char *pos; 348 u_int32_t i, count, len, remaining; 349 350 /* decode the number of components */ 351 if (!xdr_u_int32_t(xdr, &count)) 352 return FALSE; 353 354 pos = (char *)path->path; 355 remaining = NFS41_MAX_PATH_LEN; 356 357 /* decode each component */ 358 for (i = 0; i < count; i++) { 359 len = remaining; 360 if (!xdr_bytes(xdr, (char **)&pos, &len, NFS41_MAX_PATH_LEN)) 361 return FALSE; 362 remaining -= len; 363 pos += len; 364 365 if (i < count-1) { /* add a \ between components */ 366 if (remaining < 1) 367 return FALSE; 368 *pos++ = '\\'; 369 remaining--; 370 } 371 } 372 path->len = (unsigned short)(NFS41_MAX_PATH_LEN - remaining); 373 return TRUE; 374} 375 376/* fs_location4 */ 377static bool_t decode_fs_location4( 378 XDR *xdr, 379 fs_location4 *location) 380{ 381 fs_location_server *arr; 382 char *address; 383 u_int32_t i, count, len; 384 385 /* decode the number of servers */ 386 if (!xdr_u_int32_t(xdr, &count)) 387 return FALSE; 388 389 /* allocate the fs_location_server array */ 390 if (count == 0) { 391 free(location->servers); 392 arr = NULL; 393 } else if (count != location->server_count) { 394 arr = realloc(location->servers, count * sizeof(fs_location_server)); 395 if (arr == NULL) 396 return FALSE; 397 ZeroMemory(arr, count * sizeof(fs_location_server)); 398 } else { 399 arr = location->servers; 400 } 401 402 location->servers = arr; 403 location->server_count = count; 404 405 for (i = 0; i < count; i++) { 406 len = NFS41_HOSTNAME_LEN; 407 address = arr[i].address; 408 if (!xdr_bytes(xdr, &address, &len, NFS41_HOSTNAME_LEN)) { 409 free(arr); 410 return FALSE; 411 } 412 arr[i].address[len] = '\0'; 413 } 414 415 return decode_pathname4(xdr, &location->path); 416} 417 418/* fs_locations4 */ 419static bool_t decode_fs_locations4( 420 XDR *xdr, 421 fs_locations4 *locations) 422{ 423 u_int32_t i, count; 424 fs_location4 *arr; 425 426 if (!decode_pathname4(xdr, &locations->path)) 427 return FALSE; 428 429 if (!xdr_u_int32_t(xdr, &count)) 430 return FALSE; 431 432 /* allocate the fs_location array */ 433 if (count == 0) { 434 free(locations->locations); 435 arr = NULL; 436 } else if (count != locations->location_count) { 437 arr = realloc(locations->locations, count * sizeof(fs_location4)); 438 if (arr == NULL) 439 return FALSE; 440 ZeroMemory(arr, count * sizeof(fs_location4)); 441 } else { 442 arr = locations->locations; 443 } 444 445 locations->locations = arr; 446 locations->location_count = count; 447 448 for (i = 0; i < count; i++) { 449 if (!decode_fs_location4(xdr, &arr[i])) { 450 free(arr); 451 return FALSE; 452 } 453 } 454 return TRUE; 455} 456 457/* 458 * OP_EXCHANGE_ID 459 */ 460static bool_t xdr_client_owner4( 461 XDR *xdr, 462 client_owner4 *co) 463{ 464 unsigned char *co_ownerid = co->co_ownerid; 465 if (!xdr_opaque(xdr, (char *)&co->co_verifier[0], NFS4_VERIFIER_SIZE)) 466 return FALSE; 467 468 return xdr_bytes(xdr, (char **)&co_ownerid, &co->co_ownerid_len, NFS4_OPAQUE_LIMIT); 469} 470 471#if 0 472static bool_t encode_state_protect_ops4( 473 XDR *xdr, 474 state_protect_ops4 *spo) 475{ 476 if (!xdr_bitmap4(xdr, &spo->spo_must_enforce)) 477 return FALSE; 478 479 return xdr_bitmap4(xdr, &spo->spo_must_allow); 480} 481 482static bool_t encode_ssv_sp_parms4( 483 XDR *xdr, 484 ssv_sp_parms4 *spp) 485{ 486 if (!encode_state_protect_ops4(xdr, &spp->ssp_ops)) 487 return FALSE; 488 489 if (!xdr_bytes(xdr, &spp->ssp_hash_algs, 490 &spp->ssp_hash_algs_len, NFS4_OPAQUE_LIMIT)) 491 return FALSE; 492 493 if (!xdr_bytes(xdr, &spp->ssp_encr_algs, 494 &spp->ssp_encr_algs_len, NFS4_OPAQUE_LIMIT)) 495 return FALSE; 496 497 if (!xdr_u_int32_t(xdr, &spp->ssp_window)) 498 return FALSE; 499 500 return xdr_u_int32_t(xdr, &spp->ssp_num_gss_handles); 501} 502#endif 503 504static bool_t xdr_state_protect4_a( 505 XDR *xdr, 506 state_protect4_a *spa) 507{ 508 bool_t result = TRUE; 509 510 if (!xdr_u_int32_t(xdr, (u_int32_t *)&spa->spa_how)) 511 return FALSE; 512 513 switch (spa->spa_how) 514 { 515 case SP4_NONE: 516 break; 517#if 0 518 case SP4_MACH_CRED: 519 result = xdr_state_protect_ops4(xdr, &spa->u.spa_mach_ops); 520 break; 521 case SP4_SSV: 522 result = xdr_ssv_sp_parms4(xdr, &spa->u.spa_ssv_parms); 523 break; 524#endif 525 default: 526 eprintf("encode_state_protect4_a: state protect " 527 "type %d not supported.\n", spa->spa_how); 528 result = FALSE; 529 break; 530 } 531 return result; 532} 533 534static bool_t xdr_nfs_impl_id4( 535 XDR *xdr, 536 nfs_impl_id4 *nii) 537{ 538 unsigned char *nii_domain = nii->nii_domain; 539 unsigned char *nii_name = nii->nii_name; 540 541 if (!xdr_bytes(xdr, (char **)&nii_domain, &nii->nii_domain_len, NFS4_OPAQUE_LIMIT)) 542 return FALSE; 543 544 if (!xdr_bytes(xdr, (char **)&nii_name, &nii->nii_name_len, NFS4_OPAQUE_LIMIT)) 545 return FALSE; 546 547 return xdr_nfstime4(xdr, &nii->nii_date); 548} 549 550 551static bool_t encode_op_exchange_id( 552 XDR *xdr, 553 nfs_argop4 *argop) 554{ 555 uint32_t zero = 0; 556 uint32_t one = 1; 557 558 nfs41_exchange_id_args *args = (nfs41_exchange_id_args*)argop->arg; 559 560 if (unexpected_op(argop->op, OP_EXCHANGE_ID)) 561 return FALSE; 562 563 if (!xdr_client_owner4(xdr, args->eia_clientowner)) 564 return FALSE; 565 566 if (!xdr_u_int32_t(xdr, &args->eia_flags)) 567 return FALSE; 568 569 if (!xdr_state_protect4_a(xdr, &args->eia_state_protect)) 570 return FALSE; 571 572 if (args->eia_client_impl_id) 573 { 574 if (!xdr_u_int32_t(xdr, &one)) 575 return FALSE; 576 return xdr_nfs_impl_id4(xdr, args->eia_client_impl_id); 577 } 578 else 579 return xdr_u_int32_t(xdr, &zero); 580} 581 582#if 0 583 584static bool_t decode_state_protect_ops4( 585 XDR *xdr, 586 state_protect_ops4 *spo) 587{ 588 if (!xdr_bitmap4(xdr, &spo->spo_must_enforce)) 589 return FALSE; 590 591 return xdr_bitmap4(xdr, &spo->spo_must_allow); 592} 593 594static bool_t decode_ssv_prot_info4( 595 XDR *xdr, 596 ssv_prot_info4 *spi) 597{ 598/* uint32_t i; */ 599 600 if (!decode_state_protect_ops4(xdr, &spi->spi_ops)) 601 return FALSE; 602 603 if (!xdr_u_int32_t(xdr, &spi->spi_hash_alg)) 604 return FALSE; 605 606 if (!xdr_u_int32_t(xdr, &spi->spi_encr_alg)) 607 return FALSE; 608 609 if (!xdr_u_int32_t(xdr, &spi->spi_ssv_len)) 610 return FALSE; 611 612 if (!xdr_u_int32_t(xdr, &spi->spi_window)) 613 return FALSE; 614 615/* TODO: spi->spi_handles */ 616 return xdr_u_int32_t(xdr, 0); 617 /* 618 if (!xdr_u_int32_t(xdr, &spi->spi_handles.count)) 619 return FALSE; 620 621 for (i = 0; i < spi->spi_handles.count; i++) 622 if (!xdr_opaque(xdr, &spi->spi_handles.arr[i]) 623 return FALSE; 624*/ 625 return TRUE; 626} 627#endif 628 629static bool_t xdr_state_protect4_r( 630 XDR *xdr, 631 state_protect4_r *spr) 632{ 633 bool_t result = TRUE; 634 635 if (!xdr_u_int32_t(xdr, (uint32_t *)&spr->spr_how)) 636 return FALSE; 637 638 switch (spr->spr_how) 639 { 640 case SP4_NONE: 641 break; 642#if 0 643 case SP4_MACH_CRED: 644 result = decode_state_protect_ops4(xdr, &spr->u.spr_mach_ops); 645 break; 646 case SP4_SSV: 647 result = decode_ssv_prot_info4(xdr, &spr->u.spr_ssv_info); 648 break; 649#endif 650 default: 651 eprintf("decode_state_protect4_r: state protect " 652 "type %d not supported.\n", spr->spr_how); 653 result = FALSE; 654 break; 655 } 656 return result; 657} 658 659static bool_t xdr_server_owner4( 660 XDR *xdr, 661 server_owner4 *so) 662{ 663 char *so_major_id = so->so_major_id; 664 665 if (!xdr_u_hyper(xdr, &so->so_minor_id)) 666 return FALSE; 667 668 return xdr_bytes(xdr, (char **)&so_major_id, 669 &so->so_major_id_len, NFS4_OPAQUE_LIMIT); 670} 671 672static bool_t decode_op_exchange_id( 673 XDR *xdr, 674 nfs_resop4 *resop) 675{ 676 nfs41_exchange_id_res *res = (nfs41_exchange_id_res*)resop->res; 677 char *server_scope = (char *)res->server_scope; 678 679 if (unexpected_op(resop->op, OP_EXCHANGE_ID)) 680 return FALSE; 681 682 if (!xdr_u_int32_t(xdr, &res->status)) 683 return FALSE; 684 685 if (res->status != NFS4_OK) 686 return TRUE; 687 688 if (!xdr_u_hyper(xdr, &res->clientid)) 689 return FALSE; 690 691 if (!xdr_u_int32_t(xdr, &res->sequenceid)) 692 return FALSE; 693 694 if (!xdr_u_int32_t(xdr, &res->flags)) 695 return FALSE; 696 697 if (!xdr_state_protect4_r(xdr, &res->state_protect)) 698 return FALSE; 699 700 if (!xdr_server_owner4(xdr, &res->server_owner)) 701 return FALSE; 702 703 return xdr_bytes(xdr, &server_scope, 704 &res->server_scope_len, NFS4_OPAQUE_LIMIT); 705} 706 707/* 708 * OP_CREATE_SESSION 709 */ 710static bool_t xdr_channel_attrs4( 711 XDR *xdr, 712 nfs41_channel_attrs *attrs) 713{ 714 uint32_t zero = 0; 715 uint32_t one = 1; 716 717 /* count4 ca_headerpadsize */ 718 if (!xdr_u_int32_t(xdr, &attrs->ca_headerpadsize)) 719 return FALSE; 720 721 /* count4 ca_maxrequestsize */ 722 if (!xdr_u_int32_t(xdr, &attrs->ca_maxrequestsize)) 723 return FALSE; 724 725 /* count4 ca_maxresponsesize */ 726 if (!xdr_u_int32_t(xdr, &attrs->ca_maxresponsesize)) 727 return FALSE; 728 729 /* count4 ca_maxresponsesize_cached */ 730 if (!xdr_u_int32_t(xdr, &attrs->ca_maxresponsesize_cached)) 731 return FALSE; 732 733 /* count4 ca_maxoperations */ 734 if (!xdr_u_int32_t(xdr, &attrs->ca_maxoperations)) 735 return FALSE; 736 737 /* count4 ca_maxrequests */ 738 if (!xdr_u_int32_t(xdr, &attrs->ca_maxrequests)) 739 return FALSE; 740 741 if (xdr->x_op == XDR_ENCODE) { 742 /* uint32_t ca_rdma_ird<1> */ 743 if (attrs->ca_rdma_ird) 744 { 745 if (!xdr_u_int32_t(xdr, &one)) 746 return FALSE; 747 return xdr_u_int32_t(xdr, attrs->ca_rdma_ird); 748 } 749 else { 750 return xdr_u_int32_t(xdr, &zero); 751 } 752 } 753 else if (xdr->x_op == XDR_DECODE) { 754#if 0 755 u_int32_t count; 756 /* uint32_t ca_rdma_ird<1> */ 757 if (!xdr_u_int32_t(xdr, &count)) 758 return FALSE; 759 if (count > 1) 760 return FALSE; 761 if (count) 762 return xdr_u_int32_t(xdr, attrs->ca_rdma_ird); 763 else 764#endif 765 return TRUE; 766 } 767 else { 768 eprintf("%s: xdr->x_op %d not supported.\n", 769 "xdr_channel_attrs4", xdr->x_op); 770 return FALSE; 771 } 772} 773 774static bool_t encode_backchannel_sec_parms( 775 XDR *xdr, 776 nfs41_callback_secparms *args) 777{ 778 uint32_t zero = 0; 779 780 if (!xdr_u_int32_t(xdr, &args->type)) 781 return FALSE; 782 783 switch (args->type) { 784 case AUTH_NONE: return TRUE; 785 case AUTH_SYS: 786 if (!xdr_u_int32_t(xdr, &args->u.auth_sys.stamp)) 787 return FALSE; 788 if (!xdr_string(xdr, &args->u.auth_sys.machinename, NI_MAXHOST)) 789 return FALSE; 790 return xdr_u_int32_t(xdr, &zero) && xdr_u_int32_t(xdr, &zero) && 791 xdr_u_int32_t(xdr, &zero); 792 case RPCSEC_GSS: 793 default: 794 return FALSE; 795 } 796} 797 798static bool_t encode_op_create_session( 799 XDR *xdr, 800 nfs_argop4 *argop) 801{ 802 nfs41_create_session_args *args = (nfs41_create_session_args*)argop->arg; 803 nfs41_callback_secparms *cb_secparams = args->csa_cb_secparams; 804 uint32_t cb_count = 2; 805 806 if (unexpected_op(argop->op, OP_CREATE_SESSION)) 807 return FALSE; 808 809 /* clientid4 csa_clientid */ 810 if (!xdr_u_hyper(xdr, &args->csa_clientid)) 811 return FALSE; 812 813 /* sequenceid4 csa_sequence */ 814 if (!xdr_u_int32_t(xdr, &args->csa_sequence)) 815 return FALSE; 816 817 /* TODO: uint32_t csa_flags = 0 */ 818 if (!xdr_u_int32_t(xdr, &args->csa_flags)) 819 return FALSE; 820 821 /* channel_attrs4 csa_fore_chan_attrs */ 822 if (!xdr_channel_attrs4(xdr, &args->csa_fore_chan_attrs)) 823 return FALSE; 824 825 /* channel_attrs4 csa_back_chan_attrs */ 826 if (!xdr_channel_attrs4(xdr, &args->csa_back_chan_attrs)) 827 return FALSE; 828 829 /* TODO: uint32_t csa_cb_program = 1234 */ 830 if (!xdr_u_int32_t(xdr, &args->csa_cb_program)) 831 return FALSE; 832 833 return xdr_array(xdr, (char **)&cb_secparams, &cb_count, 834 3, sizeof(nfs41_callback_secparms), (xdrproc_t) encode_backchannel_sec_parms); 835} 836 837static bool_t decode_op_create_session( 838 XDR *xdr, 839 nfs_resop4 *resop) 840{ 841 uint32_t opstatus; 842 nfs41_create_session_res *res = (nfs41_create_session_res*)resop->res; 843 844 if (unexpected_op(resop->op, OP_CREATE_SESSION)) 845 return FALSE; 846 847 if (!xdr_u_int32_t(xdr, &opstatus)) 848 return FALSE; 849 850 if (opstatus != NFS4_OK) 851 return TRUE; 852 853 if (!xdr_opaque(xdr, (char *)res->csr_sessionid, NFS4_SESSIONID_SIZE)) 854 return FALSE; 855 856 /* sequenceid4 csr_sequence */ 857 if (!xdr_u_int32_t(xdr, &res->csr_sequence)) 858 return FALSE; 859 860 /* uint32_t csr_flags */ 861 if (!xdr_u_int32_t(xdr, &res->csr_flags)) 862 return FALSE; 863 864 /* channel_attrs4 csr_fore_chan_attrs */ 865 if (!xdr_channel_attrs4(xdr, res->csr_fore_chan_attrs)) 866 return FALSE; 867 868 /* channel_attrs4 csr_back_chan_attrs */ 869 return xdr_channel_attrs4(xdr, res->csr_back_chan_attrs); 870} 871 872 873/* 874 * OP_BIND_CONN_TO_SESSION 875 */ 876static bool_t encode_op_bind_conn_to_session( 877 XDR *xdr, 878 nfs_argop4 *argop) 879{ 880 uint32_t zero = 0; 881 882 nfs41_bind_conn_to_session_args *args = 883 (nfs41_bind_conn_to_session_args*)argop->arg; 884 885 if (unexpected_op(argop->op, OP_BIND_CONN_TO_SESSION)) 886 return FALSE; 887 888 if (!xdr_opaque(xdr, (char *)args->sessionid, NFS4_SESSIONID_SIZE)) 889 return FALSE; 890 891 if (!xdr_enum(xdr, (enum_t *)&args->dir)) 892 return FALSE; 893 894 return xdr_u_int32_t(xdr, &zero); /* bctsa_use_conn_in_rdma_mode = false */ 895} 896 897static bool_t decode_op_bind_conn_to_session( 898 XDR *xdr, 899 nfs_resop4 *resop) 900{ 901 unsigned char sessionid_ignored[NFS4_SESSIONID_SIZE]; 902 nfs41_bind_conn_to_session_res *res = 903 (nfs41_bind_conn_to_session_res*)resop->res; 904 bool_t use_rdma_ignored; 905 906 if (unexpected_op(resop->op, OP_BIND_CONN_TO_SESSION)) 907 return FALSE; 908 909 if (!xdr_enum(xdr, (enum_t *)&res->status)) 910 return FALSE; 911 912 if (res->status == NFS4_OK) { 913 if (!xdr_opaque(xdr, (char *)&sessionid_ignored, NFS4_SESSIONID_SIZE)) 914 return FALSE; 915 916 if (!xdr_enum(xdr, (enum_t *)&res->dir)) 917 return FALSE; 918 919 return xdr_bool(xdr, &use_rdma_ignored); 920 } 921 return TRUE; 922} 923 924 925/* 926 * OP_DESTROY_SESSION 927 */ 928static bool_t encode_op_destroy_session( 929 XDR *xdr, 930 nfs_argop4 *argop) 931{ 932 nfs41_destroy_session_args *args = (nfs41_destroy_session_args*)argop->arg; 933 934 if (unexpected_op(argop->op, OP_DESTROY_SESSION)) 935 return FALSE; 936 937 return xdr_opaque(xdr, (char *)args->dsa_sessionid, NFS4_SESSIONID_SIZE); 938} 939 940static bool_t decode_op_destroy_session( 941 XDR *xdr, 942 nfs_resop4 *resop) 943{ 944 nfs41_destroy_session_res *res = (nfs41_destroy_session_res*)resop->res; 945 946 if (unexpected_op(resop->op, OP_DESTROY_SESSION)) 947 return FALSE; 948 949 return xdr_u_int32_t(xdr, &res->dsr_status); 950} 951 952/* 953 * OP_DESTROY_CLIENTID 954 */ 955static bool_t encode_op_destroy_clientid( 956 XDR *xdr, 957 nfs_argop4 *argop) 958{ 959 nfs41_destroy_clientid_args *args = (nfs41_destroy_clientid_args*)argop->arg; 960 961 if (unexpected_op(argop->op, OP_DESTROY_CLIENTID)) 962 return FALSE; 963 964 return xdr_u_hyper(xdr, &args->dca_clientid); 965} 966 967static bool_t decode_op_destroy_clientid( 968 XDR *xdr, 969 nfs_resop4 *resop) 970{ 971 nfs41_destroy_clientid_res *res = (nfs41_destroy_clientid_res*)resop->res; 972 973 if (unexpected_op(resop->op, OP_DESTROY_CLIENTID)) 974 return FALSE; 975 976 return xdr_u_int32_t(xdr, &res->dcr_status); 977} 978 979 980/* 981 * OP_SEQUENCE 982 */ 983static bool_t encode_op_sequence( 984 XDR *xdr, 985 nfs_argop4 *argop) 986{ 987 nfs41_sequence_args *args = (nfs41_sequence_args*)argop->arg; 988 989 if (unexpected_op(argop->op, OP_SEQUENCE)) 990 return FALSE; 991 992 if (!xdr_opaque(xdr, (char *)args->sa_sessionid, NFS4_SESSIONID_SIZE)) 993 return FALSE; 994 995 if (!xdr_u_int32_t(xdr, &args->sa_sequenceid)) 996 return FALSE; 997 998 if (!xdr_u_int32_t(xdr, &args->sa_slotid)) 999 return FALSE; 1000 1001 if (!xdr_u_int32_t(xdr, &args->sa_highest_slotid)) 1002 return FALSE; 1003 1004 return xdr_bool(xdr, &args->sa_cachethis); 1005} 1006 1007static bool_t xdr_sequence_res_ok( 1008 XDR *xdr, 1009 nfs41_sequence_res_ok *res) 1010{ 1011 if (!xdr_opaque(xdr, (char *)res->sr_sessionid, NFS4_SESSIONID_SIZE)) 1012 return FALSE; 1013 1014 if (!xdr_u_int32_t(xdr, &res->sr_sequenceid)) 1015 return FALSE; 1016 1017 if (!xdr_u_int32_t(xdr, &res->sr_slotid)) 1018 return FALSE; 1019 1020 if (!xdr_u_int32_t(xdr, &res->sr_highest_slotid)) 1021 return FALSE; 1022 1023 if (!xdr_u_int32_t(xdr, &res->sr_target_highest_slotid)) 1024 return FALSE; 1025 1026 return xdr_u_int32_t(xdr, &res->sr_status_flags); 1027} 1028 1029static bool_t decode_op_sequence( 1030 XDR *xdr, 1031 nfs_resop4 *resop) 1032{ 1033 nfs41_sequence_res *res = (nfs41_sequence_res*)resop->res; 1034 1035 if (unexpected_op(resop->op, OP_SEQUENCE)) 1036 return FALSE; 1037 1038 if (!xdr_u_int32_t(xdr, &res->sr_status)) 1039 return FALSE; 1040 1041 if (res->sr_status == NFS4_OK) 1042 return xdr_sequence_res_ok(xdr, &res->sr_resok4); 1043 1044 return TRUE; 1045} 1046 1047 1048/* 1049 * OP_RECLAIM_COMPLETE 1050 */ 1051static bool_t encode_op_reclaim_complete( 1052 XDR *xdr, 1053 nfs_argop4 *argop) 1054{ 1055 bool_t zero = FALSE; 1056 1057 if (unexpected_op(argop->op, OP_RECLAIM_COMPLETE)) 1058 return FALSE; 1059 1060 /* rca_one_fs = 0 indicates that the reclaim applies to all filesystems */ 1061 return xdr_bool(xdr, &zero); 1062} 1063 1064static bool_t decode_op_reclaim_complete( 1065 XDR *xdr, 1066 nfs_resop4 *resop) 1067{ 1068 nfs41_reclaim_complete_res *res = (nfs41_reclaim_complete_res*)resop->res; 1069 1070 if (unexpected_op(resop->op, OP_RECLAIM_COMPLETE)) 1071 return FALSE; 1072 1073 return xdr_enum(xdr, (enum_t *)&res->status); 1074} 1075 1076 1077/* 1078 * OP_PUTFH 1079 */ 1080static bool_t encode_op_putfh( 1081 XDR *xdr, 1082 nfs_argop4 *argop) 1083{ 1084 nfs41_putfh_args *args = (nfs41_putfh_args*)argop->arg; 1085 1086 if (unexpected_op(argop->op, OP_PUTFH)) 1087 return FALSE; 1088 1089 return xdr_fh(xdr, &args->file->fh); 1090} 1091 1092static bool_t decode_op_putfh( 1093 XDR *xdr, 1094 nfs_resop4 *resop) 1095{ 1096 nfs41_putfh_res *res = (nfs41_putfh_res*)resop->res; 1097 1098 if (unexpected_op(resop->op, OP_PUTFH)) 1099 return FALSE; 1100 1101 return xdr_u_int32_t(xdr, &res->status); 1102} 1103 1104 1105/* 1106 * OP_PUTROOTFH 1107 */ 1108static bool_t encode_op_putrootfh( 1109 XDR *xdr, 1110 nfs_argop4* argop) 1111{ 1112 if (unexpected_op(argop->op, OP_PUTROOTFH)) 1113 return FALSE; 1114 /* void */ 1115 return TRUE; 1116} 1117 1118static bool_t decode_op_putrootfh( 1119 XDR *xdr, 1120 nfs_resop4 *resop) 1121{ 1122 nfs41_putrootfh_res *res = (nfs41_putrootfh_res*)resop->res; 1123 1124 if (unexpected_op(resop->op, OP_PUTROOTFH)) 1125 return FALSE; 1126 1127 return xdr_u_int32_t(xdr, &res->status); 1128} 1129 1130 1131/* 1132 * OP_GETFH 1133 */ 1134static bool_t encode_op_getfh( 1135 XDR *xdr, 1136 nfs_argop4 *argop) 1137{ 1138 if (unexpected_op(argop->op, OP_GETFH)) 1139 return FALSE; 1140 1141 /* void */ 1142 return TRUE; 1143} 1144 1145static bool_t decode_op_getfh( 1146 XDR *xdr, 1147 nfs_resop4 *resop) 1148{ 1149 nfs41_getfh_res *res = (nfs41_getfh_res*)resop->res; 1150 1151 if (unexpected_op(resop->op, OP_GETFH)) 1152 return FALSE; 1153 1154 if (!xdr_u_int32_t(xdr, &res->status)) 1155 return FALSE; 1156 1157 if (res->status == NFS4_OK) 1158 return xdr_fh(xdr, res->fh); 1159 1160 return TRUE; 1161} 1162 1163 1164/* 1165 * OP_LOOKUP 1166 */ 1167static bool_t encode_op_lookup( 1168 XDR *xdr, 1169 nfs_argop4 *argop) 1170{ 1171 nfs41_lookup_args *args = (nfs41_lookup_args*)argop->arg; 1172 1173 if (unexpected_op(argop->op, OP_LOOKUP)) 1174 return FALSE; 1175 1176 return encode_component(xdr, args->name); 1177} 1178 1179static bool_t decode_op_lookup( 1180 XDR *xdr, 1181 nfs_resop4 *resop) 1182{ 1183 nfs41_lookup_res *res = (nfs41_lookup_res*)resop->res; 1184 1185 if (unexpected_op(resop->op, OP_LOOKUP)) 1186 return FALSE; 1187 1188 return xdr_u_int32_t(xdr, &res->status); 1189} 1190 1191 1192/* 1193 * OP_ACCESS 1194 */ 1195static bool_t encode_op_access( 1196 XDR *xdr, 1197 nfs_argop4 *argop) 1198{ 1199 nfs41_access_args *args = (nfs41_access_args*)argop->arg; 1200 1201 if (unexpected_op(argop->op, OP_ACCESS)) 1202 return FALSE; 1203 1204 return xdr_u_int32_t(xdr, &args->access); 1205} 1206 1207static bool_t decode_op_access( 1208 XDR *xdr, 1209 nfs_resop4 *resop) 1210{ 1211 nfs41_access_res *res = (nfs41_access_res*)resop->res; 1212 1213 if (unexpected_op(resop->op, OP_ACCESS)) 1214 return FALSE; 1215 1216 if (!xdr_u_int32_t(xdr, &res->status)) 1217 return FALSE; 1218 1219 if (res->status == NFS4_OK) 1220 { 1221 if (!xdr_u_int32_t(xdr, &res->supported)) 1222 return FALSE; 1223 1224 return xdr_u_int32_t(xdr, &res->access); 1225 } 1226 return TRUE; 1227} 1228 1229 1230/* 1231 * OP_CLOSE 1232 */ 1233static bool_t encode_op_close( 1234 XDR *xdr, 1235 nfs_argop4 *argop) 1236{ 1237 nfs41_op_close_args *args = (nfs41_op_close_args*)argop->arg; 1238 uint32_t zero = 0; 1239 1240 if (unexpected_op(argop->op, OP_CLOSE)) 1241 return FALSE; 1242 1243 if (!xdr_u_int32_t(xdr, &zero)) // This should be ignored by server 1244 return FALSE; 1245 1246 return xdr_stateid4(xdr, &args->stateid->stateid); 1247} 1248 1249static bool_t decode_op_close( 1250 XDR *xdr, 1251 nfs_resop4 *resop) 1252{ 1253 stateid4 ignored; 1254 nfs41_op_close_res *res = (nfs41_op_close_res*)resop->res; 1255 1256 if (unexpected_op(resop->op, OP_CLOSE)) 1257 return FALSE; 1258 1259 if (!xdr_u_int32_t(xdr, &res->status)) 1260 return FALSE; 1261 1262 if (res->status == NFS4_OK) 1263 return xdr_stateid4(xdr, &ignored); 1264 1265 return TRUE; 1266} 1267 1268 1269/* 1270 * OP_COMMIT 1271 */ 1272static bool_t encode_op_commit( 1273 XDR *xdr, 1274 nfs_argop4 *argop) 1275{ 1276 nfs41_commit_args *args = (nfs41_commit_args*)argop->arg; 1277 1278 if (unexpected_op(argop->op, OP_COMMIT)) 1279 return FALSE; 1280 1281 if (!xdr_u_hyper(xdr, &args->offset)) 1282 return FALSE; 1283 1284 return xdr_u_int32_t(xdr, &args->count); 1285} 1286 1287static bool_t decode_op_commit( 1288 XDR *xdr, 1289 nfs_resop4 *resop) 1290{ 1291 nfs41_commit_res *res = (nfs41_commit_res*)resop->res; 1292 1293 if (unexpected_op(resop->op, OP_COMMIT)) 1294 return FALSE; 1295 1296 if (!xdr_u_int32_t(xdr, &res->status)) 1297 return FALSE; 1298 1299 if (res->status == NFS4_OK) 1300 return xdr_opaque(xdr, (char *)res->verf->verf, NFS4_VERIFIER_SIZE); 1301 1302 return TRUE; 1303} 1304 1305 1306/* 1307 * OP_CREATE 1308 */ 1309static bool_t encode_createtype4( 1310 XDR *xdr, 1311 createtype4 *ct) 1312{ 1313 bool_t result = TRUE; 1314 const char *linkdata; 1315 1316 if (!xdr_u_int32_t(xdr, &ct->type)) 1317 return FALSE; 1318 1319 switch (ct->type) 1320 { 1321 case NF4LNK: 1322 linkdata = ct->u.lnk.linkdata; 1323 result = xdr_bytes(xdr, (char**)&linkdata, &ct->u.lnk.linkdata_len, 1324 NFS4_OPAQUE_LIMIT); 1325 break; 1326 case NF4BLK: 1327 case NF4CHR: 1328 result = xdr_u_int32_t(xdr, &ct->u.devdata.specdata1); 1329 if (result == TRUE) 1330 result = xdr_u_int32_t(xdr, &ct->u.devdata.specdata2); 1331 break; 1332 default: 1333 // Some types need no further action 1334 break; 1335 } 1336 return result; 1337} 1338 1339static bool_t encode_createattrs4( 1340 XDR *xdr, 1341 nfs41_file_info* createattrs) 1342{ 1343 fattr4 attrs; 1344 1345 /* encode attribute values from createattrs->info into attrs.attr_vals */ 1346 attrs.attr_vals_len = NFS4_OPAQUE_LIMIT; 1347 if (!encode_file_attrs(&attrs, createattrs)) 1348 return FALSE; 1349 1350 return xdr_fattr4(xdr, &attrs); 1351} 1352 1353static bool_t encode_op_create( 1354 XDR *xdr, 1355 nfs_argop4 *argop) 1356{ 1357 nfs41_create_args *args = (nfs41_create_args*)argop->arg; 1358 1359 if (unexpected_op(argop->op, OP_CREATE)) 1360 return FALSE; 1361 1362 if (!encode_createtype4(xdr, &args->objtype)) 1363 return FALSE; 1364 1365 if (!encode_component(xdr, args->name)) 1366 return FALSE; 1367 1368 return encode_createattrs4(xdr, args->createattrs); 1369} 1370 1371static bool_t xdr_change_info4( 1372 XDR *xdr, 1373 change_info4 *cinfo) 1374{ 1375 if (!xdr_bool(xdr, &cinfo->atomic)) 1376 return FALSE; 1377 1378 if (!xdr_u_hyper(xdr, &cinfo->before)) 1379 return FALSE; 1380 1381 return xdr_u_hyper(xdr, &cinfo->after); 1382} 1383 1384static bool_t decode_op_create( 1385 XDR *xdr, 1386 nfs_resop4 *resop) 1387{ 1388 nfs41_create_res *res = (nfs41_create_res*)resop->res; 1389 1390 if (unexpected_op(resop->op, OP_CREATE)) 1391 return FALSE; 1392 1393 if (!xdr_u_int32_t(xdr, &res->status)) 1394 return FALSE; 1395 1396 if (res->status == NFS4_OK) 1397 { 1398 if (!xdr_change_info4(xdr, &res->cinfo)) 1399 return FALSE; 1400 return xdr_bitmap4(xdr, &res->attrset); 1401 } 1402 return TRUE; 1403} 1404 1405 1406/* 1407 * OP_LINK 1408 */ 1409static bool_t encode_op_link( 1410 XDR *xdr, 1411 nfs_argop4 *argop) 1412{ 1413 nfs41_link_args *args = (nfs41_link_args*)argop->arg; 1414 1415 if (unexpected_op(argop->op, OP_LINK)) 1416 return FALSE; 1417 1418 return encode_component(xdr, args->newname); 1419} 1420 1421static bool_t decode_op_link( 1422 XDR *xdr, 1423 nfs_resop4 *resop) 1424{ 1425 nfs41_link_res *res = (nfs41_link_res*)resop->res; 1426 1427 if (unexpected_op(resop->op, OP_LINK)) 1428 return FALSE; 1429 1430 if (!xdr_u_int32_t(xdr, &res->status)) 1431 return FALSE; 1432 1433 if (res->status == NFS4_OK) 1434 return xdr_change_info4(xdr, &res->cinfo); 1435 1436 return TRUE; 1437} 1438 1439 1440/* 1441 * OP_LOCK 1442 */ 1443static bool_t xdr_locker4( 1444 XDR *xdr, 1445 locker4 *locker) 1446{ 1447 if (xdr->x_op != XDR_ENCODE) { 1448 eprintf("%s: xdr->x_op %d is not supported!\n", 1449 "xdr_locker4", xdr->x_op); 1450 return FALSE; 1451 } 1452 1453 if (!xdr_bool(xdr, &locker->new_lock_owner)) 1454 return FALSE; 1455 1456 if (locker->new_lock_owner) { 1457 /* open_to_lock_owner4 open_owner */ 1458 if (!xdr_u_int32_t(xdr, &locker->u.open_owner.open_seqid)) 1459 return FALSE; 1460 1461 if (!xdr_stateid4(xdr, &locker->u.open_owner.open_stateid->stateid)) 1462 return FALSE; 1463 1464 if (!xdr_u_int32_t(xdr, &locker->u.open_owner.lock_seqid)) 1465 return FALSE; 1466 1467 return xdr_state_owner4(xdr, locker->u.open_owner.lock_owner); 1468 } else { 1469 /* exist_lock_owner4 lock_owner */ 1470 if (!xdr_stateid4(xdr, &locker->u.lock_owner.lock_stateid->stateid)) 1471 return FALSE; 1472 1473 return xdr_u_int32_t(xdr, &locker->u.lock_owner.lock_seqid); 1474 } 1475} 1476 1477static bool_t encode_op_lock( 1478 XDR *xdr, 1479 nfs_argop4 *argop) 1480{ 1481 nfs41_lock_args *args = (nfs41_lock_args*)argop->arg; 1482 1483 if (unexpected_op(argop->op, OP_LOCK)) 1484 return FALSE; 1485 1486 if (!xdr_u_int32_t(xdr, &args->locktype)) 1487 return FALSE; 1488 1489 if (!xdr_bool(xdr, &args->reclaim)) 1490 return FALSE; 1491 1492 if (!xdr_u_hyper(xdr, &args->offset)) 1493 return FALSE; 1494 1495 if (!xdr_u_hyper(xdr, &args->length)) 1496 return FALSE; 1497 1498 return xdr_locker4(xdr, &args->locker); 1499} 1500 1501static bool_t decode_lock_res_denied( 1502 XDR *xdr, 1503 lock_res_denied *denied) 1504{ 1505 if (!xdr_u_hyper(xdr, &denied->offset)) 1506 return FALSE; 1507 1508 if (!xdr_u_hyper(xdr, &denied->length)) 1509 return FALSE; 1510 1511 if (!xdr_u_int32_t(xdr, &denied->locktype)) 1512 return FALSE; 1513 1514 return xdr_state_owner4(xdr, &denied->owner); 1515} 1516 1517static bool_t decode_op_lock( 1518 XDR *xdr, 1519 nfs_resop4 *resop) 1520{ 1521 nfs41_lock_res *res = (nfs41_lock_res*)resop->res; 1522 1523 if (unexpected_op(resop->op, OP_LOCK)) 1524 return FALSE; 1525 1526 if (!xdr_u_int32_t(xdr, &res->status)) 1527 return FALSE; 1528 1529 switch (res->status) { 1530 case NFS4_OK: 1531 return xdr_stateid4(xdr, res->u.resok4.lock_stateid); 1532 break; 1533 case NFS4ERR_DENIED: 1534 return decode_lock_res_denied(xdr, &res->u.denied); 1535 break; 1536 default: 1537 break; 1538 } 1539 1540 return TRUE; 1541} 1542 1543 1544/* 1545 * OP_LOCKT 1546 */ 1547static bool_t encode_op_lockt( 1548 XDR *xdr, 1549 nfs_argop4 *argop) 1550{ 1551 nfs41_lockt_args *args = (nfs41_lockt_args*)argop->arg; 1552 1553 if (unexpected_op(argop->op, OP_LOCKT)) 1554 return FALSE; 1555 1556 if (!xdr_u_int32_t(xdr, &args->locktype)) 1557 return FALSE; 1558 1559 if (!xdr_u_hyper(xdr, &args->offset)) 1560 return FALSE; 1561 1562 if (!xdr_u_hyper(xdr, &args->length)) 1563 return FALSE; 1564 1565 return xdr_state_owner4(xdr, args->owner); 1566} 1567 1568static bool_t decode_op_lockt( 1569 XDR *xdr, 1570 nfs_resop4 *resop) 1571{ 1572 nfs41_lockt_res *res = (nfs41_lockt_res*)resop->res; 1573 1574 if (unexpected_op(resop->op, OP_LOCKT)) 1575 return FALSE; 1576 1577 if (!xdr_u_int32_t(xdr, &res->status)) 1578 return FALSE; 1579 1580 if (res->status == NFS4ERR_DENIED) 1581 return decode_lock_res_denied(xdr, &res->denied); 1582 1583 return TRUE; 1584} 1585 1586 1587/* 1588 * OP_LOCKU 1589 */ 1590static bool_t encode_op_locku( 1591 XDR *xdr, 1592 nfs_argop4 *argop) 1593{ 1594 nfs41_locku_args *args = (nfs41_locku_args*)argop->arg; 1595 1596 if (unexpected_op(argop->op, OP_LOCKU)) 1597 return FALSE; 1598 1599 if (!xdr_u_int32_t(xdr, &args->locktype)) 1600 return FALSE; 1601 1602 if (!xdr_u_int32_t(xdr, &args->seqid)) 1603 return FALSE; 1604 1605 if (!xdr_stateid4(xdr, &args->lock_stateid->stateid)) 1606 return FALSE; 1607 1608 if (!xdr_u_hyper(xdr, &args->offset)) 1609 return FALSE; 1610 1611 return xdr_u_hyper(xdr, &args->length); 1612} 1613 1614static bool_t decode_op_locku( 1615 XDR *xdr, 1616 nfs_resop4 *resop) 1617{ 1618 nfs41_locku_res *res = (nfs41_locku_res*)resop->res; 1619 1620 if (unexpected_op(resop->op, OP_LOCKU)) 1621 return FALSE; 1622 1623 if (!xdr_u_int32_t(xdr, &res->status)) 1624 return FALSE; 1625 1626 if (res->status == NFS4_OK) 1627 return xdr_stateid4(xdr, res->lock_stateid); 1628 1629 return TRUE; 1630} 1631 1632 1633/* 1634 * OP_DELEGPURGE 1635 */ 1636static bool_t encode_op_delegpurge( 1637 XDR *xdr, 1638 nfs_argop4 *argop) 1639{ 1640 uint64_t zero = 0; 1641 1642 if (unexpected_op(argop->op, OP_DELEGPURGE)) 1643 return FALSE; 1644 1645 /* The client SHOULD set the client field to zero, 1646 * and the server MUST ignore the clientid field. */ 1647 return xdr_u_int64_t(xdr, &zero); 1648} 1649 1650static bool_t decode_op_delegpurge( 1651 XDR *xdr, 1652 nfs_resop4 *resop) 1653{ 1654 nfs41_delegpurge_res *res = (nfs41_delegpurge_res*)resop->res; 1655 1656 if (unexpected_op(resop->op, OP_DELEGPURGE)) 1657 return FALSE; 1658 1659 return xdr_u_int32_t(xdr, &res->status); 1660} 1661 1662 1663/* 1664 * OP_DELEGRETURN 1665 */ 1666static bool_t encode_op_delegreturn( 1667 XDR *xdr, 1668 nfs_argop4 *argop) 1669{ 1670 nfs41_delegreturn_args *args = (nfs41_delegreturn_args*)argop->arg; 1671 1672 if (unexpected_op(argop->op, OP_DELEGRETURN)) 1673 return FALSE; 1674 1675 return xdr_stateid4(xdr, &args->stateid->stateid); 1676} 1677 1678static bool_t decode_op_delegreturn( 1679 XDR *xdr, 1680 nfs_resop4 *resop) 1681{ 1682 nfs41_delegreturn_res *res = (nfs41_delegreturn_res*)resop->res; 1683 1684 if (unexpected_op(resop->op, OP_DELEGRETURN)) 1685 return FALSE; 1686 1687 return xdr_u_int32_t(xdr, &res->status); 1688} 1689 1690 1691/* 1692 * OP_GETATTR 1693 */ 1694static bool_t encode_op_getattr( 1695 XDR *xdr, 1696 nfs_argop4 *argop) 1697{ 1698 nfs41_getattr_args *args = (nfs41_getattr_args*)argop->arg; 1699 1700 if (unexpected_op(argop->op, OP_GETATTR)) 1701 return FALSE; 1702 1703 return xdr_bitmap4(xdr, args->attr_request); 1704} 1705 1706static bool_t decode_file_attrs( 1707 XDR *xdr, 1708 fattr4 *attrs, 1709 nfs41_file_info *info) 1710{ 1711 if (attrs->attrmask.count >= 1) { 1712 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SUPPORTED_ATTRS) { 1713 if (!xdr_bitmap4(xdr, info->supported_attrs)) 1714 return FALSE; 1715 } 1716 if (attrs->attrmask.arr[0] & FATTR4_WORD0_TYPE) { 1717 if (!xdr_u_int32_t(xdr, &info->type)) 1718 return FALSE; 1719 } 1720 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CHANGE) { 1721 if (!xdr_u_hyper(xdr, &info->change)) 1722 return FALSE; 1723 } 1724 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SIZE) { 1725 if (!xdr_u_hyper(xdr, &info->size)) 1726 return FALSE; 1727 } 1728 if (attrs->attrmask.arr[0] & FATTR4_WORD0_LINK_SUPPORT) { 1729 if (!xdr_bool(xdr, &info->link_support)) 1730 return FALSE; 1731 } 1732 if (attrs->attrmask.arr[0] & FATTR4_WORD0_SYMLINK_SUPPORT) { 1733 if (!xdr_bool(xdr, &info->symlink_support)) 1734 return FALSE; 1735 } 1736 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FSID) { 1737 if (!xdr_fsid(xdr, &info->fsid)) 1738 return FALSE; 1739 } 1740 if (attrs->attrmask.arr[0] & FATTR4_WORD0_LEASE_TIME) { 1741 if (!xdr_u_int32_t(xdr, &info->lease_time)) 1742 return FALSE; 1743 } 1744 if (attrs->attrmask.arr[0] & FATTR4_WORD0_RDATTR_ERROR) { 1745 if (!xdr_u_int32_t(xdr, &info->rdattr_error)) 1746 return FALSE; 1747 } 1748 if (attrs->attrmask.arr[0] & FATTR4_WORD0_ACL) { 1749 nfsacl41 *acl = info->acl; 1750 if (!xdr_array(xdr, (char**)&acl->aces, &acl->count, 1751 32, sizeof(nfsace4), (xdrproc_t)xdr_nfsace4)) 1752 return FALSE; 1753 } 1754 if (attrs->attrmask.arr[0] & FATTR4_WORD0_ACLSUPPORT) { 1755 if (!xdr_u_int32_t(xdr, &info->aclsupport)) 1756 return FALSE; 1757 } 1758 if (attrs->attrmask.arr[0] & FATTR4_WORD0_ARCHIVE) { 1759 if (!xdr_bool(xdr, &info->archive)) 1760 return FALSE; 1761 } 1762 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CANSETTIME) { 1763 if (!xdr_bool(xdr, &info->cansettime)) 1764 return FALSE; 1765 } 1766 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CASE_INSENSITIVE) { 1767 if (!xdr_bool(xdr, &info->case_insensitive)) 1768 return FALSE; 1769 } 1770 if (attrs->attrmask.arr[0] & FATTR4_WORD0_CASE_PRESERVING) { 1771 if (!xdr_bool(xdr, &info->case_preserving)) 1772 return FALSE; 1773 } 1774 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FILEID) { 1775 if (!xdr_u_hyper(xdr, &info->fileid)) 1776 return FALSE; 1777 } 1778 if (attrs->attrmask.arr[0] & FATTR4_WORD0_FS_LOCATIONS) { 1779 if (!decode_fs_locations4(xdr, info->fs_locations)) 1780 return FALSE; 1781 } 1782 if (attrs->attrmask.arr[0] & FATTR4_WORD0_HIDDEN) { 1783 if (!xdr_bool(xdr, &info->hidden)) 1784 return FALSE; 1785 } 1786 if (attrs->attrmask.arr[0] & FATTR4_WORD0_MAXREAD) { 1787 if (!xdr_u_hyper(xdr, &info->maxread)) 1788 return FALSE; 1789 } 1790 if (attrs->attrmask.arr[0] & FATTR4_WORD0_MAXWRITE) { 1791 if (!xdr_u_hyper(xdr, &info->maxwrite)) 1792 return FALSE; 1793 } 1794 } 1795 if (attrs->attrmask.count >= 2) { 1796 if (attrs->attrmask.arr[1] & FATTR4_WORD1_MODE) { 1797 if (!xdr_u_int32_t(xdr, &info->mode)) 1798 return FALSE; 1799 } 1800 if (attrs->attrmask.arr[1] & FATTR4_WORD1_NUMLINKS) { 1801 if (!xdr_u_int32_t(xdr, &info->numlinks)) 1802 return FALSE; 1803 } 1804 if (attrs->attrmask.arr[1] & FATTR4_WORD1_OWNER) { 1805 char *ptr = &info->owner[0]; 1806 uint32_t owner_len; 1807 if (!xdr_bytes(xdr, &ptr, &owner_len, 1808 NFS4_OPAQUE_LIMIT)) 1809 return FALSE; 1810 info->owner[owner_len] = '\0'; 1811 } 1812 if (attrs->attrmask.arr[1] & FATTR4_WORD1_OWNER_GROUP) { 1813 char *ptr = &info->owner_group[0]; 1814 uint32_t owner_group_len; 1815 if (!xdr_bytes(xdr, &ptr, &owner_group_len, 1816 NFS4_OPAQUE_LIMIT)) 1817 return FALSE; 1818 info->owner_group[owner_group_len] = '\0'; 1819 } 1820 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_AVAIL) { 1821 if (!xdr_u_hyper(xdr, &info->space_avail)) 1822 return FALSE; 1823 } 1824 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_FREE) { 1825 if (!xdr_u_hyper(xdr, &info->space_free)) 1826 return FALSE; 1827 } 1828 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SPACE_TOTAL) { 1829 if (!xdr_u_hyper(xdr, &info->space_total)) 1830 return FALSE; 1831 } 1832 if (attrs->attrmask.arr[1] & FATTR4_WORD1_SYSTEM) { 1833 if (!xdr_bool(xdr, &info->system)) 1834 return FALSE; 1835 } 1836 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_ACCESS) { 1837 if (!xdr_nfstime4(xdr, &info->time_access)) 1838 return FALSE; 1839 } 1840 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_CREATE) { 1841 if (!xdr_nfstime4(xdr, &info->time_create)) 1842 return FALSE; 1843 } 1844 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_DELTA) { 1845 if (!xdr_nfstime4(xdr, info->time_delta)) 1846 return FALSE; 1847 } 1848 if (attrs->attrmask.arr[1] & FATTR4_WORD1_TIME_MODIFY) { 1849 if (!xdr_nfstime4(xdr, &info->time_modify)) 1850 return FALSE; 1851 } 1852 if (attrs->attrmask.arr[1] & FATTR4_WORD1_DACL) { 1853 if (!xdr_nfsdacl41(xdr, info->acl)) 1854 return FALSE; 1855 } 1856 if (attrs->attrmask.arr[1] & FATTR4_WORD1_FS_LAYOUT_TYPE) { 1857 if (!xdr_layout_types(xdr, &info->fs_layout_types)) 1858 return FALSE; 1859 } 1860 } 1861 if (attrs->attrmask.count >= 3) { 1862 if (attrs->attrmask.arr[2] & FATTR4_WORD2_MDSTHRESHOLD) { 1863 if (!xdr_mdsthreshold(xdr, &info->mdsthreshold)) 1864 return FALSE; 1865 } 1866 if (attrs->attrmask.arr[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 1867 if (!xdr_bitmap4(xdr, info->suppattr_exclcreat)) 1868 return FALSE; 1869 } 1870 } 1871 return TRUE; 1872} 1873 1874static bool_t decode_op_getattr( 1875 XDR *xdr, 1876 nfs_resop4 *resop) 1877{ 1878 nfs41_getattr_res *res = (nfs41_getattr_res*)resop->res; 1879 1880 if (unexpected_op(resop->op, OP_GETATTR)) 1881 return FALSE; 1882 1883 if (!xdr_u_int32_t(xdr, &res->status)) 1884 return FALSE; 1885 1886 if (res->status == NFS4_OK) 1887 { 1888 XDR attr_xdr; 1889 1890 if (!xdr_fattr4(xdr, &res->obj_attributes)) 1891 return FALSE; 1892 xdrmem_create(&attr_xdr, (char *)res->obj_attributes.attr_vals, res->obj_attributes.attr_vals_len, XDR_DECODE); 1893 return decode_file_attrs(&attr_xdr, &res->obj_attributes, res->info); 1894 } 1895 return TRUE; 1896} 1897 1898 1899/* 1900 * OP_OPEN 1901 */ 1902static bool_t encode_createhow4( 1903 XDR *xdr, 1904 createhow4 *ch) 1905{ 1906 bool_t result = TRUE; 1907 1908 if (!xdr_u_int32_t(xdr, &ch->mode)) 1909 return FALSE; 1910 1911 switch (ch->mode) 1912 { 1913 case UNCHECKED4: 1914 case GUARDED4: 1915 result = encode_createattrs4(xdr, ch->createattrs); 1916 break; 1917 case EXCLUSIVE4: 1918 result = xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE); 1919 break; 1920 case EXCLUSIVE4_1: 1921 if (!xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE)) 1922 return FALSE; 1923 if (!encode_createattrs4(xdr, ch->createattrs)) 1924 return FALSE; 1925 break; 1926 } 1927 return result; 1928} 1929 1930static bool_t encode_openflag4( 1931 XDR *xdr, 1932 openflag4 *of) 1933{ 1934 bool_t result = TRUE; 1935 1936 if (!xdr_u_int32_t(xdr, &of->opentype)) 1937 return FALSE; 1938 1939 switch (of->opentype) 1940 { 1941 case OPEN4_CREATE: 1942 result = encode_createhow4(xdr, &of->how); 1943 break; 1944 default: 1945 break; 1946 } 1947 return result; 1948} 1949 1950static bool_t encode_claim_deleg_cur( 1951 XDR *xdr, 1952 stateid4 *stateid, 1953 nfs41_component *name) 1954{ 1955 if (!xdr_stateid4(xdr, stateid)) 1956 return FALSE; 1957 return encode_component(xdr, name); 1958} 1959 1960static bool_t encode_open_claim4( 1961 XDR *xdr, 1962 open_claim4 *oc) 1963{ 1964 if (!xdr_u_int32_t(xdr, &oc->claim)) 1965 return FALSE; 1966 1967 switch (oc->claim) 1968 { 1969 case CLAIM_NULL: 1970 return encode_component(xdr, oc->u.null.filename); 1971 case CLAIM_PREVIOUS: 1972 return xdr_u_int32_t(xdr, &oc->u.prev.delegate_type); 1973 case CLAIM_FH: 1974 return TRUE; /* use current file handle */ 1975 case CLAIM_DELEGATE_CUR: 1976 return encode_claim_deleg_cur(xdr, 1977 &oc->u.deleg_cur.delegate_stateid->stateid, 1978 oc->u.deleg_cur.name); 1979 case CLAIM_DELEG_CUR_FH: 1980 return xdr_stateid4(xdr, 1981 &oc->u.deleg_cur_fh.delegate_stateid->stateid); 1982 case CLAIM_DELEGATE_PREV: 1983 return encode_component(xdr, oc->u.deleg_prev.filename); 1984 case CLAIM_DELEG_PREV_FH: 1985 return TRUE; /* use current file handle */ 1986 default: 1987 eprintf("encode_open_claim4: unsupported claim %d.\n", 1988 oc->claim); 1989 return FALSE; 1990 } 1991} 1992 1993static bool_t encode_op_open( 1994 XDR *xdr, 1995 nfs_argop4 *argop) 1996{ 1997 nfs41_op_open_args *args = (nfs41_op_open_args*)argop->arg; 1998 1999 if (unexpected_op(argop->op, OP_OPEN)) 2000 return FALSE; 2001 2002 if (!xdr_u_int32_t(xdr, &args->seqid)) 2003 return FALSE; 2004 2005 if (!xdr_u_int32_t(xdr, &args->share_access)) 2006 return FALSE; 2007 2008 if (!xdr_u_int32_t(xdr, &args->share_deny)) 2009 return FALSE; 2010 2011 if (!xdr_state_owner4(xdr, args->owner)) 2012 return FALSE; 2013 2014 if (!encode_openflag4(xdr, &args->openhow)) 2015 return FALSE; 2016 2017 return encode_open_claim4(xdr, args->claim); 2018} 2019 2020static bool_t decode_open_none_delegation4( 2021 XDR *xdr, 2022 open_delegation4 *delegation) 2023{ 2024 enum_t why_no_deleg; 2025 bool_t will_signal; 2026 2027 if (!xdr_enum(xdr, (enum_t*)&why_no_deleg)) 2028 return FALSE; 2029 2030 switch (why_no_deleg) 2031 { 2032 case WND4_CONTENTION: 2033 case WND4_RESOURCE: 2034 return xdr_bool(xdr, &will_signal); 2035 default: 2036 return TRUE; 2037 } 2038} 2039 2040static bool_t decode_open_read_delegation4( 2041 XDR *xdr, 2042 open_delegation4 *delegation) 2043{ 2044 if (!xdr_stateid4(xdr, &delegation->stateid)) 2045 return FALSE; 2046 2047 if (!xdr_bool(xdr, &delegation->recalled)) 2048 return FALSE; 2049 2050 return xdr_nfsace4(xdr, &delegation->permissions); 2051} 2052 2053static bool_t decode_modified_limit4( 2054 XDR *xdr, 2055 uint64_t *filesize) 2056{ 2057 uint32_t blocks, bytes_per_block; 2058 2059 if (!xdr_u_int32_t(xdr, &blocks)) 2060 return FALSE; 2061 2062 if (!xdr_u_int32_t(xdr, &bytes_per_block)) 2063 return FALSE; 2064 2065 *filesize = blocks * bytes_per_block; 2066 return TRUE; 2067} 2068 2069enum limit_by4 { 2070 NFS_LIMIT_SIZE = 1, 2071 NFS_LIMIT_BLOCKS = 2 2072}; 2073 2074static bool_t decode_space_limit4( 2075 XDR *xdr, 2076 uint64_t *filesize) 2077{ 2078 uint32_t limitby; 2079 2080 if (!xdr_u_int32_t(xdr, &limitby)) 2081 return FALSE; 2082 2083 switch (limitby) 2084 { 2085 case NFS_LIMIT_SIZE: 2086 return xdr_u_hyper(xdr, filesize); 2087 case NFS_LIMIT_BLOCKS: 2088 return decode_modified_limit4(xdr, filesize); 2089 default: 2090 eprintf("decode_space_limit4: limitby %d invalid\n", limitby); 2091 return FALSE; 2092 } 2093} 2094 2095static bool_t decode_open_write_delegation4( 2096 XDR *xdr, 2097 open_delegation4 *delegation) 2098{ 2099 uint64_t size_limit; 2100 2101 if (!xdr_stateid4(xdr, &delegation->stateid)) 2102 return FALSE; 2103 2104 if (!xdr_bool(xdr, &delegation->recalled)) 2105 return FALSE; 2106 2107 if (!decode_space_limit4(xdr, &size_limit)) 2108 return FALSE; 2109 2110 return xdr_nfsace4(xdr, &delegation->permissions); 2111} 2112 2113static bool_t decode_open_res_ok( 2114 XDR *xdr, 2115 nfs41_op_open_res_ok *res) 2116{ 2117 if (!xdr_stateid4(xdr, res->stateid)) 2118 return FALSE; 2119 2120 if (!xdr_change_info4(xdr, &res->cinfo)) 2121 return FALSE; 2122 2123 if (!xdr_u_int32_t(xdr, &res->rflags)) 2124 return FALSE; 2125 2126 if (!xdr_bitmap4(xdr, &res->attrset)) 2127 return FALSE; 2128 2129 if (!xdr_enum(xdr, (enum_t*)&res->delegation->type)) 2130 return FALSE; 2131 2132 switch (res->delegation->type) 2133 { 2134 case OPEN_DELEGATE_NONE: 2135 return TRUE; 2136 case OPEN_DELEGATE_NONE_EXT: 2137 return decode_open_none_delegation4(xdr, res->delegation); 2138 case OPEN_DELEGATE_READ: 2139 return decode_open_read_delegation4(xdr, res->delegation); 2140 case OPEN_DELEGATE_WRITE: 2141 return decode_open_write_delegation4(xdr, res->delegation); 2142 default: 2143 eprintf("decode_open_res_ok: delegation type %d not " 2144 "supported.\n", res->delegation->type); 2145 return FALSE; 2146 } 2147} 2148 2149static bool_t decode_op_open( 2150 XDR *xdr, 2151 nfs_resop4 *resop) 2152{ 2153 nfs41_op_open_res *res = (nfs41_op_open_res*)resop->res; 2154 2155 if (unexpected_op(resop->op, OP_OPEN)) 2156 return FALSE; 2157 2158 if (!xdr_u_int32_t(xdr, &res->status)) 2159 return FALSE; 2160 2161 if (res->status == NFS4_OK) 2162 return decode_open_res_ok(xdr, &res->resok4); 2163 2164 return TRUE; 2165} 2166 2167 2168/* 2169 * OP_OPENATTR 2170 */ 2171static bool_t encode_op_openattr( 2172 XDR *xdr, 2173 nfs_argop4 *argop) 2174{ 2175 nfs41_openattr_args *args = (nfs41_openattr_args*)argop->arg; 2176 2177 if (unexpected_op(argop->op, OP_OPENATTR)) 2178 return FALSE; 2179 2180 return xdr_bool(xdr, &args->createdir); 2181} 2182 2183static bool_t decode_op_openattr( 2184 XDR *xdr, 2185 nfs_resop4 *resop) 2186{ 2187 nfs41_openattr_res *res = (nfs41_openattr_res*)resop->res; 2188 2189 if (unexpected_op(resop->op, OP_OPENATTR)) 2190 return FALSE; 2191 2192 return xdr_u_int32_t(xdr, &res->status); 2193} 2194 2195 2196/* 2197 * OP_READ 2198 */ 2199static bool_t encode_op_read( 2200 XDR *xdr, 2201 nfs_argop4 *argop) 2202{ 2203 nfs41_read_args *args = (nfs41_read_args*)argop->arg; 2204 2205 if (unexpected_op(argop->op, OP_READ)) 2206 return FALSE; 2207 2208 if (!xdr_stateid4(xdr, &args->stateid->stateid)) 2209 return FALSE; 2210 2211 if (!xdr_u_hyper(xdr, &args->offset)) 2212 return FALSE; 2213 2214 return xdr_u_int32_t(xdr, &args->count); 2215} 2216 2217static bool_t decode_read_res_ok( 2218 XDR *xdr, 2219 nfs41_read_res_ok *res) 2220{ 2221 unsigned char *data = res->data; 2222 2223 if (!xdr_bool(xdr, &res->eof)) 2224 return FALSE; 2225 2226 return xdr_bytes(xdr, (char **)&data, &res->data_len, NFS41_MAX_FILEIO_SIZE); 2227} 2228 2229static bool_t decode_op_read( 2230 XDR *xdr, 2231 nfs_resop4 *resop) 2232{ 2233 nfs41_read_res *res = (nfs41_read_res*)resop->res; 2234 2235 if (unexpected_op(resop->op, OP_READ)) 2236 return FALSE; 2237 2238 if (!xdr_u_int32_t(xdr, &res->status)) 2239 return FALSE; 2240 2241 if (res->status == NFS4_OK) 2242 return decode_read_res_ok(xdr, &res->resok4); 2243 2244 return TRUE; 2245} 2246 2247 2248/* 2249 * OP_READDIR 2250 */ 2251static bool_t encode_op_readdir( 2252 XDR *xdr, 2253 nfs_argop4 *argop) 2254{ 2255 nfs41_readdir_args *args = (nfs41_readdir_args*)argop->arg; 2256 2257 if (unexpected_op(argop->op, OP_READDIR)) 2258 return FALSE; 2259 2260 if (!xdr_u_hyper(xdr, &args->cookie.cookie)) 2261 return FALSE; 2262 2263 if (!xdr_opaque(xdr, (char *)args->cookie.verf, NFS4_VERIFIER_SIZE)) 2264 return FALSE; 2265 2266 if (!xdr_u_int32_t(xdr, &args->dircount)) 2267 return FALSE; 2268 2269 if (!xdr_u_int32_t(xdr, &args->maxcount)) 2270 return FALSE; 2271 2272 return xdr_bitmap4(xdr, args->attr_request); 2273} 2274 2275typedef struct __readdir_entry_iterator { 2276 unsigned char *buf_pos; 2277 uint32_t remaining_len; 2278 uint32_t *last_entry_offset; 2279 bool_t ignore_the_rest; 2280 bool_t has_next_entry; 2281} readdir_entry_iterator; 2282 2283static bool_t decode_readdir_entry( 2284 XDR *xdr, 2285 readdir_entry_iterator *it) 2286{ 2287 uint64_t cookie; 2288 unsigned char name[NFS4_OPAQUE_LIMIT]; 2289 unsigned char *nameptr = &name[0]; 2290 uint32_t name_len, entry_len; 2291 fattr4 attrs; 2292 2293 /* decode into temporaries so we can determine if there's enough 2294 * room in the buffer for this entry */ 2295 ZeroMemory(name, NFS4_OPAQUE_LIMIT); 2296 name_len = NFS4_OPAQUE_LIMIT; 2297 entry_len = (uint32_t)FIELD_OFFSET(nfs41_readdir_entry, name); 2298 attrs.attr_vals_len = NFS4_OPAQUE_LIMIT; 2299 2300 if (!xdr_u_hyper(xdr, &cookie)) 2301 return FALSE; 2302 2303 if (!xdr_bytes(xdr, (char **)&nameptr, &name_len, NFS4_OPAQUE_LIMIT)) 2304 return FALSE; 2305 2306 if (!xdr_fattr4(xdr, &attrs)) 2307 return FALSE; 2308 2309 if (!xdr_bool(xdr, &it->has_next_entry)) 2310 return FALSE; 2311 2312 if (it->ignore_the_rest) 2313 return TRUE; 2314 2315 name_len += 1; /* account for null terminator */ 2316 if (entry_len + name_len <= it->remaining_len) 2317 { 2318 XDR fattr_xdr; 2319 nfs41_readdir_entry *entry = (nfs41_readdir_entry*)it->buf_pos; 2320 entry->cookie = cookie; 2321 entry->name_len = name_len; 2322 2323 if (it->has_next_entry) 2324 entry->next_entry_offset = entry_len + name_len; 2325 else 2326 entry->next_entry_offset = 0; 2327 2328 xdrmem_create(&fattr_xdr, (char *)attrs.attr_vals, attrs.attr_vals_len, XDR_DECODE); 2329 if (!(decode_file_attrs(&fattr_xdr, &attrs, &entry->attr_info))) 2330 entry->attr_info.rdattr_error = NFS4ERR_BADXDR; 2331 StringCchCopyA(entry->name, name_len, (STRSAFE_LPCSTR)name); 2332 2333 it->buf_pos += entry_len + name_len; 2334 it->remaining_len -= entry_len + name_len; 2335 it->last_entry_offset = &entry->next_entry_offset; 2336 } 2337 else if (it->last_entry_offset) 2338 { 2339 *(it->last_entry_offset) = 0; 2340 it->ignore_the_rest = 1; 2341 } 2342 2343 return TRUE; 2344} 2345 2346static bool_t decode_readdir_list( 2347 XDR *xdr, 2348 nfs41_readdir_list *dirs) 2349{ 2350 readdir_entry_iterator iter; 2351 iter.buf_pos = dirs->entries; 2352 iter.remaining_len = dirs->entries_len; 2353 iter.last_entry_offset = NULL; 2354 iter.ignore_the_rest = 0; 2355 iter.has_next_entry = 0; 2356 2357 if (!xdr_bool(xdr, &dirs->has_entries)) 2358 return FALSE; 2359 2360 if (dirs->has_entries) 2361 { 2362 do { 2363 if (!decode_readdir_entry(xdr, &iter)) 2364 return FALSE; 2365 2366 } while (iter.has_next_entry); 2367 } 2368 dirs->entries_len -= iter.remaining_len; 2369 2370 if (!xdr_bool(xdr, &dirs->eof)) 2371 return FALSE; 2372 2373 /* reset eof if we couldn't fit everything in the buffer */ 2374 if (iter.ignore_the_rest) 2375 dirs->eof = 0; 2376 return TRUE; 2377} 2378 2379static bool_t decode_op_readdir( 2380 XDR *xdr, 2381 nfs_resop4 *resop) 2382{ 2383 nfs41_readdir_res *res = (nfs41_readdir_res*)resop->res; 2384 2385 if (unexpected_op(resop->op, OP_READDIR)) 2386 return FALSE; 2387 2388 if (!xdr_u_int32_t(xdr, &res->status)) 2389 return FALSE; 2390 2391 if (res->status == NFS4_OK) { 2392 if (!xdr_opaque(xdr, (char *)res->cookieverf, NFS4_VERIFIER_SIZE)) 2393 return FALSE; 2394 return decode_readdir_list(xdr, &res->reply); 2395 } 2396 return TRUE; 2397} 2398 2399 2400/* 2401 * OP_READLINK 2402 */ 2403static bool_t encode_op_readlink( 2404 XDR *xdr, 2405 nfs_argop4 *argop) 2406{ 2407 if (unexpected_op(argop->op, OP_READLINK)) 2408 return FALSE; 2409 2410 /* void */ 2411 return TRUE; 2412} 2413 2414static bool_t decode_op_readlink( 2415 XDR *xdr, 2416 nfs_resop4 *resop) 2417{ 2418 nfs41_readlink_res *res = (nfs41_readlink_res*)resop->res; 2419 2420 if (unexpected_op(resop->op, OP_READLINK)) 2421 return FALSE; 2422 2423 if (!xdr_u_int32_t(xdr, &res->status)) 2424 return FALSE; 2425 2426 if (res->status == NFS4_OK) { 2427 char *link = res->link; 2428 return xdr_bytes(xdr, &link, &res->link_len, res->link_len); 2429 } 2430 2431 return TRUE; 2432} 2433 2434 2435/* 2436 * OP_REMOVE 2437 */ 2438static bool_t encode_op_remove( 2439 XDR *xdr, 2440 nfs_argop4 *argop) 2441{ 2442 nfs41_remove_args *args = (nfs41_remove_args*)argop->arg; 2443 2444 if (unexpected_op(argop->op, OP_REMOVE)) 2445 return FALSE; 2446 2447 return encode_component(xdr, args->target); 2448} 2449 2450static bool_t decode_op_remove( 2451 XDR *xdr, 2452 nfs_resop4 *resop) 2453{ 2454 nfs41_remove_res *res = (nfs41_remove_res*)resop->res; 2455 2456 if (unexpected_op(resop->op, OP_REMOVE)) 2457 return FALSE; 2458 2459 if (!xdr_u_int32_t(xdr, &res->status)) 2460 return FALSE; 2461 2462 if (res->status == NFS4_OK) 2463 return xdr_change_info4(xdr, &res->cinfo); 2464 2465 return TRUE; 2466} 2467 2468 2469/* 2470 * OP_RENAME 2471 */ 2472static bool_t encode_op_rename( 2473 XDR *xdr, 2474 nfs_argop4 *argop) 2475{ 2476 nfs41_rename_args *args = (nfs41_rename_args*)argop->arg; 2477 2478 if (unexpected_op(argop->op, OP_RENAME)) 2479 return FALSE; 2480 2481 if (!encode_component(xdr, args->oldname)) 2482 return FALSE; 2483 2484 return encode_component(xdr, args->newname); 2485} 2486 2487static bool_t decode_op_rename( 2488 XDR *xdr, 2489 nfs_resop4 *resop) 2490{ 2491 nfs41_rename_res *res = (nfs41_rename_res*)resop->res; 2492 2493 if (unexpected_op(resop->op, OP_RENAME)) 2494 return FALSE; 2495 2496 if (!xdr_u_int32_t(xdr, &res->status)) 2497 return FALSE; 2498 2499 if (res->status == NFS4_OK) 2500 { 2501 if (!xdr_change_info4(xdr, &res->source_cinfo)) 2502 return FALSE; 2503 return xdr_change_info4(xdr, &res->target_cinfo); 2504 } 2505 return TRUE; 2506} 2507 2508 2509/* 2510 * OP_RESTOREFH 2511 */ 2512static bool_t encode_op_restorefh( 2513 XDR *xdr, 2514 nfs_argop4 *argop) 2515{ 2516 if (unexpected_op(argop->op, OP_RESTOREFH)) 2517 return FALSE; 2518 2519 /* void */ 2520 return TRUE; 2521} 2522 2523static bool_t decode_op_restorefh( 2524 XDR *xdr, 2525 nfs_resop4 *resop) 2526{ 2527 nfs41_restorefh_res *res = (nfs41_restorefh_res*)resop->res; 2528 2529 if (unexpected_op(resop->op, OP_RESTOREFH)) 2530 return FALSE; 2531 2532 return xdr_u_int32_t(xdr, &res->status); 2533} 2534 2535 2536/* 2537 * OP_SAVEFH 2538 */ 2539static bool_t encode_op_savefh( 2540 XDR *xdr, 2541 nfs_argop4 *argop) 2542{ 2543 if (unexpected_op(argop->op, OP_SAVEFH)) 2544 return FALSE; 2545 2546 /* void */ 2547 return TRUE; 2548} 2549 2550static bool_t decode_op_savefh( 2551 XDR *xdr, 2552 nfs_resop4 *resop) 2553{ 2554 nfs41_savefh_res *res = (nfs41_savefh_res*)resop->res; 2555 2556 if (unexpected_op(resop->op, OP_SAVEFH)) 2557 return FALSE; 2558 2559 return xdr_u_int32_t(xdr, &res->status); 2560} 2561 2562 2563/* 2564 * OP_SETATTR 2565 */ 2566static bool_t encode_file_attrs( 2567 fattr4 *attrs, 2568 nfs41_file_info *info) 2569{ 2570 uint32_t i; 2571 XDR localxdr; 2572 2573 xdrmem_create(&localxdr, (char *)attrs->attr_vals, NFS4_OPAQUE_LIMIT, XDR_ENCODE); 2574 2575 attrs->attr_vals_len = 0; 2576 ZeroMemory(&attrs->attrmask, sizeof(bitmap4)); 2577 attrs->attrmask.count = info->attrmask.count; 2578 2579 if (info->attrmask.count > 0) { 2580 if (info->attrmask.arr[0] & FATTR4_WORD0_SIZE) { 2581 if (!xdr_u_hyper(&localxdr, &info->size)) 2582 return FALSE; 2583 attrs->attrmask.arr[0] |= FATTR4_WORD0_SIZE; 2584 } 2585 if (info->attrmask.arr[0] & FATTR4_WORD0_ACL) { 2586 if (!xdr_nfsacl41(&localxdr, info->acl)) 2587 return FALSE; 2588 attrs->attrmask.arr[0] |= FATTR4_WORD0_ACL; 2589 } 2590 if (info->attrmask.arr[0] & FATTR4_WORD0_ARCHIVE) { 2591 if (!xdr_bool(&localxdr, &info->archive)) 2592 return FALSE; 2593 attrs->attrmask.arr[0] |= FATTR4_WORD0_ARCHIVE; 2594 } 2595 if (info->attrmask.arr[0] & FATTR4_WORD0_HIDDEN) { 2596 if (!xdr_bool(&localxdr, &info->hidden)) 2597 return FALSE; 2598 attrs->attrmask.arr[0] |= FATTR4_WORD0_HIDDEN; 2599 } 2600 } 2601 if (info->attrmask.count > 1) { 2602 if (info->attrmask.arr[1] & FATTR4_WORD1_MODE) { 2603 if (!xdr_u_int32_t(&localxdr, &info->mode)) 2604 return FALSE; 2605 attrs->attrmask.arr[1] |= FATTR4_WORD1_MODE; 2606 } 2607 if (info->attrmask.arr[1] & FATTR4_WORD1_SYSTEM) { 2608 if (!xdr_bool(&localxdr, &info->system)) 2609 return FALSE; 2610 attrs->attrmask.arr[1] |= FATTR4_WORD1_SYSTEM; 2611 } 2612 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 2613 if (!xdr_settime4(&localxdr, &info->time_access, info->time_delta)) 2614 return FALSE; 2615 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_ACCESS_SET; 2616 } 2617 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_CREATE) { 2618 if (!xdr_nfstime4(&localxdr, &info->time_create)) 2619 return FALSE; 2620 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE; 2621 } 2622 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 2623 if (!xdr_settime4(&localxdr, &info->time_modify, info->time_delta)) 2624 return FALSE; 2625 attrs->attrmask.arr[1] |= FATTR4_WORD1_TIME_MODIFY_SET; 2626 } 2627 if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER) { 2628 char *ptr = &info->owner[0]; 2629 uint32_t owner_len = (uint32_t)strlen(info->owner); 2630 if (!xdr_bytes(&localxdr, &ptr, &owner_len, 2631 NFS4_OPAQUE_LIMIT)) 2632 return FALSE; 2633 attrs->attrmask.arr[1] |= FATTR4_WORD1_OWNER; 2634 } 2635 if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER_GROUP) { 2636 char *ptr = &info->owner_group[0]; 2637 uint32_t owner_group_len = (uint32_t)strlen(info->owner_group); 2638 if (!xdr_bytes(&localxdr, &ptr, &owner_group_len, 2639 NFS4_OPAQUE_LIMIT)) 2640 return FALSE; 2641 attrs->attrmask.arr[1] |= FATTR4_WORD1_OWNER_GROUP; 2642 } 2643 } 2644 if (info->attrmask.count > 2) { 2645 if (info->attrmask.arr[2] & FATTR4_WORD2_MODE_SET_MASKED) { 2646 if (!xdr_u_int32_t(&localxdr, &info->mode)) 2647 return FALSE; 2648 if (!xdr_u_int32_t(&localxdr, &info->mode_mask)) 2649 return FALSE; 2650 attrs->attrmask.arr[2] |= FATTR4_WORD2_MODE_SET_MASKED; 2651 } 2652 } 2653 2654 /* warn if we try to set attributes that aren't handled */ 2655 for (i = 0; i < info->attrmask.count; i++) 2656 if (attrs->attrmask.arr[i] != info->attrmask.arr[i]) 2657 eprintf("encode_file_attrs() attempted to encode extra " 2658 "attributes in arr[%d]: encoded %d, but wanted %d.\n", 2659 i, attrs->attrmask.arr[i], info->attrmask.arr[i]); 2660 2661 attrs->attr_vals_len = xdr_getpos(&localxdr); 2662 return TRUE; 2663} 2664 2665static bool_t encode_op_setattr( 2666 XDR *xdr, 2667 nfs_argop4 *argop) 2668{ 2669 nfs41_setattr_args *args = (nfs41_setattr_args*)argop->arg; 2670 fattr4 attrs; 2671 2672 if (unexpected_op(argop->op, OP_SETATTR)) 2673 return FALSE; 2674 2675 if (!xdr_stateid4(xdr, &args->stateid->stateid)) 2676 return FALSE; 2677 2678 /* encode attribute values from args->info into attrs.attr_vals */ 2679 attrs.attr_vals_len = NFS4_OPAQUE_LIMIT; 2680 if (!encode_file_attrs(&attrs, args->info)) 2681 return FALSE; 2682 2683 return xdr_fattr4(xdr, &attrs); 2684} 2685 2686static bool_t decode_op_setattr( 2687 XDR *xdr, 2688 nfs_resop4 *resop) 2689{ 2690 nfs41_setattr_res *res = (nfs41_setattr_res*)resop->res; 2691 2692 if (unexpected_op(resop->op, OP_SETATTR)) 2693 return FALSE; 2694 2695 if (!xdr_u_int32_t(xdr, &res->status)) 2696 return FALSE; 2697 2698 if (res->status == NFS4_OK) 2699 return xdr_bitmap4(xdr, &res->attrsset); 2700 2701 return TRUE; 2702} 2703 2704 2705/* 2706 * OP_WANT_DELEGATION 2707 */ 2708static bool_t encode_op_want_delegation( 2709 XDR *xdr, 2710 nfs_argop4 *argop) 2711{ 2712 nfs41_want_delegation_args *args = (nfs41_want_delegation_args*)argop->arg; 2713 2714 if (unexpected_op(argop->op, OP_WANT_DELEGATION)) 2715 return FALSE; 2716 2717 if (!xdr_u_int32_t(xdr, &args->want)) 2718 return FALSE; 2719 2720 if (!xdr_u_int32_t(xdr, &args->claim->claim)) 2721 return FALSE; 2722 2723 return args->claim->claim != CLAIM_PREVIOUS || 2724 xdr_u_int32_t(xdr, &args->claim->prev_delegate_type); 2725} 2726 2727static bool_t decode_op_want_delegation( 2728 XDR *xdr, 2729 nfs_resop4 *resop) 2730{ 2731 nfs41_want_delegation_res *res = (nfs41_want_delegation_res*)resop->res; 2732 2733 if (unexpected_op(resop->op, OP_WANT_DELEGATION)) 2734 return FALSE; 2735 2736 if (!xdr_u_int32_t(xdr, &res->status)) 2737 return FALSE; 2738 2739 if (res->status) 2740 return TRUE; 2741 2742 if (!xdr_enum(xdr, (enum_t*)&res->delegation->type)) 2743 return FALSE; 2744 2745 switch (res->delegation->type) 2746 { 2747 case OPEN_DELEGATE_NONE: 2748 return TRUE; 2749 case OPEN_DELEGATE_NONE_EXT: 2750 return decode_open_none_delegation4(xdr, res->delegation); 2751 case OPEN_DELEGATE_READ: 2752 return decode_open_read_delegation4(xdr, res->delegation); 2753 case OPEN_DELEGATE_WRITE: 2754 return decode_open_write_delegation4(xdr, res->delegation); 2755 default: 2756 eprintf("decode_open_res_ok: delegation type %d not " 2757 "supported.\n", res->delegation->type); 2758 return FALSE; 2759 } 2760} 2761 2762 2763/* 2764 * OP_FREE_STATEID 2765 */ 2766static bool_t encode_op_free_stateid( 2767 XDR *xdr, 2768 nfs_argop4 *argop) 2769{ 2770 nfs41_free_stateid_args *args = (nfs41_free_stateid_args*)argop->arg; 2771 2772 if (unexpected_op(argop->op, OP_FREE_STATEID)) 2773 return FALSE; 2774 2775 return xdr_stateid4(xdr, args->stateid); 2776} 2777 2778static bool_t decode_op_free_stateid( 2779 XDR *xdr, 2780 nfs_resop4 *resop) 2781{ 2782 nfs41_free_stateid_res *res = (nfs41_free_stateid_res*)resop->res; 2783 2784 if (unexpected_op(resop->op, OP_FREE_STATEID)) 2785 return FALSE; 2786 2787 return xdr_u_int32_t(xdr, &res->status); 2788} 2789 2790 2791/* 2792 * OP_TEST_STATEID 2793 */ 2794static bool_t encode_op_test_stateid( 2795 XDR *xdr, 2796 nfs_argop4 *argop) 2797{ 2798 nfs41_test_stateid_args *args = (nfs41_test_stateid_args*)argop->arg; 2799 2800 if (unexpected_op(argop->op, OP_TEST_STATEID)) 2801 return FALSE; 2802 2803 return xdr_array(xdr, (char**)&args->stateids, &args->count, 2804 args->count, sizeof(stateid_arg), (xdrproc_t)xdr_stateid4); 2805} 2806 2807static bool_t decode_op_test_stateid( 2808 XDR *xdr, 2809 nfs_resop4 *resop) 2810{ 2811 nfs41_test_stateid_res *res = (nfs41_test_stateid_res*)resop->res; 2812 2813 if (unexpected_op(resop->op, OP_TEST_STATEID)) 2814 return FALSE; 2815 2816 if (!xdr_u_int32_t(xdr, &res->status)) 2817 return FALSE; 2818 2819 if (res->status == NFS4_OK) { 2820 return xdr_array(xdr, (char**)&res->resok.status, &res->resok.count, 2821 res->resok.count, sizeof(uint32_t), (xdrproc_t)xdr_u_int32_t); 2822 } 2823 return TRUE; 2824} 2825 2826 2827/* 2828 * OP_WRITE 2829 */ 2830static bool_t encode_op_write( 2831 XDR *xdr, 2832 nfs_argop4 *argop) 2833{ 2834 nfs41_write_args *args = (nfs41_write_args*)argop->arg; 2835 unsigned char *data = args->data; 2836 2837 if (unexpected_op(argop->op, OP_WRITE)) 2838 return FALSE; 2839 2840 if (!xdr_stateid4(xdr, &args->stateid->stateid)) 2841 return FALSE; 2842 2843 if (!xdr_u_hyper(xdr, &args->offset)) 2844 return FALSE; 2845 2846 if (!xdr_u_int32_t(xdr, &args->stable)) 2847 return FALSE; 2848 2849 return xdr_bytes(xdr, (char **)&data, &args->data_len, NFS41_MAX_FILEIO_SIZE); 2850} 2851 2852static bool_t xdr_write_verf( 2853 XDR *xdr, 2854 nfs41_write_verf *verf) 2855{ 2856 if (!xdr_enum(xdr, (enum_t *)&verf->committed)) 2857 return FALSE; 2858 2859 return xdr_opaque(xdr, (char *)verf->verf, NFS4_VERIFIER_SIZE); 2860} 2861 2862static bool_t xdr_write_res_ok( 2863 XDR *xdr, 2864 nfs41_write_res_ok *res) 2865{ 2866 if (!xdr_u_int32_t(xdr, &res->count)) 2867 return FALSE; 2868 2869 return xdr_write_verf(xdr, res->verf); 2870} 2871 2872static bool_t decode_op_write( 2873 XDR *xdr, 2874 nfs_resop4 *resop) 2875{ 2876 nfs41_write_res *res = (nfs41_write_res*)resop->res; 2877 2878 if (unexpected_op(resop->op, OP_WRITE)) 2879 return FALSE; 2880 2881 if (!xdr_u_int32_t(xdr, &res->status)) 2882 return FALSE; 2883 2884 if (res->status == NFS4_OK) 2885 return xdr_write_res_ok(xdr, &res->resok4); 2886 2887 return TRUE; 2888} 2889 2890/* 2891 * OP_SECINFO_NO_NAME 2892 */ 2893static bool_t xdr_secinfo( 2894 XDR *xdr, 2895 nfs41_secinfo_info *secinfo) 2896{ 2897 if (!xdr_u_int32_t(xdr, &secinfo->sec_flavor)) 2898 return FALSE; 2899 if (secinfo->sec_flavor == RPCSEC_GSS) { 2900 char *p = secinfo->oid; 2901 if (!xdr_bytes(xdr, (char **)&p, &secinfo->oid_len, MAX_OID_LEN)) 2902 return FALSE; 2903 if (!xdr_u_int32_t(xdr, &secinfo->qop)) 2904 return FALSE; 2905 if (!xdr_enum(xdr, (enum_t *)&secinfo->type)) 2906 return FALSE; 2907 } 2908 return TRUE; 2909} 2910 2911static bool_t encode_op_secinfo_noname( 2912 XDR *xdr, 2913 nfs_argop4 *argop) 2914{ 2915 nfs41_secinfo_noname_args *args = (nfs41_secinfo_noname_args *)argop->arg; 2916 2917 if (unexpected_op(argop->op, OP_SECINFO_NO_NAME)) 2918 return FALSE; 2919 2920 if (!xdr_enum(xdr, (enum_t *)&args->type)) 2921 return FALSE; 2922 2923 return TRUE; 2924} 2925 2926static bool_t decode_op_secinfo_noname( 2927 XDR *xdr, 2928 nfs_resop4 *resop) 2929{ 2930 nfs41_secinfo_noname_res *res = (nfs41_secinfo_noname_res *)resop->res; 2931 nfs41_secinfo_info *secinfo = res->secinfo; 2932 if (unexpected_op(resop->op, OP_SECINFO_NO_NAME)) 2933 return FALSE; 2934 2935 if (!xdr_u_int32_t(xdr, &res->status)) 2936 return FALSE; 2937 2938 if (res->status == NFS4_OK) 2939 return xdr_array(xdr, (char**)&secinfo, &res->count, 2940 MAX_SECINFOS, sizeof(nfs41_secinfo_info), (xdrproc_t)xdr_secinfo); 2941 2942 return TRUE; 2943} 2944 2945/* 2946 * OP_SECINFO 2947 */ 2948static bool_t encode_op_secinfo( 2949 XDR *xdr, 2950 nfs_argop4 *argop) 2951{ 2952 nfs41_secinfo_args *args = (nfs41_secinfo_args *)argop->arg; 2953 2954 if (unexpected_op(argop->op, OP_SECINFO)) 2955 return FALSE; 2956 2957 if (!encode_component(xdr, args->name)) 2958 return FALSE; 2959 2960 return TRUE; 2961} 2962 2963static bool_t decode_op_secinfo( 2964 XDR *xdr, 2965 nfs_resop4 *resop) 2966{ 2967 nfs41_secinfo_noname_res *res = (nfs41_secinfo_noname_res *)resop->res; 2968 nfs41_secinfo_info *secinfo = res->secinfo; 2969 2970 if (unexpected_op(resop->op, OP_SECINFO)) 2971 return FALSE; 2972 2973 if (!xdr_u_int32_t(xdr, &res->status)) 2974 return FALSE; 2975 2976 if (res->status == NFS4_OK) 2977 return xdr_array(xdr, (char**)&secinfo, &res->count, 2978 MAX_SECINFOS, sizeof(nfs41_secinfo_info), (xdrproc_t)xdr_secinfo); 2979 2980 return TRUE; 2981} 2982/* 2983 * OP_GETDEVICEINFO 2984 */ 2985static bool_t encode_op_getdeviceinfo( 2986 XDR *xdr, 2987 nfs_argop4 *argop) 2988{ 2989 pnfs_getdeviceinfo_args *args = (pnfs_getdeviceinfo_args*)argop->arg; 2990 2991 if (unexpected_op(argop->op, OP_GETDEVICEINFO)) 2992 return FALSE; 2993 2994 if (!xdr_opaque(xdr, (char *)args->deviceid, PNFS_DEVICEID_SIZE)) 2995 return FALSE; 2996 2997 if (!xdr_enum(xdr, (enum_t *)&args->layout_type)) 2998 return FALSE; 2999 3000 if (!xdr_u_int32_t(xdr, &args->maxcount)) 3001 return FALSE; 3002 3003 return xdr_bitmap4(xdr, &args->notify_types); 3004} 3005 3006static bool_t xdr_stripe_indices( 3007 XDR *xdr, 3008 pnfs_stripe_indices *indices) 3009{ 3010 uint32_t i, count; 3011 3012 if (!xdr_u_int32_t(xdr, &count)) 3013 return FALSE; 3014 3015 if (count && count != indices->count) { 3016 uint32_t *tmp; 3017 tmp = realloc(indices->arr, count * sizeof(uint32_t)); 3018 if (tmp == NULL) 3019 return FALSE; 3020 indices->arr = tmp; 3021 ZeroMemory(indices->arr, count * sizeof(uint32_t)); 3022 indices->count = count; 3023 } 3024 3025 for (i = 0; i < indices->count; i++) { 3026 if (!xdr_u_int32_t(xdr, &indices->arr[i])) 3027 return FALSE; 3028 } 3029 return TRUE; 3030} 3031 3032static bool_t xdr_pnfs_addr( 3033 XDR *xdr, 3034 netaddr4 *addr) 3035{ 3036 uint32_t len; 3037 char *netid = addr->netid; 3038 char *uaddr = addr->uaddr; 3039 3040 if (xdr->x_op == XDR_ENCODE) 3041 len = sizeof(addr->netid); 3042 if (!xdr_bytes(xdr, &netid, &len, NFS41_NETWORK_ID_LEN)) 3043 return FALSE; 3044 3045 if (xdr->x_op == XDR_DECODE) { 3046 if (len < NFS41_NETWORK_ID_LEN) 3047 addr->netid[len] = 0; 3048 else 3049 addr->netid[NFS41_NETWORK_ID_LEN] = 0; 3050 } 3051 3052 if (xdr->x_op == XDR_ENCODE) 3053 len = sizeof(addr->uaddr); 3054 if (!xdr_bytes(xdr, &uaddr, &len, NFS41_UNIVERSAL_ADDR_LEN)) 3055 return FALSE; 3056 3057 if (xdr->x_op == XDR_DECODE){ 3058 if (len < NFS41_UNIVERSAL_ADDR_LEN) 3059 addr->uaddr[len] = 0; 3060 else 3061 addr->uaddr[NFS41_UNIVERSAL_ADDR_LEN] = 0; 3062 } 3063 3064 return TRUE; 3065} 3066 3067static bool_t xdr_multi_addr( 3068 XDR *xdr, 3069 multi_addr4 *list) 3070{ 3071 netaddr4 dummy, *dest; 3072 uint32_t i; 3073 3074 if (!xdr_u_int32_t(xdr, &list->count)) 3075 return FALSE; 3076 3077 for (i = 0; i < list->count; i++) { 3078 /* if there are too many addrs, decode the extras into 'dummy' */ 3079 dest = i < NFS41_ADDRS_PER_SERVER ? &list->arr[i] : &dummy; 3080 3081 if (!xdr_pnfs_addr(xdr, dest)) 3082 return FALSE; 3083 } 3084 return TRUE; 3085} 3086 3087static bool_t xdr_data_server_list( 3088 XDR *xdr, 3089 pnfs_data_server_list *servers) 3090{ 3091 uint32_t i, count; 3092 3093 if (!xdr_u_int32_t(xdr, &count)) 3094 return FALSE; 3095 3096 if (count && count != servers->count) { 3097 pnfs_data_server *tmp; 3098 /* clear data server clients; they're still cached with nfs41_root, 3099 * so pnfs_data_server_client() will look them up again */ 3100 for (i = 0; i < servers->count; i++) 3101 servers->arr[i].client = NULL; 3102 3103 tmp = realloc(servers->arr, count * sizeof(pnfs_data_server)); 3104 if (tmp == NULL) 3105 return FALSE; 3106 servers->arr = tmp; 3107 ZeroMemory(servers->arr, count * sizeof(pnfs_data_server)); 3108 for (i = servers->count; i < count; i++) /* initialize new elements */ 3109 InitializeSRWLock(&servers->arr[i].lock); 3110 servers->count = count; 3111 } 3112 3113 for (i = 0; i < servers->count; i++) { 3114 if (!xdr_multi_addr(xdr, &servers->arr[i].addrs)) 3115 return FALSE; 3116 } 3117 return TRUE; 3118} 3119 3120static bool_t xdr_file_device( 3121 XDR *xdr, 3122 pnfs_file_device *device) 3123{ 3124 if (!xdr_stripe_indices(xdr, &device->stripes)) 3125 return FALSE; 3126 3127 return xdr_data_server_list(xdr, &device->servers); 3128} 3129 3130static bool_t decode_getdeviceinfo_ok( 3131 XDR *xdr, 3132 pnfs_getdeviceinfo_res_ok *res_ok) 3133{ 3134 u_int32_t len_ignored; 3135 3136 if (!xdr_enum(xdr, (enum_t *)&res_ok->device->device.type)) 3137 return FALSE; 3138 3139 if (res_ok->device->device.type != PNFS_LAYOUTTYPE_FILE) 3140 return FALSE; 3141 3142 if (!xdr_u_int32_t(xdr, &len_ignored)) 3143 return FALSE; 3144 3145 if (!xdr_file_device(xdr, res_ok->device)) 3146 return FALSE; 3147 3148 return xdr_bitmap4(xdr, &res_ok->notification); 3149} 3150 3151static bool_t decode_op_getdeviceinfo( 3152 XDR *xdr, 3153 nfs_resop4 *resop) 3154{ 3155 pnfs_getdeviceinfo_res *res = (pnfs_getdeviceinfo_res*)resop->res; 3156 3157 if (unexpected_op(resop->op, OP_GETDEVICEINFO)) 3158 return FALSE; 3159 3160 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status)) 3161 return FALSE; 3162 3163 switch (res->status) { 3164 case NFS4_OK: 3165 return decode_getdeviceinfo_ok(xdr, &res->u.res_ok); 3166 break; 3167 case NFS4ERR_TOOSMALL: 3168 { 3169 uint32_t ignored; 3170 return xdr_u_int32_t(xdr, &ignored); 3171 } 3172 break; 3173 } 3174 return TRUE; 3175} 3176 3177 3178/* 3179 * OP_LAYOUTCOMMIT 3180 */ 3181static bool_t encode_op_layoutcommit( 3182 XDR *xdr, 3183 nfs_argop4 *argop) 3184{ 3185 pnfs_layoutcommit_args *args = (pnfs_layoutcommit_args*)argop->arg; 3186 bool_t false_bool = FALSE; 3187 bool_t true_bool = TRUE; 3188 enum_t pnfs_layout = PNFS_LAYOUTTYPE_FILE; 3189 uint32_t zero = 0; 3190 3191 if (unexpected_op(argop->op, OP_LAYOUTCOMMIT)) 3192 return FALSE; 3193 3194 if (!xdr_u_hyper(xdr, &args->offset)) 3195 return FALSE; 3196 3197 if (!xdr_u_hyper(xdr, &args->length)) 3198 return FALSE; 3199 3200 if (!xdr_bool(xdr, &false_bool)) /* loca_reclaim = 0 */ 3201 return FALSE; 3202 3203 if (!xdr_stateid4(xdr, args->stateid)) 3204 return FALSE; 3205 3206 /* loca_last_write_offset */ 3207 if (args->new_offset) { 3208 if (!xdr_bool(xdr, &true_bool)) 3209 return FALSE; 3210 3211 if (!xdr_u_hyper(xdr, args->new_offset)) 3212 return FALSE; 3213 } else { 3214 if (!xdr_bool(xdr, &false_bool)) 3215 return FALSE; 3216 } 3217 3218 /* loca_time_modify */ 3219 if (args->new_time) { 3220 if (!xdr_bool(xdr, &true_bool)) 3221 return FALSE; 3222 3223 if (!xdr_nfstime4(xdr, args->new_time)) 3224 return FALSE; 3225 } else { 3226 if (!xdr_bool(xdr, &false_bool)) 3227 return FALSE; 3228 } 3229 3230 /* loca_layoutupdate */ 3231 if (!xdr_enum(xdr, &pnfs_layout)) 3232 return FALSE; 3233 3234 return xdr_u_int32_t(xdr, &zero); 3235} 3236 3237static bool_t decode_op_layoutcommit( 3238 XDR *xdr, 3239 nfs_resop4 *resop) 3240{ 3241 pnfs_layoutcommit_res *res = (pnfs_layoutcommit_res*)resop->res; 3242 3243 if (unexpected_op(resop->op, OP_LAYOUTCOMMIT)) 3244 return FALSE; 3245 3246 if (!xdr_u_int32_t(xdr, &res->status)) 3247 return FALSE; 3248 3249 if (res->status == NFS4_OK) { 3250 if (!xdr_bool(xdr, &res->has_new_size)) 3251 return FALSE; 3252 3253 if (res->has_new_size) 3254 if (!xdr_u_hyper(xdr, &res->new_size)) 3255 return FALSE; 3256 } 3257 return TRUE; 3258} 3259 3260/* 3261 * OP_LAYOUTGET 3262 */ 3263static bool_t encode_op_layoutget( 3264 XDR *xdr, 3265 nfs_argop4 *argop) 3266{ 3267 pnfs_layoutget_args *args = (pnfs_layoutget_args*)argop->arg; 3268 3269 if (unexpected_op(argop->op, OP_LAYOUTGET)) 3270 return FALSE; 3271 3272 if (!xdr_bool(xdr, &args->signal_layout_avail)) 3273 return FALSE; 3274 3275 if (!xdr_u_int32_t(xdr, (u_int32_t *)&args->layout_type)) 3276 return FALSE; 3277 3278 if (!xdr_u_int32_t(xdr, (u_int32_t *)&args->iomode)) 3279 return FALSE; 3280 3281 if (!xdr_u_hyper(xdr, &args->offset)) 3282 return FALSE; 3283 3284 if (!xdr_u_hyper(xdr, &args->length)) 3285 return FALSE; 3286 3287 if (!xdr_u_hyper(xdr, &args->minlength)) 3288 return FALSE; 3289 3290 if (!xdr_stateid4(xdr, &args->stateid->stateid)) 3291 return FALSE; 3292 3293 return xdr_u_int32_t(xdr, &args->maxcount); 3294} 3295 3296static bool_t decode_file_layout_handles( 3297 XDR *xdr, 3298 pnfs_file_layout_handles *handles) 3299{ 3300 uint32_t i, count; 3301 3302 if (!xdr_u_int32_t(xdr, &count)) 3303 return FALSE; 3304 3305 if (count && count != handles->count) { 3306 nfs41_path_fh *tmp; 3307 tmp = realloc(handles->arr, count * sizeof(nfs41_path_fh)); 3308 if (tmp == NULL) 3309 return FALSE; 3310 handles->arr = tmp; 3311 ZeroMemory(handles->arr, count * sizeof(nfs41_path_fh)); 3312 handles->count = count; 3313 } 3314 3315 for (i = 0; i < handles->count; i++) { 3316 if (!xdr_fh(xdr, &handles->arr[i].fh)) 3317 return FALSE; 3318 } 3319 return TRUE; 3320} 3321 3322static bool_t decode_file_layout( 3323 XDR *xdr, 3324 struct list_entry *list, 3325 pnfs_layout *base) 3326{ 3327 pnfs_file_layout *layout; 3328 u_int32_t len_ignored; 3329 3330 if (!xdr_u_int32_t(xdr, &len_ignored)) 3331 return FALSE; 3332 3333 layout = calloc(1, sizeof(pnfs_file_layout)); 3334 if (layout == NULL) 3335 return FALSE; 3336 3337 layout->layout.offset = base->offset; 3338 layout->layout.length = base->length; 3339 layout->layout.iomode = base->iomode; 3340 layout->layout.type = base->type; 3341 list_init(&layout->layout.entry); 3342 3343 if (!xdr_opaque(xdr, (char *)layout->deviceid, PNFS_DEVICEID_SIZE)) 3344 goto out_error; 3345 3346 if (!xdr_u_int32_t(xdr, &layout->util)) 3347 goto out_error; 3348 3349 if (!xdr_u_int32_t(xdr, &layout->first_index)) 3350 goto out_error; 3351 3352 if (!xdr_u_hyper(xdr, &layout->pattern_offset)) 3353 goto out_error; 3354 3355 if (!decode_file_layout_handles(xdr, &layout->filehandles)) 3356 goto out_error; 3357 3358 list_add_tail(list, &layout->layout.entry); 3359 return TRUE; 3360 3361out_error: 3362 free(layout); 3363 return FALSE; 3364} 3365 3366static bool_t decode_layout( 3367 XDR *xdr, 3368 struct list_entry *list) 3369{ 3370 pnfs_layout layout; 3371 3372 if (!xdr_u_hyper(xdr, &layout.offset)) 3373 return FALSE; 3374 3375 if (!xdr_u_hyper(xdr, &layout.length)) 3376 return FALSE; 3377 3378 if (!xdr_enum(xdr, (enum_t *)&layout.iomode)) 3379 return FALSE; 3380 3381 if (!xdr_enum(xdr, (enum_t *)&layout.type)) 3382 return FALSE; 3383 3384 switch (layout.type) { 3385 case PNFS_LAYOUTTYPE_FILE: 3386 return decode_file_layout(xdr, list, &layout); 3387 3388 default: 3389 eprintf("%s: received non-FILE layout type, %d\n", 3390 "decode_file_layout", layout.type); 3391 } 3392 return FALSE; 3393} 3394 3395static bool_t decode_layout_res_ok( 3396 XDR *xdr, 3397 pnfs_layoutget_res_ok *res) 3398{ 3399 uint32_t i; 3400 3401 if (!xdr_bool(xdr, &res->return_on_close)) 3402 return FALSE; 3403 3404 if (!xdr_stateid4(xdr, &res->stateid)) 3405 return FALSE; 3406 3407 if (!xdr_u_int32_t(xdr, &res->count)) 3408 return FALSE; 3409 3410 for (i = 0; i < res->count; i++) 3411 if (!decode_layout(xdr, &res->layouts)) 3412 return FALSE; 3413 return TRUE; 3414} 3415 3416static bool_t decode_op_layoutget( 3417 XDR *xdr, 3418 nfs_resop4 *resop) 3419{ 3420 pnfs_layoutget_res *res = (pnfs_layoutget_res*)resop->res; 3421 3422 if (unexpected_op(resop->op, OP_LAYOUTGET)) 3423 return FALSE; 3424 3425 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status)) 3426 return FALSE; 3427 3428 switch (res->status) { 3429 case NFS4_OK: 3430 return decode_layout_res_ok(xdr, res->u.res_ok); 3431 case NFS4ERR_LAYOUTTRYLATER: 3432 return xdr_bool(xdr, &res->u.will_signal_layout_avail); 3433 } 3434 return TRUE; 3435} 3436 3437 3438/* 3439 * OP_LAYOUTRETURN 3440 */ 3441static bool_t encode_op_layoutreturn( 3442 XDR *xdr, 3443 nfs_argop4 *argop) 3444{ 3445 pnfs_layoutreturn_args *args = (pnfs_layoutreturn_args*)argop->arg; 3446 3447 if (unexpected_op(argop->op, OP_LAYOUTRETURN)) 3448 return FALSE; 3449 3450 if (!xdr_bool(xdr, &args->reclaim)) 3451 return FALSE; 3452 3453 if (!xdr_enum(xdr, (enum_t *)&args->type)) 3454 return FALSE; 3455 3456 if (!xdr_enum(xdr, (enum_t *)&args->iomode)) 3457 return FALSE; 3458 3459 if (!xdr_enum(xdr, (enum_t *)&args->return_type)) 3460 return FALSE; 3461 3462 if (args->return_type == PNFS_RETURN_FILE) { 3463 u_int32_t zero = 0; 3464 3465 if (!xdr_u_hyper(xdr, &args->offset)) 3466 return FALSE; 3467 3468 if (!xdr_u_hyper(xdr, &args->length)) 3469 return FALSE; 3470 3471 if (!xdr_stateid4(xdr, args->stateid)) 3472 return FALSE; 3473 3474 return xdr_u_int32_t(xdr, &zero); /* size of lrf_body is 0 */ 3475 } else { 3476 eprintf("%s: layout type (%d) is not PNFS_RETURN_FILE!\n", 3477 "encode_op_layoutreturn", args->return_type); 3478 return FALSE; 3479 } 3480} 3481 3482static bool_t decode_op_layoutreturn( 3483 XDR *xdr, 3484 nfs_resop4 *resop) 3485{ 3486 pnfs_layoutreturn_res *res = (pnfs_layoutreturn_res*)resop->res; 3487 3488 if (unexpected_op(resop->op, OP_LAYOUTRETURN)) 3489 return FALSE; 3490 3491 if (!xdr_u_int32_t(xdr, (uint32_t *)&res->status)) 3492 return FALSE; 3493 3494 if (res->status == NFS4_OK) { 3495 if (!xdr_bool(xdr, &res->stateid_present)) 3496 return FALSE; 3497 3498 if (res->stateid_present) 3499 return xdr_stateid4(xdr, &res->stateid); 3500 } 3501 return TRUE; 3502} 3503 3504 3505/* op encode/decode table */ 3506typedef bool_t (*nfs_op_encode_proc)(XDR*, nfs_argop4*); 3507typedef bool_t (*nfs_op_decode_proc)(XDR*, nfs_resop4*); 3508 3509typedef struct __op_table_entry { 3510 nfs_op_encode_proc encode; 3511 nfs_op_decode_proc decode; 3512} op_table_entry; 3513 3514/* table of encode/decode functions, indexed by operation number */ 3515static const op_table_entry g_op_table[] = { 3516 { NULL, NULL }, /* 0 unused */ 3517 { NULL, NULL }, /* 1 unused */ 3518 { NULL, NULL }, /* 2 unused */ 3519 { encode_op_access, decode_op_access }, /* OP_ACCESS = 3 */ 3520 { encode_op_close, decode_op_close }, /* OP_CLOSE = 4 */ 3521 { encode_op_commit, decode_op_commit }, /* OP_COMMIT = 5 */ 3522 { encode_op_create, decode_op_create }, /* OP_CREATE = 6 */ 3523 { encode_op_delegpurge, decode_op_delegpurge }, /* OP_DELEGPURGE = 7 */ 3524 { encode_op_delegreturn, decode_op_delegreturn }, /* OP_DELEGRETURN = 8 */ 3525 { encode_op_getattr, decode_op_getattr }, /* OP_GETATTR = 9 */ 3526 { encode_op_getfh, decode_op_getfh }, /* OP_GETFH = 10 */ 3527 { encode_op_link, decode_op_link }, /* OP_LINK = 11 */ 3528 { encode_op_lock, decode_op_lock }, /* OP_LOCK = 12 */ 3529 { encode_op_lockt, decode_op_lockt }, /* OP_LOCKT = 13 */ 3530 { encode_op_locku, decode_op_locku }, /* OP_LOCKU = 14 */ 3531 { encode_op_lookup, decode_op_lookup }, /* OP_LOOKUP = 15 */ 3532 { NULL, NULL }, /* OP_LOOKUPP = 16 */ 3533 { NULL, NULL }, /* OP_NVERIFY = 17 */ 3534 { encode_op_open, decode_op_open }, /* OP_OPEN = 18 */ 3535 { encode_op_openattr, decode_op_openattr }, /* OP_OPENATTR = 19 */ 3536 { NULL, NULL }, /* OP_OPEN_CONFIRM = 20 */ 3537 { NULL, NULL }, /* OP_OPEN_DOWNGRADE = 21 */ 3538 { encode_op_putfh, decode_op_putfh }, /* OP_PUTFH = 22 */ 3539 { NULL, NULL }, /* OP_PUTPUBFH = 23 */ 3540 { encode_op_putrootfh, decode_op_putrootfh }, /* OP_PUTROOTFH = 24 */ 3541 { encode_op_read, decode_op_read }, /* OP_READ = 25 */ 3542 { encode_op_readdir, decode_op_readdir }, /* OP_READDIR = 26 */ 3543 { encode_op_readlink, decode_op_readlink }, /* OP_READLINK = 27 */ 3544 { encode_op_remove, decode_op_remove }, /* OP_REMOVE = 28 */ 3545 { encode_op_rename, decode_op_rename }, /* OP_RENAME = 29 */ 3546 { NULL, NULL }, /* OP_RENEW = 30 */ 3547 { encode_op_restorefh, decode_op_restorefh }, /* OP_RESTOREFH = 31 */ 3548 { encode_op_savefh, decode_op_savefh }, /* OP_SAVEFH = 32 */ 3549 { encode_op_secinfo, decode_op_secinfo }, /* OP_SECINFO = 33 */ 3550 { encode_op_setattr, decode_op_setattr }, /* OP_SETATTR = 34 */ 3551 { NULL, NULL }, /* OP_SETCLIENTID = 35 */ 3552 { NULL, NULL }, /* OP_SETCLIENTID_CONFIRM = 36 */ 3553 { NULL, NULL }, /* OP_VERIFY = 37 */ 3554 { encode_op_write, decode_op_write }, /* OP_WRITE = 38 */ 3555 { NULL, NULL }, /* OP_RELEASE_LOCKOWNER = 39 */ 3556 { NULL, NULL }, /* OP_BACKCHANNEL_CTL = 40 */ 3557 { encode_op_bind_conn_to_session, decode_op_bind_conn_to_session }, /* OP_BIND_CONN_TO_SESSION = 41 */ 3558 { encode_op_exchange_id, decode_op_exchange_id }, /* OP_EXCHANGE_ID = 42 */ 3559 { encode_op_create_session, decode_op_create_session }, /* OP_CREATE_SESSION = 43 */ 3560 { encode_op_destroy_session, decode_op_destroy_session }, /* OP_DESTROY_SESSION = 44 */ 3561 { encode_op_free_stateid, decode_op_free_stateid }, /* OP_FREE_STATEID = 45 */ 3562 { NULL, NULL }, /* OP_GET_DIR_DELEGATION = 46 */ 3563 { encode_op_getdeviceinfo, decode_op_getdeviceinfo }, /* OP_GETDEVICEINFO = 47 */ 3564 { NULL, NULL }, /* OP_GETDEVICELIST = 48 */ 3565 { encode_op_layoutcommit, decode_op_layoutcommit }, /* OP_LAYOUTCOMMIT = 49 */ 3566 { encode_op_layoutget, decode_op_layoutget }, /* OP_LAYOUTGET = 50 */ 3567 { encode_op_layoutreturn, decode_op_layoutreturn }, /* OP_LAYOUTRETURN = 51 */ 3568 { encode_op_secinfo_noname, decode_op_secinfo_noname }, /* OP_SECINFO_NO_NAME = 52 */ 3569 { encode_op_sequence, decode_op_sequence }, /* OP_SEQUENCE = 53 */ 3570 { NULL, NULL }, /* OP_SET_SSV = 54 */ 3571 { encode_op_test_stateid, decode_op_test_stateid }, /* OP_TEST_STATEID = 55 */ 3572 { encode_op_want_delegation, decode_op_want_delegation }, /* OP_WANT_DELEGATION = 56 */ 3573 { encode_op_destroy_clientid, decode_op_destroy_clientid }, /* OP_DESTROY_CLIENTID = 57 */ 3574 { encode_op_reclaim_complete, decode_op_reclaim_complete }, /* OP_RECLAIM_COMPLETE = 58 */ 3575}; 3576#ifdef __REACTOS__ 3577static const uint32_t g_op_table_size = (sizeof(g_op_table) / sizeof(g_op_table[0])); 3578#else 3579static const uint32_t g_op_table_size = ARRAYSIZE(g_op_table); 3580#endif 3581 3582static const op_table_entry* op_table_find(uint32_t op) 3583{ 3584 return op >= g_op_table_size ? NULL : &g_op_table[op]; 3585} 3586 3587 3588/* 3589 * COMPOUND 3590 */ 3591bool_t nfs_encode_compound( 3592 XDR *xdr, 3593 caddr_t *pargs) 3594{ 3595 unsigned char *tag; 3596 3597 nfs41_compound_args *args = (nfs41_compound_args*)pargs; 3598 uint32_t i; 3599 const op_table_entry *entry; 3600 3601 tag = args->tag; 3602 if (!xdr_bytes(xdr, (char **)&tag, &args->tag_len, NFS4_OPAQUE_LIMIT)) 3603 return FALSE; 3604 3605 if (!xdr_u_int32_t(xdr, &args->minorversion)) 3606 return FALSE; 3607 3608 if (!xdr_u_int32_t(xdr, &args->argarray_count)) 3609 return FALSE; 3610 3611 for (i = 0; i < args->argarray_count; i++) 3612 { 3613 entry = op_table_find(args->argarray[i].op); 3614 if (entry == NULL || entry->encode == NULL) 3615 return FALSE; 3616 3617 if (!xdr_u_int32_t(xdr, &args->argarray[i].op)) 3618 return FALSE; 3619 if (!entry->encode(xdr, &args->argarray[i])) 3620 return FALSE; 3621 } 3622 return TRUE; 3623} 3624 3625bool_t nfs_decode_compound( 3626 XDR *xdr, 3627 caddr_t *pres) 3628{ 3629 nfs41_compound_res *res = (nfs41_compound_res*)pres; 3630 uint32_t i, expected_count, expected_op; 3631 const op_table_entry *entry; 3632 unsigned char *tag = res->tag; 3633 3634 if (!xdr_u_int32_t(xdr, &res->status)) 3635 return FALSE; 3636 3637 if (!xdr_bytes(xdr, (char **)&tag, &res->tag_len, NFS4_OPAQUE_LIMIT)) 3638 return FALSE; 3639 3640 expected_count = res->resarray_count; 3641 if (!xdr_u_int32_t(xdr, &res->resarray_count)) 3642 return FALSE; 3643 3644 /* validate the number of operations against what we sent */ 3645 if (res->resarray_count > expected_count) { 3646 eprintf("reply with %u operations, only sent %u!\n", 3647 res->resarray_count, expected_count); 3648 return FALSE; 3649 } else if (res->resarray_count < expected_count && 3650 res->status == NFS4_OK) { 3651 /* illegal for a server to reply with less operations, 3652 * unless one of them fails */ 3653 eprintf("successful reply with only %u operations, sent %u!\n", 3654 res->resarray_count, expected_count); 3655 return FALSE; 3656 } 3657 3658 for (i = 0; i < res->resarray_count; i++) 3659 { 3660 expected_op = res->resarray[i].op; 3661 if (!xdr_u_int32_t(xdr, &res->resarray[i].op)) 3662 return FALSE; 3663 3664 /* validate each operation number against what we sent */ 3665 if (res->resarray[i].op != expected_op) { 3666 eprintf("reply with %s in operation %u, expected %s!\n", 3667 nfs_opnum_to_string(res->resarray[i].op), i+1, 3668 nfs_opnum_to_string(expected_op)); 3669 return FALSE; 3670 } 3671 3672 entry = op_table_find(res->resarray[i].op); 3673 if (entry == NULL || entry->decode == NULL) 3674 return FALSE; 3675 if (!entry->decode(xdr, &res->resarray[i])) 3676 return FALSE; 3677 } 3678 return TRUE; 3679}