xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c (revision 4c28a617e3922d92a58e813a5b955eb526b9c386)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 /*
27  * Dispatch function for SMB2_QUERY_INFO
28  *
29  * [MS-FSCC 2.5] If a file system does not implement ...
30  * an Information Classs, NT_STATUS_INVALID_PARAMETER...
31  */
32 
33 #include <smbsrv/smb2_kproto.h>
34 #include <smbsrv/smb_fsops.h>
35 #include <smbsrv/ntifs.h>
36 
37 uint32_t smb2_qfs_volume(smb_request_t *);
38 uint32_t smb2_qfs_size(smb_request_t *);
39 uint32_t smb2_qfs_device(smb_request_t *);
40 uint32_t smb2_qfs_attr(smb_request_t *);
41 uint32_t smb2_qfs_control(smb_request_t *);
42 uint32_t smb2_qfs_fullsize(smb_request_t *);
43 uint32_t smb2_qfs_obj_id(smb_request_t *);
44 
45 uint32_t
46 smb2_qinfo_fs(smb_request_t *sr, smb_queryinfo_t *qi)
47 {
48 	uint32_t status;
49 
50 	switch (qi->qi_InfoClass) {
51 
52 	/* pg 153 */
53 	case FileFsVolumeInformation:	/* 1 */
54 		status = smb2_qfs_volume(sr);
55 		break;
56 	case FileFsSizeInformation:	/* 3 */
57 		status = smb2_qfs_size(sr);
58 		break;
59 	case FileFsDeviceInformation:	/* 4 */
60 		status = smb2_qfs_device(sr);
61 		break;
62 	case FileFsAttributeInformation: /* 5 */
63 		status = smb2_qfs_attr(sr);
64 		break;
65 	case FileFsControlInformation:	/* 6 */
66 		status = smb2_qfs_control(sr);
67 		break;
68 	case FileFsFullSizeInformation:	/* 7 */
69 		status = smb2_qfs_fullsize(sr);
70 		break;
71 	case FileFsObjectIdInformation:	/* 8 */
72 		status = smb2_qfs_obj_id(sr);
73 		break;
74 
75 	default:
76 		status = NT_STATUS_INVALID_INFO_CLASS;
77 		break;
78 	}
79 
80 	return (status);
81 }
82 
83 /*
84  * FileFsVolumeInformation
85  */
86 uint32_t
87 smb2_qfs_volume(smb_request_t *sr)
88 {
89 	smb_tree_t *tree = sr->tid_tree;
90 	smb_node_t *snode;
91 	fsid_t fsid;
92 	uint32_t LabelLength;
93 
94 	if (!STYPE_ISDSK(tree->t_res_type))
95 		return (NT_STATUS_INVALID_PARAMETER);
96 
97 	snode = tree->t_snode;
98 	fsid = SMB_NODE_FSID(snode);
99 
100 	LabelLength = smb_wcequiv_strlen(tree->t_volume);
101 
102 	/*
103 	 * NT has the "supports objects" flag set to 1.
104 	 */
105 	(void) smb_mbc_encodef(
106 	    &sr->raw_data, "qllb.U",
107 	    0LL,	/* Volume creation time (q) */
108 	    fsid.val[0],	/* serial no.   (l) */
109 	    LabelLength,		/*	(l) */
110 	    0,		/* Supports objects	(b) */
111 	    /* reserved				(.) */
112 	    tree->t_volume);		/*	(U) */
113 
114 	return (0);
115 }
116 
117 /*
118  * FileFsSizeInformation
119  */
120 uint32_t
121 smb2_qfs_size(smb_request_t *sr)
122 {
123 	smb_fssize_t		fssize;
124 	smb_tree_t *tree = sr->tid_tree;
125 	int rc;
126 
127 	if (!STYPE_ISDSK(tree->t_res_type))
128 		return (NT_STATUS_INVALID_PARAMETER);
129 
130 	rc = smb_fssize(sr, &fssize);
131 	if (rc)
132 		return (smb_errno2status(rc));
133 
134 	(void) smb_mbc_encodef(
135 	    &sr->raw_data, "qqll",
136 	    fssize.fs_caller_units,
137 	    fssize.fs_caller_avail,
138 	    fssize.fs_sectors_per_unit,
139 	    fssize.fs_bytes_per_sector);
140 
141 	return (0);
142 }
143 
144 /*
145  * FileFsFullSizeInformation
146  */
147 uint32_t
148 smb2_qfs_fullsize(smb_request_t *sr)
149 {
150 	smb_fssize_t		fssize;
151 	smb_tree_t *tree = sr->tid_tree;
152 	int rc;
153 
154 	if (!STYPE_ISDSK(tree->t_res_type))
155 		return (NT_STATUS_INVALID_PARAMETER);
156 
157 	rc = smb_fssize(sr, &fssize);
158 	if (rc)
159 		return (smb_errno2status(rc));
160 
161 	(void) smb_mbc_encodef(
162 	    &sr->raw_data, "qqqll",
163 	    fssize.fs_caller_units,
164 	    fssize.fs_caller_avail,
165 	    fssize.fs_volume_avail,
166 	    fssize.fs_sectors_per_unit,
167 	    fssize.fs_bytes_per_sector);
168 
169 	return (0);
170 }
171 
172 /*
173  * FileFsDeviceInformation
174  */
175 uint32_t
176 smb2_qfs_device(smb_request_t *sr)
177 {
178 	smb_tree_t *tree = sr->tid_tree;
179 	uint32_t DeviceType;
180 	uint32_t Characteristics;
181 
182 	if (!STYPE_ISDSK(tree->t_res_type))
183 		return (NT_STATUS_INVALID_PARAMETER);
184 
185 	DeviceType = FILE_DEVICE_DISK;
186 	Characteristics = FILE_DEVICE_IS_MOUNTED;
187 
188 	(void) smb_mbc_encodef(
189 	    &sr->raw_data, "ll",
190 	    DeviceType,
191 	    Characteristics);
192 
193 	return (0);
194 }
195 
196 /*
197  * FileFsAttributeInformation
198  */
199 uint32_t
200 smb2_qfs_attr(smb_request_t *sr)
201 {
202 	smb_tree_t *tree = sr->tid_tree;
203 	char *fsname;
204 	uint32_t namelen;
205 	uint32_t FsAttr;
206 
207 	/* This call is OK on all tree types. */
208 	switch (tree->t_res_type & STYPE_MASK) {
209 	case STYPE_IPC:
210 		fsname = "PIPE";
211 		break;
212 	case STYPE_DISKTREE:
213 		fsname = "NTFS"; /* A lie, but compatible... */
214 		break;
215 	case STYPE_PRINTQ:
216 	case STYPE_DEVICE:
217 	default: /* gcc -Wuninitialized */
218 		return (NT_STATUS_INVALID_PARAMETER);
219 	}
220 	namelen = smb_wcequiv_strlen(fsname);
221 
222 	/*
223 	 * Todo: Store the FsAttributes in the tree object,
224 	 * then just return that directly here.
225 	 */
226 	FsAttr = FILE_CASE_PRESERVED_NAMES;
227 	if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
228 		FsAttr |= FILE_UNICODE_ON_DISK;
229 	if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
230 		FsAttr |= FILE_PERSISTENT_ACLS;
231 	if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
232 		FsAttr |= FILE_CASE_SENSITIVE_SEARCH;
233 	if (tree->t_flags & SMB_TREE_STREAMS)
234 		FsAttr |= FILE_NAMED_STREAMS;
235 	if (tree->t_flags & SMB_TREE_QUOTA)
236 		FsAttr |= FILE_VOLUME_QUOTAS;
237 	if (tree->t_flags & SMB_TREE_SPARSE)
238 		FsAttr |= FILE_SUPPORTS_SPARSE_FILES;
239 
240 	(void) smb_mbc_encodef(
241 	    &sr->raw_data, "lllU",
242 	    FsAttr,
243 	    MAXNAMELEN-1,
244 	    namelen,
245 	    fsname);
246 
247 	return (0);
248 }
249 
250 /*
251  * FileFsControlInformation
252  */
253 uint32_t
254 smb2_qfs_control(smb_request_t *sr)
255 {
256 	smb_tree_t *tree = sr->tid_tree;
257 
258 	if (!STYPE_ISDSK(tree->t_res_type))
259 		return (NT_STATUS_INVALID_PARAMETER);
260 	if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
261 		/*
262 		 * Strange error per. [MS-FSCC 2.5.2]
263 		 * which means quotas not supported.
264 		 */
265 		return (NT_STATUS_VOLUME_NOT_UPGRADED);
266 	}
267 
268 	(void) smb_mbc_encodef(
269 	    &sr->raw_data, "qqqqqll",
270 	    0,		/* free space start filtering - MUST be 0 */
271 	    0,		/* free space threshold - MUST be 0 */
272 	    0,		/* free space stop filtering - MUST be 0 */
273 	    SMB_QUOTA_UNLIMITED,	/* default quota threshold */
274 	    SMB_QUOTA_UNLIMITED,	/* default quota limit */
275 	    FILE_VC_QUOTA_ENFORCE,	/* fs control flag */
276 	    0);				/* pad bytes */
277 
278 	return (0);
279 }
280 
281 /*
282  * FileFsObjectIdInformation
283  */
284 /* ARGSUSED */
285 uint32_t
286 smb2_qfs_obj_id(smb_request_t *sr)
287 {
288 	return (NT_STATUS_INVALID_PARAMETER);
289 }
290