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