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