1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 14 * Copyright 2022-2023 RackTop Systems, Inc. 15 */ 16 17 /* 18 * Dispatch function for SMB2_QUERY_INFO 19 * 20 * [MS-FSCC 2.4] If a file system does not support ... 21 * an Information Classs, NT_STATUS_INVALID_PARAMETER... 22 */ 23 24 #include <smbsrv/smb2_kproto.h> 25 #include <smbsrv/smb_fsops.h> 26 #include <smbsrv/ntifs.h> 27 28 static uint32_t smb2_qif_basic(smb_request_t *, smb_queryinfo_t *); 29 static uint32_t smb2_qif_standard(smb_request_t *, smb_queryinfo_t *); 30 static uint32_t smb2_qif_internal(smb_request_t *, smb_queryinfo_t *); 31 static uint32_t smb2_qif_ea_size(smb_request_t *, smb_queryinfo_t *); 32 static uint32_t smb2_qif_access(smb_request_t *, smb_queryinfo_t *); 33 static uint32_t smb2_qif_name(smb_request_t *, smb_queryinfo_t *); 34 static uint32_t smb2_qif_normalized_name(smb_request_t *, smb_queryinfo_t *); 35 static uint32_t smb2_qif_position(smb_request_t *, smb_queryinfo_t *); 36 static uint32_t smb2_qif_full_ea(smb_request_t *, smb_queryinfo_t *); 37 static uint32_t smb2_qif_mode(smb_request_t *, smb_queryinfo_t *); 38 static uint32_t smb2_qif_alignment(smb_request_t *, smb_queryinfo_t *); 39 static uint32_t smb2_qif_all(smb_request_t *, smb_queryinfo_t *); 40 static uint32_t smb2_qif_altname(smb_request_t *, smb_queryinfo_t *); 41 static uint32_t smb2_qif_stream(smb_request_t *, smb_queryinfo_t *); 42 static uint32_t smb2_qif_pipe(smb_request_t *, smb_queryinfo_t *); 43 static uint32_t smb2_qif_pipe_lcl(smb_request_t *, smb_queryinfo_t *); 44 static uint32_t smb2_qif_pipe_rem(smb_request_t *, smb_queryinfo_t *); 45 static uint32_t smb2_qif_compr(smb_request_t *, smb_queryinfo_t *); 46 static uint32_t smb2_qif_opens(smb_request_t *, smb_queryinfo_t *); 47 static uint32_t smb2_qif_tags(smb_request_t *, smb_queryinfo_t *); 48 static uint32_t smb2_qif_id_info(smb_request_t *, smb_queryinfo_t *); 49 50 /* 51 * MS-SMB2 3.3.5.20.1 says (in a windows behavior note) that 52 * 2012R2 and older fill in the FileNameInformation. 53 * Default to the new behavior. 54 */ 55 boolean_t smb2_qif_all_get_name = B_FALSE; 56 57 uint32_t 58 smb2_qinfo_file(smb_request_t *sr, smb_queryinfo_t *qi) 59 { 60 smb_ofile_t *of = sr->fid_ofile; 61 uint_t mask = 0; 62 boolean_t getstd = B_FALSE; 63 boolean_t getname = B_FALSE; 64 uint32_t status; 65 66 /* 67 * Which attributes do we need from the FS? 68 */ 69 switch (qi->qi_InfoClass) { 70 case FileBasicInformation: 71 mask = SMB_AT_BASIC; 72 break; 73 case FileStandardInformation: 74 mask = SMB_AT_STANDARD; 75 getstd = B_TRUE; 76 break; 77 case FileInternalInformation: 78 mask = SMB_AT_NODEID; 79 break; 80 case FileAllInformation: 81 mask = SMB_AT_ALL; 82 getstd = B_TRUE; 83 if (smb2_qif_all_get_name) 84 getname = B_TRUE; 85 break; 86 87 case FileNameInformation: 88 case FileNormalizedNameInformation: 89 getname = B_TRUE; 90 break; 91 92 case FileAlternateNameInformation: 93 mask = SMB_AT_NODEID; 94 getname = B_TRUE; 95 break; 96 97 case FileStreamInformation: 98 mask = SMB_AT_STANDARD; 99 getstd = B_TRUE; 100 break; 101 102 case FileCompressionInformation: 103 mask = SMB_AT_SIZE | SMB_AT_ALLOCSZ; 104 break; 105 106 case FileNetworkOpenInformation: 107 mask = SMB_AT_BASIC | SMB_AT_STANDARD; 108 break; 109 110 case FileIdInformation: 111 mask = SMB_AT_NODEID; 112 break; 113 114 default: 115 break; 116 } 117 118 qi->qi_attr.sa_mask = mask; 119 qi->qi_node = of->f_node; 120 if (mask & SMB_AT_ALL) { 121 status = smb2_ofile_getattr(sr, of, &qi->qi_attr); 122 if (status) 123 return (status); 124 } 125 if (getstd) { 126 status = smb2_ofile_getstd(of, qi); 127 if (status) 128 return (status); 129 } 130 if (getname) { 131 status = smb2_ofile_getname(of, qi); 132 if (status) 133 return (status); 134 } 135 136 switch (qi->qi_InfoClass) { 137 case FileBasicInformation: 138 status = smb2_qif_basic(sr, qi); 139 break; 140 case FileStandardInformation: 141 status = smb2_qif_standard(sr, qi); 142 break; 143 case FileInternalInformation: 144 status = smb2_qif_internal(sr, qi); 145 break; 146 case FileEaInformation: 147 status = smb2_qif_ea_size(sr, qi); 148 break; 149 case FileAccessInformation: 150 status = smb2_qif_access(sr, qi); 151 break; 152 case FileNameInformation: 153 status = smb2_qif_name(sr, qi); 154 break; 155 case FileNormalizedNameInformation: 156 status = smb2_qif_normalized_name(sr, qi); 157 break; 158 case FilePositionInformation: 159 status = smb2_qif_position(sr, qi); 160 break; 161 case FileFullEaInformation: 162 status = smb2_qif_full_ea(sr, qi); 163 break; 164 case FileModeInformation: 165 status = smb2_qif_mode(sr, qi); 166 break; 167 case FileAlignmentInformation: 168 status = smb2_qif_alignment(sr, qi); 169 break; 170 case FileAllInformation: 171 status = smb2_qif_all(sr, qi); 172 break; 173 case FileAlternateNameInformation: 174 status = smb2_qif_altname(sr, qi); 175 break; 176 case FileStreamInformation: 177 status = smb2_qif_stream(sr, qi); 178 break; 179 case FilePipeInformation: 180 status = smb2_qif_pipe(sr, qi); 181 break; 182 case FilePipeLocalInformation: 183 status = smb2_qif_pipe_lcl(sr, qi); 184 break; 185 case FilePipeRemoteInformation: 186 status = smb2_qif_pipe_rem(sr, qi); 187 break; 188 case FileCompressionInformation: 189 status = smb2_qif_compr(sr, qi); 190 break; 191 case FileNetworkOpenInformation: 192 status = smb2_qif_opens(sr, qi); 193 break; 194 case FileAttributeTagInformation: 195 status = smb2_qif_tags(sr, qi); 196 break; 197 case FileIdInformation: 198 status = smb2_qif_id_info(sr, qi); 199 break; 200 default: 201 status = NT_STATUS_INVALID_INFO_CLASS; 202 break; 203 } 204 205 return (status); 206 } 207 208 /* 209 * FileAllInformation 210 * 211 * This returns a concatenation of: 212 * FileBasicInformation 213 * FileStandardInformation 214 * FileInternalInformation 215 * FileEaInformation 216 * FilePositionInformation 217 * FileModeInformation 218 * FileAlignmentInformation 219 * FileNameInformation 220 * 221 * Note: FileNameInformation is all zero on Win2016 and later. 222 */ 223 static uint32_t 224 smb2_qif_all(smb_request_t *sr, smb_queryinfo_t *qi) 225 { 226 uint32_t status; 227 228 status = smb2_qif_basic(sr, qi); 229 if (status) 230 return (status); 231 status = smb2_qif_standard(sr, qi); 232 if (status) 233 return (status); 234 status = smb2_qif_internal(sr, qi); 235 if (status) 236 return (status); 237 status = smb2_qif_ea_size(sr, qi); 238 if (status) 239 return (status); 240 status = smb2_qif_position(sr, qi); 241 if (status) 242 return (status); 243 status = smb2_qif_mode(sr, qi); 244 if (status) 245 return (status); 246 status = smb2_qif_alignment(sr, qi); 247 if (status) 248 return (status); 249 250 /* See smb2_qif_all_get_name */ 251 if (qi->qi_namelen != 0) { 252 /* Win2012r2 and earlier fill it in. */ 253 status = smb2_qif_name(sr, qi); 254 } else { 255 /* Win2016 and later just put zeros. */ 256 int rc = smb_mbc_encodef(&sr->raw_data, "10."); 257 status = (rc == 0) ? 0 : NT_STATUS_BUFFER_OVERFLOW; 258 } 259 260 return (status); 261 } 262 263 /* 264 * FileBasicInformation 265 * See also: 266 * case SMB_QUERY_FILE_BASIC_INFO: 267 * case SMB_FILE_BASIC_INFORMATION: 268 */ 269 static uint32_t 270 smb2_qif_basic(smb_request_t *sr, smb_queryinfo_t *qi) 271 { 272 smb_attr_t *sa = &qi->qi_attr; 273 int rc; 274 275 ASSERT((sa->sa_mask & SMB_AT_BASIC) == SMB_AT_BASIC); 276 277 rc = smb_mbc_encodef( 278 &sr->raw_data, "TTTTll", 279 &sa->sa_crtime, /* T */ 280 &sa->sa_vattr.va_atime, /* T */ 281 &sa->sa_vattr.va_mtime, /* T */ 282 &sa->sa_vattr.va_ctime, /* T */ 283 sa->sa_dosattr, /* l */ 284 0); /* reserved */ /* l */ 285 if (rc != 0) 286 return (NT_STATUS_BUFFER_OVERFLOW); 287 288 return (0); 289 } 290 291 /* 292 * FileStandardInformation 293 * See also: 294 * SMB_QUERY_FILE_STANDARD_INFO 295 * SMB_FILE_STANDARD_INFORMATION 296 */ 297 static uint32_t 298 smb2_qif_standard(smb_request_t *sr, smb_queryinfo_t *qi) 299 { 300 smb_attr_t *sa = &qi->qi_attr; 301 int rc; 302 303 ASSERT((sa->sa_mask & SMB_AT_STANDARD) == SMB_AT_STANDARD); 304 305 rc = smb_mbc_encodef( 306 &sr->raw_data, "qqlbbw", 307 sa->sa_allocsz, /* q */ 308 sa->sa_vattr.va_size, /* q */ 309 sa->sa_vattr.va_nlink, /* l */ 310 qi->qi_delete_on_close, /* b */ 311 qi->qi_isdir, /* b */ 312 0); /* reserved */ /* w */ 313 if (rc != 0) 314 return (NT_STATUS_BUFFER_OVERFLOW); 315 316 return (0); 317 } 318 319 /* 320 * FileInternalInformation 321 * See also: 322 * SMB_FILE_INTERNAL_INFORMATION 323 */ 324 static uint32_t 325 smb2_qif_internal(smb_request_t *sr, smb_queryinfo_t *qi) 326 { 327 smb_attr_t *sa = &qi->qi_attr; 328 u_longlong_t nodeid; 329 int rc; 330 331 ASSERT((sa->sa_mask & SMB_AT_NODEID) == SMB_AT_NODEID); 332 nodeid = sa->sa_vattr.va_nodeid; 333 334 if (smb2_aapl_use_file_ids == 0 && 335 (sr->session->s_flags & SMB_SSN_AAPL_CCEXT) != 0) 336 nodeid = 0; 337 338 rc = smb_mbc_encodef( 339 &sr->raw_data, "q", 340 nodeid); /* q */ 341 if (rc != 0) 342 return (NT_STATUS_BUFFER_OVERFLOW); 343 344 return (0); 345 } 346 347 /* 348 * FileEaInformation 349 * See also: 350 * SMB_QUERY_FILE_EA_INFO 351 * SMB_FILE_EA_INFORMATION 352 */ 353 static uint32_t 354 smb2_qif_ea_size(smb_request_t *sr, smb_queryinfo_t *qi) 355 { 356 _NOTE(ARGUNUSED(qi)) 357 int rc; 358 359 rc = smb_mbc_encodef( 360 &sr->raw_data, "l", 0); 361 if (rc != 0) 362 return (NT_STATUS_BUFFER_OVERFLOW); 363 364 return (0); 365 } 366 367 /* 368 * FileFullEaInformation 369 * We could put EAs in a named stream... 370 */ 371 /* ARGSUSED */ 372 static uint32_t 373 smb2_qif_full_ea(smb_request_t *sr, smb_queryinfo_t *qi) 374 { 375 return (NT_STATUS_NO_EAS_ON_FILE); 376 } 377 378 /* 379 * FileAccessInformation 380 */ 381 static uint32_t 382 smb2_qif_access(smb_request_t *sr, smb_queryinfo_t *qi) 383 { 384 _NOTE(ARGUNUSED(qi)) 385 smb_ofile_t *of = sr->fid_ofile; 386 int rc; 387 388 rc = smb_mbc_encodef( 389 &sr->raw_data, "l", 390 of->f_granted_access); 391 if (rc != 0) 392 return (NT_STATUS_BUFFER_OVERFLOW); 393 394 return (0); 395 } 396 397 /* 398 * FileNameInformation 399 * See also: 400 * SMB_QUERY_FILE_NAME_INFO 401 * SMB_FILE_NAME_INFORMATION 402 */ 403 static uint32_t 404 smb2_qif_name(smb_request_t *sr, smb_queryinfo_t *qi) 405 { 406 char *name; 407 uint32_t nlen; 408 int rc; 409 410 /* SMB2 leaves off the leading / */ 411 nlen = qi->qi_namelen; 412 name = qi->qi_name; 413 if (qi->qi_name[0] == '\\') { 414 name++; 415 nlen -= 2; 416 } 417 418 rc = smb_mbc_encodef( 419 &sr->raw_data, "llU", 420 0, /* FileIndex (l) */ 421 nlen, /* l */ 422 name); /* U */ 423 if (rc != 0) 424 return (NT_STATUS_BUFFER_OVERFLOW); 425 426 return (0); 427 } 428 429 /* 430 * FileNormalizedNameInformation 431 */ 432 static uint32_t 433 smb2_qif_normalized_name(smb_request_t *sr, smb_queryinfo_t *qi) 434 { 435 char *name; 436 uint32_t nlen; 437 int rc; 438 439 /* SMB2 leaves off the leading / */ 440 nlen = qi->qi_namelen; 441 name = qi->qi_name; 442 if (qi->qi_name[0] == '\\') { 443 name++; 444 nlen -= 2; 445 } 446 447 rc = smb_mbc_encodef( 448 &sr->raw_data, "lU", 449 nlen, /* l */ 450 name); /* U */ 451 if (rc != 0) 452 return (NT_STATUS_BUFFER_OVERFLOW); 453 454 return (0); 455 } 456 457 /* 458 * FilePositionInformation 459 */ 460 static uint32_t 461 smb2_qif_position(smb_request_t *sr, smb_queryinfo_t *qi) 462 { 463 _NOTE(ARGUNUSED(qi)) 464 smb_ofile_t *of = sr->fid_ofile; 465 uint64_t pos; 466 int rc; 467 468 mutex_enter(&of->f_mutex); 469 pos = of->f_seek_pos; 470 mutex_exit(&of->f_mutex); 471 472 rc = smb_mbc_encodef( 473 &sr->raw_data, "q", pos); 474 if (rc != 0) 475 return (NT_STATUS_BUFFER_OVERFLOW); 476 477 return (0); 478 } 479 480 /* 481 * FileModeInformation [MS-FSA 2.4.24] 482 */ 483 static uint32_t 484 smb2_qif_mode(smb_request_t *sr, smb_queryinfo_t *qi) 485 { 486 _NOTE(ARGUNUSED(qi)) 487 smb_ofile_t *of = sr->fid_ofile; 488 uint32_t mode; 489 int rc; 490 491 /* 492 * See MS-FSA description of Open.Mode 493 * For now, we have these in... 494 */ 495 mode = of->f_create_options & 496 (FILE_WRITE_THROUGH | FILE_SEQUENTIAL_ONLY | 497 FILE_NO_INTERMEDIATE_BUFFERING | FILE_DELETE_ON_CLOSE); 498 499 /* 500 * The ofile level DoC flag is currently in of->f_flags 501 * (SMB_OFLAGS_SET_DELETE_ON_CLOSE) though probably it 502 * should be in f_create_options (and perhaps rename 503 * that field to f_mode or something closer to the 504 * Open.Mode terminology used in MS-FSA). 505 */ 506 if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) 507 mode |= FILE_DELETE_ON_CLOSE; 508 509 rc = smb_mbc_encodef( 510 &sr->raw_data, "l", mode); 511 if (rc != 0) 512 return (NT_STATUS_BUFFER_OVERFLOW); 513 514 return (0); 515 } 516 517 /* 518 * FileAlignmentInformation 519 */ 520 static uint32_t 521 smb2_qif_alignment(smb_request_t *sr, smb_queryinfo_t *qi) 522 { 523 _NOTE(ARGUNUSED(qi)) 524 int rc; 525 526 rc = smb_mbc_encodef( 527 &sr->raw_data, "l", 0); 528 if (rc != 0) 529 return (NT_STATUS_BUFFER_OVERFLOW); 530 531 return (0); 532 } 533 534 /* 535 * FileAlternateNameInformation 536 * See also: 537 * SMB_QUERY_FILE_ALT_NAME_INFO 538 * SMB_FILE_ALT_NAME_INFORMATION 539 */ 540 static uint32_t 541 smb2_qif_altname(smb_request_t *sr, smb_queryinfo_t *qi) 542 { 543 smb_ofile_t *of = sr->fid_ofile; 544 int rc; 545 546 ASSERT(qi->qi_namelen > 0); 547 ASSERT(qi->qi_attr.sa_mask & SMB_AT_NODEID); 548 549 if (of->f_ftype != SMB_FTYPE_DISK) 550 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 551 if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0) 552 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 553 554 /* fill in qi->qi_shortname */ 555 smb_query_shortname(of->f_node, qi); 556 557 rc = smb_mbc_encodef( 558 &sr->raw_data, "%lU", sr, 559 smb_wcequiv_strlen(qi->qi_shortname), 560 qi->qi_shortname); 561 if (rc != 0) 562 return (NT_STATUS_BUFFER_OVERFLOW); 563 564 return (0); 565 } 566 567 /* 568 * FileStreamInformation 569 */ 570 static uint32_t 571 smb2_qif_stream(smb_request_t *sr, smb_queryinfo_t *qi) 572 { 573 smb_ofile_t *of = sr->fid_ofile; 574 smb_attr_t *attr = &qi->qi_attr; 575 uint32_t status; 576 577 ASSERT((attr->sa_mask & SMB_AT_STANDARD) == SMB_AT_STANDARD); 578 if (of->f_ftype != SMB_FTYPE_DISK) { 579 (void) smb_mbc_encodef( 580 &sr->raw_data, "l", 0); 581 return (0); 582 } 583 584 status = smb_query_stream_info(sr, &sr->raw_data, qi); 585 return (status); 586 } 587 588 /* 589 * FilePipeInformation 590 */ 591 static uint32_t 592 smb2_qif_pipe(smb_request_t *sr, smb_queryinfo_t *qi) 593 { 594 _NOTE(ARGUNUSED(qi)) 595 smb_ofile_t *of = sr->fid_ofile; 596 uint32_t pipe_mode; 597 uint32_t nonblock; 598 int rc; 599 600 switch (of->f_ftype) { 601 case SMB_FTYPE_BYTE_PIPE: 602 pipe_mode = 0; /* FILE_PIPE_BYTE_STREAM_MODE */ 603 break; 604 case SMB_FTYPE_MESG_PIPE: 605 pipe_mode = 1; /* FILE_PIPE_MESSAGE_MODE */ 606 break; 607 case SMB_FTYPE_DISK: 608 case SMB_FTYPE_PRINTER: 609 default: 610 return (NT_STATUS_INVALID_PARAMETER); 611 } 612 nonblock = 0; /* XXX todo: Get this from the pipe handle. */ 613 614 rc = smb_mbc_encodef( 615 &sr->raw_data, "ll", 616 pipe_mode, nonblock); 617 if (rc != 0) 618 return (NT_STATUS_BUFFER_OVERFLOW); 619 620 return (0); 621 } 622 623 /* 624 * FilePipeLocalInformation 625 */ 626 /* ARGSUSED */ 627 static uint32_t 628 smb2_qif_pipe_lcl(smb_request_t *sr, smb_queryinfo_t *qi) 629 { 630 return (NT_STATUS_INVALID_PARAMETER); /* XXX todo */ 631 } 632 633 /* 634 * FilePipeRemoteInformation 635 */ 636 /* ARGSUSED */ 637 static uint32_t 638 smb2_qif_pipe_rem(smb_request_t *sr, smb_queryinfo_t *qi) 639 { 640 return (NT_STATUS_INVALID_PARAMETER); /* XXX todo */ 641 } 642 643 /* 644 * FileCompressionInformation 645 * XXX: For now, just say "not compressed". 646 */ 647 static uint32_t 648 smb2_qif_compr(smb_request_t *sr, smb_queryinfo_t *qi) 649 { 650 smb_attr_t *sa = &qi->qi_attr; 651 uint16_t CompressionFormat = 0; /* COMPRESSION_FORMAT_NONE */ 652 int rc; 653 654 ASSERT(sa->sa_mask & SMB_AT_SIZE); 655 656 rc = smb_mbc_encodef( 657 &sr->raw_data, "qw6.", 658 sa->sa_vattr.va_size, /* q */ 659 CompressionFormat); /* w */ 660 if (rc != 0) 661 return (NT_STATUS_BUFFER_OVERFLOW); 662 663 return (0); 664 } 665 666 /* 667 * FileNetworkOpenInformation 668 */ 669 static uint32_t 670 smb2_qif_opens(smb_request_t *sr, smb_queryinfo_t *qi) 671 { 672 smb_attr_t *sa = &qi->qi_attr; 673 int rc; 674 675 rc = smb_mbc_encodef( 676 &sr->raw_data, "TTTTqqll", 677 &sa->sa_crtime, /* T */ 678 &sa->sa_vattr.va_atime, /* T */ 679 &sa->sa_vattr.va_mtime, /* T */ 680 &sa->sa_vattr.va_ctime, /* T */ 681 sa->sa_allocsz, /* q */ 682 sa->sa_vattr.va_size, /* q */ 683 sa->sa_dosattr, /* l */ 684 0); /* reserved */ /* l */ 685 if (rc != 0) 686 return (NT_STATUS_BUFFER_OVERFLOW); 687 688 return (0); 689 } 690 691 /* 692 * FileAttributeTagInformation 693 * 694 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the 695 * second dword should be the reparse tag. Otherwise 696 * the tag value should be set to zero. 697 * We don't support reparse points, so we set the tag 698 * to zero. 699 */ 700 static uint32_t 701 smb2_qif_tags(smb_request_t *sr, smb_queryinfo_t *qi) 702 { 703 _NOTE(ARGUNUSED(qi)) 704 int rc; 705 706 rc = smb_mbc_encodef( 707 &sr->raw_data, "ll", 0, 0); 708 if (rc != 0) 709 return (NT_STATUS_BUFFER_OVERFLOW); 710 711 return (0); 712 } 713 714 /* 715 * FileIdInformation 716 * 717 * Returns a A FILE_ID_INFORMATION 718 * VolumeSerialNumber (8 bytes) 719 * FileId (16 bytes) 720 * 721 * Take the volume serial from the share root, 722 * and compose the FileId from the nodeid and fsid 723 * of the file (in case we crossed mounts) 724 */ 725 static uint32_t 726 smb2_qif_id_info(smb_request_t *sr, smb_queryinfo_t *qi) 727 { 728 smb_attr_t *sa = &qi->qi_attr; 729 smb_ofile_t *of = sr->fid_ofile; 730 smb_tree_t *tree = sr->tid_tree; 731 vfs_t *f_vfs; // file 732 vfs_t *s_vfs; // share 733 uint64_t nodeid; 734 int rc; 735 736 ASSERT((sa->sa_mask & SMB_AT_NODEID) != 0); 737 if (of->f_ftype != SMB_FTYPE_DISK) 738 return (NT_STATUS_INVALID_INFO_CLASS); 739 740 s_vfs = SMB_NODE_VFS(tree->t_snode); 741 f_vfs = SMB_NODE_VFS(of->f_node); 742 nodeid = (uint64_t)sa->sa_vattr.va_nodeid; 743 744 rc = smb_mbc_encodef( 745 &sr->raw_data, "llqll", 746 s_vfs->vfs_fsid.val[0], /* l */ 747 s_vfs->vfs_fsid.val[1], /* l */ 748 nodeid, /* q */ 749 f_vfs->vfs_fsid.val[0], /* l */ 750 f_vfs->vfs_fsid.val[1]); /* l */ 751 if (rc != 0) 752 return (NT_STATUS_INFO_LENGTH_MISMATCH); 753 754 return (0); 755 } 756