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
smb2_qinfo_file(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_all(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_basic(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_standard(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_internal(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_ea_size(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_full_ea(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_access(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_name(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_normalized_name(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_position(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_mode(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_alignment(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_altname(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_stream(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_pipe(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_pipe_lcl(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_pipe_rem(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_compr(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_opens(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_tags(smb_request_t * sr,smb_queryinfo_t * qi)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
smb2_qif_id_info(smb_request_t * sr,smb_queryinfo_t * qi)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