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 * FileAccessInformation 217 * FilePositionInformation 218 * FileModeInformation 219 * FileAlignmentInformation 220 * FileNameInformation 221 * 222 * Note: FileNameInformation is all zero on Win2016 and later. 223 */ 224 static uint32_t 225 smb2_qif_all(smb_request_t *sr, smb_queryinfo_t *qi) 226 { 227 uint32_t status; 228 229 status = smb2_qif_basic(sr, qi); 230 if (status) 231 return (status); 232 status = smb2_qif_standard(sr, qi); 233 if (status) 234 return (status); 235 status = smb2_qif_internal(sr, qi); 236 if (status) 237 return (status); 238 status = smb2_qif_ea_size(sr, qi); 239 if (status) 240 return (status); 241 status = smb2_qif_access(sr, qi); 242 if (status) 243 return (status); 244 status = smb2_qif_position(sr, qi); 245 if (status) 246 return (status); 247 status = smb2_qif_mode(sr, qi); 248 if (status) 249 return (status); 250 status = smb2_qif_alignment(sr, qi); 251 if (status) 252 return (status); 253 254 /* See smb2_qif_all_get_name */ 255 if (qi->qi_namelen != 0) { 256 /* Win2012r2 and earlier fill it in. */ 257 status = smb2_qif_name(sr, qi); 258 } else { 259 /* Win2016 and later just put zeros. */ 260 int rc = smb_mbc_encodef(&sr->raw_data, "6."); 261 status = (rc == 0) ? 0 : NT_STATUS_BUFFER_OVERFLOW; 262 } 263 264 return (status); 265 } 266 267 /* 268 * FileBasicInformation 269 * See also: 270 * case SMB_QUERY_FILE_BASIC_INFO: 271 * case SMB_FILE_BASIC_INFORMATION: 272 */ 273 static uint32_t 274 smb2_qif_basic(smb_request_t *sr, smb_queryinfo_t *qi) 275 { 276 smb_attr_t *sa = &qi->qi_attr; 277 int rc; 278 279 ASSERT((sa->sa_mask & SMB_AT_BASIC) == SMB_AT_BASIC); 280 281 rc = smb_mbc_encodef( 282 &sr->raw_data, "TTTTll", 283 &sa->sa_crtime, /* T */ 284 &sa->sa_vattr.va_atime, /* T */ 285 &sa->sa_vattr.va_mtime, /* T */ 286 &sa->sa_vattr.va_ctime, /* T */ 287 sa->sa_dosattr, /* l */ 288 0); /* reserved */ /* l */ 289 if (rc != 0) 290 return (NT_STATUS_BUFFER_OVERFLOW); 291 292 return (0); 293 } 294 295 /* 296 * FileStandardInformation 297 * See also: 298 * SMB_QUERY_FILE_STANDARD_INFO 299 * SMB_FILE_STANDARD_INFORMATION 300 */ 301 static uint32_t 302 smb2_qif_standard(smb_request_t *sr, smb_queryinfo_t *qi) 303 { 304 smb_attr_t *sa = &qi->qi_attr; 305 int rc; 306 307 ASSERT((sa->sa_mask & SMB_AT_STANDARD) == SMB_AT_STANDARD); 308 309 rc = smb_mbc_encodef( 310 &sr->raw_data, "qqlbbw", 311 sa->sa_allocsz, /* q */ 312 sa->sa_vattr.va_size, /* q */ 313 sa->sa_vattr.va_nlink, /* l */ 314 qi->qi_delete_on_close, /* b */ 315 qi->qi_isdir, /* b */ 316 0); /* reserved */ /* w */ 317 if (rc != 0) 318 return (NT_STATUS_BUFFER_OVERFLOW); 319 320 return (0); 321 } 322 323 /* 324 * FileInternalInformation 325 * See also: 326 * SMB_FILE_INTERNAL_INFORMATION 327 */ 328 static uint32_t 329 smb2_qif_internal(smb_request_t *sr, smb_queryinfo_t *qi) 330 { 331 smb_attr_t *sa = &qi->qi_attr; 332 u_longlong_t nodeid; 333 int rc; 334 335 ASSERT((sa->sa_mask & SMB_AT_NODEID) == SMB_AT_NODEID); 336 nodeid = sa->sa_vattr.va_nodeid; 337 338 if (smb2_aapl_use_file_ids == 0 && 339 (sr->session->s_flags & SMB_SSN_AAPL_CCEXT) != 0) 340 nodeid = 0; 341 342 rc = smb_mbc_encodef( 343 &sr->raw_data, "q", 344 nodeid); /* q */ 345 if (rc != 0) 346 return (NT_STATUS_BUFFER_OVERFLOW); 347 348 return (0); 349 } 350 351 /* 352 * FileEaInformation 353 * See also: 354 * SMB_QUERY_FILE_EA_INFO 355 * SMB_FILE_EA_INFORMATION 356 */ 357 static uint32_t 358 smb2_qif_ea_size(smb_request_t *sr, smb_queryinfo_t *qi) 359 { 360 _NOTE(ARGUNUSED(qi)) 361 int rc; 362 363 rc = smb_mbc_encodef( 364 &sr->raw_data, "l", 0); 365 if (rc != 0) 366 return (NT_STATUS_BUFFER_OVERFLOW); 367 368 return (0); 369 } 370 371 /* 372 * FileFullEaInformation 373 * We could put EAs in a named stream... 374 */ 375 /* ARGSUSED */ 376 static uint32_t 377 smb2_qif_full_ea(smb_request_t *sr, smb_queryinfo_t *qi) 378 { 379 return (NT_STATUS_NO_EAS_ON_FILE); 380 } 381 382 /* 383 * FileAccessInformation 384 */ 385 static uint32_t 386 smb2_qif_access(smb_request_t *sr, smb_queryinfo_t *qi) 387 { 388 _NOTE(ARGUNUSED(qi)) 389 smb_ofile_t *of = sr->fid_ofile; 390 int rc; 391 392 rc = smb_mbc_encodef( 393 &sr->raw_data, "l", 394 of->f_granted_access); 395 if (rc != 0) 396 return (NT_STATUS_BUFFER_OVERFLOW); 397 398 return (0); 399 } 400 401 /* 402 * FileNameInformation 403 * See also: 404 * SMB_QUERY_FILE_NAME_INFO 405 * SMB_FILE_NAME_INFORMATION 406 * MS-FSCC 2.1.7 FILE_NAME_INFORMATION 407 */ 408 static uint32_t 409 smb2_qif_name(smb_request_t *sr, smb_queryinfo_t *qi) 410 { 411 char *name; 412 uint32_t nlen; 413 int rc; 414 415 /* SMB2 leaves off the leading / */ 416 nlen = qi->qi_namelen; 417 name = qi->qi_name; 418 if (qi->qi_name[0] == '\\') { 419 name++; 420 nlen -= 2; 421 } 422 423 rc = smb_mbc_encodef( 424 &sr->raw_data, "lU", 425 nlen, /* l */ 426 name); /* U */ 427 if (rc != 0) 428 return (NT_STATUS_BUFFER_OVERFLOW); 429 430 return (0); 431 } 432 433 /* 434 * FileNormalizedNameInformation 435 */ 436 static uint32_t 437 smb2_qif_normalized_name(smb_request_t *sr, smb_queryinfo_t *qi) 438 { 439 char *name; 440 uint32_t nlen; 441 int rc; 442 443 /* SMB2 leaves off the leading / */ 444 nlen = qi->qi_namelen; 445 name = qi->qi_name; 446 if (qi->qi_name[0] == '\\') { 447 name++; 448 nlen -= 2; 449 } 450 451 rc = smb_mbc_encodef( 452 &sr->raw_data, "lU", 453 nlen, /* l */ 454 name); /* U */ 455 if (rc != 0) 456 return (NT_STATUS_BUFFER_OVERFLOW); 457 458 return (0); 459 } 460 461 /* 462 * FilePositionInformation 463 */ 464 static uint32_t 465 smb2_qif_position(smb_request_t *sr, smb_queryinfo_t *qi) 466 { 467 _NOTE(ARGUNUSED(qi)) 468 smb_ofile_t *of = sr->fid_ofile; 469 uint64_t pos; 470 int rc; 471 472 mutex_enter(&of->f_mutex); 473 pos = of->f_seek_pos; 474 mutex_exit(&of->f_mutex); 475 476 rc = smb_mbc_encodef( 477 &sr->raw_data, "q", pos); 478 if (rc != 0) 479 return (NT_STATUS_BUFFER_OVERFLOW); 480 481 return (0); 482 } 483 484 /* 485 * FileModeInformation [MS-FSA 2.4.24] 486 */ 487 static uint32_t 488 smb2_qif_mode(smb_request_t *sr, smb_queryinfo_t *qi) 489 { 490 _NOTE(ARGUNUSED(qi)) 491 smb_ofile_t *of = sr->fid_ofile; 492 uint32_t mode; 493 int rc; 494 495 /* 496 * See MS-FSA description of Open.Mode 497 * For now, we have these in... 498 */ 499 mode = of->f_create_options & 500 (FILE_WRITE_THROUGH | FILE_SEQUENTIAL_ONLY | 501 FILE_NO_INTERMEDIATE_BUFFERING | FILE_DELETE_ON_CLOSE); 502 503 /* 504 * The ofile level DoC flag is currently in of->f_flags 505 * (SMB_OFLAGS_SET_DELETE_ON_CLOSE) though probably it 506 * should be in f_create_options (and perhaps rename 507 * that field to f_mode or something closer to the 508 * Open.Mode terminology used in MS-FSA). 509 */ 510 if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) 511 mode |= FILE_DELETE_ON_CLOSE; 512 513 rc = smb_mbc_encodef( 514 &sr->raw_data, "l", mode); 515 if (rc != 0) 516 return (NT_STATUS_BUFFER_OVERFLOW); 517 518 return (0); 519 } 520 521 /* 522 * FileAlignmentInformation 523 */ 524 static uint32_t 525 smb2_qif_alignment(smb_request_t *sr, smb_queryinfo_t *qi) 526 { 527 _NOTE(ARGUNUSED(qi)) 528 int rc; 529 530 rc = smb_mbc_encodef( 531 &sr->raw_data, "l", 0); 532 if (rc != 0) 533 return (NT_STATUS_BUFFER_OVERFLOW); 534 535 return (0); 536 } 537 538 /* 539 * FileAlternateNameInformation 540 * See also: 541 * SMB_QUERY_FILE_ALT_NAME_INFO 542 * SMB_FILE_ALT_NAME_INFORMATION 543 */ 544 static uint32_t 545 smb2_qif_altname(smb_request_t *sr, smb_queryinfo_t *qi) 546 { 547 smb_ofile_t *of = sr->fid_ofile; 548 int rc; 549 550 ASSERT(qi->qi_namelen > 0); 551 ASSERT(qi->qi_attr.sa_mask & SMB_AT_NODEID); 552 553 if (of->f_ftype != SMB_FTYPE_DISK) 554 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 555 if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0) 556 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 557 558 /* fill in qi->qi_shortname */ 559 smb_query_shortname(of->f_node, qi); 560 561 rc = smb_mbc_encodef( 562 &sr->raw_data, "%lU", sr, 563 smb_wcequiv_strlen(qi->qi_shortname), 564 qi->qi_shortname); 565 if (rc != 0) 566 return (NT_STATUS_BUFFER_OVERFLOW); 567 568 return (0); 569 } 570 571 /* 572 * FileStreamInformation 573 */ 574 static uint32_t 575 smb2_qif_stream(smb_request_t *sr, smb_queryinfo_t *qi) 576 { 577 smb_ofile_t *of = sr->fid_ofile; 578 smb_attr_t *attr = &qi->qi_attr; 579 uint32_t status; 580 581 ASSERT((attr->sa_mask & SMB_AT_STANDARD) == SMB_AT_STANDARD); 582 if (of->f_ftype != SMB_FTYPE_DISK) { 583 (void) smb_mbc_encodef( 584 &sr->raw_data, "l", 0); 585 return (0); 586 } 587 588 status = smb_query_stream_info(sr, &sr->raw_data, qi); 589 return (status); 590 } 591 592 /* 593 * FilePipeInformation 594 */ 595 static uint32_t 596 smb2_qif_pipe(smb_request_t *sr, smb_queryinfo_t *qi) 597 { 598 _NOTE(ARGUNUSED(qi)) 599 smb_ofile_t *of = sr->fid_ofile; 600 uint32_t pipe_mode; 601 uint32_t nonblock; 602 int rc; 603 604 switch (of->f_ftype) { 605 case SMB_FTYPE_BYTE_PIPE: 606 pipe_mode = 0; /* FILE_PIPE_BYTE_STREAM_MODE */ 607 break; 608 case SMB_FTYPE_MESG_PIPE: 609 pipe_mode = 1; /* FILE_PIPE_MESSAGE_MODE */ 610 break; 611 case SMB_FTYPE_DISK: 612 case SMB_FTYPE_PRINTER: 613 default: 614 return (NT_STATUS_INVALID_PARAMETER); 615 } 616 nonblock = 0; /* XXX todo: Get this from the pipe handle. */ 617 618 rc = smb_mbc_encodef( 619 &sr->raw_data, "ll", 620 pipe_mode, nonblock); 621 if (rc != 0) 622 return (NT_STATUS_BUFFER_OVERFLOW); 623 624 return (0); 625 } 626 627 /* 628 * FilePipeLocalInformation 629 */ 630 /* ARGSUSED */ 631 static uint32_t 632 smb2_qif_pipe_lcl(smb_request_t *sr, smb_queryinfo_t *qi) 633 { 634 return (NT_STATUS_INVALID_PARAMETER); /* XXX todo */ 635 } 636 637 /* 638 * FilePipeRemoteInformation 639 */ 640 /* ARGSUSED */ 641 static uint32_t 642 smb2_qif_pipe_rem(smb_request_t *sr, smb_queryinfo_t *qi) 643 { 644 return (NT_STATUS_INVALID_PARAMETER); /* XXX todo */ 645 } 646 647 /* 648 * FileCompressionInformation 649 * XXX: For now, just say "not compressed". 650 */ 651 static uint32_t 652 smb2_qif_compr(smb_request_t *sr, smb_queryinfo_t *qi) 653 { 654 smb_attr_t *sa = &qi->qi_attr; 655 uint16_t CompressionFormat = 0; /* COMPRESSION_FORMAT_NONE */ 656 int rc; 657 658 ASSERT(sa->sa_mask & SMB_AT_SIZE); 659 660 rc = smb_mbc_encodef( 661 &sr->raw_data, "qw6.", 662 sa->sa_vattr.va_size, /* q */ 663 CompressionFormat); /* w */ 664 if (rc != 0) 665 return (NT_STATUS_BUFFER_OVERFLOW); 666 667 return (0); 668 } 669 670 /* 671 * FileNetworkOpenInformation 672 */ 673 static uint32_t 674 smb2_qif_opens(smb_request_t *sr, smb_queryinfo_t *qi) 675 { 676 smb_attr_t *sa = &qi->qi_attr; 677 int rc; 678 679 rc = smb_mbc_encodef( 680 &sr->raw_data, "TTTTqqll", 681 &sa->sa_crtime, /* T */ 682 &sa->sa_vattr.va_atime, /* T */ 683 &sa->sa_vattr.va_mtime, /* T */ 684 &sa->sa_vattr.va_ctime, /* T */ 685 sa->sa_allocsz, /* q */ 686 sa->sa_vattr.va_size, /* q */ 687 sa->sa_dosattr, /* l */ 688 0); /* reserved */ /* l */ 689 if (rc != 0) 690 return (NT_STATUS_BUFFER_OVERFLOW); 691 692 return (0); 693 } 694 695 /* 696 * FileAttributeTagInformation 697 * 698 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the 699 * second dword should be the reparse tag. Otherwise 700 * the tag value should be set to zero. 701 * We don't support reparse points, so we set the tag 702 * to zero. 703 */ 704 static uint32_t 705 smb2_qif_tags(smb_request_t *sr, smb_queryinfo_t *qi) 706 { 707 _NOTE(ARGUNUSED(qi)) 708 int rc; 709 710 rc = smb_mbc_encodef( 711 &sr->raw_data, "ll", 0, 0); 712 if (rc != 0) 713 return (NT_STATUS_BUFFER_OVERFLOW); 714 715 return (0); 716 } 717 718 /* 719 * FileIdInformation 720 * 721 * Returns a A FILE_ID_INFORMATION 722 * VolumeSerialNumber (8 bytes) 723 * FileId (16 bytes) 724 * 725 * Take the volume serial from the share root, 726 * and compose the FileId from the nodeid and fsid 727 * of the file (in case we crossed mounts) 728 */ 729 static uint32_t 730 smb2_qif_id_info(smb_request_t *sr, smb_queryinfo_t *qi) 731 { 732 smb_attr_t *sa = &qi->qi_attr; 733 smb_ofile_t *of = sr->fid_ofile; 734 smb_tree_t *tree = sr->tid_tree; 735 vfs_t *f_vfs; // file 736 vfs_t *s_vfs; // share 737 uint64_t nodeid; 738 int rc; 739 740 ASSERT((sa->sa_mask & SMB_AT_NODEID) != 0); 741 if (of->f_ftype != SMB_FTYPE_DISK) 742 return (NT_STATUS_INVALID_INFO_CLASS); 743 744 s_vfs = SMB_NODE_VFS(tree->t_snode); 745 f_vfs = SMB_NODE_VFS(of->f_node); 746 nodeid = (uint64_t)sa->sa_vattr.va_nodeid; 747 748 rc = smb_mbc_encodef( 749 &sr->raw_data, "llqll", 750 s_vfs->vfs_fsid.val[0], /* l */ 751 s_vfs->vfs_fsid.val[1], /* l */ 752 nodeid, /* q */ 753 f_vfs->vfs_fsid.val[0], /* l */ 754 f_vfs->vfs_fsid.val[1]); /* l */ 755 if (rc != 0) 756 return (NT_STATUS_INFO_LENGTH_MISMATCH); 757 758 return (0); 759 } 760