Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
SMB-136 Snapshots not visible in Windows previous versions
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
re #14152 Race between ipmi_submit_driver_request() and kcs_loop() (sync with illumos fix 3902)
SMB-46 File handle leaks exposed by mtime fixes (rm 7815)
re #7815 SMB server delivers old modification time...
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <smbsrv/smb_kproto.h>
27 -#include <smbsrv/winioctl.h>
27 +#include <smb/winioctl.h>
28 28
29 29
30 30 static uint32_t smb_nt_trans_ioctl_noop(smb_request_t *, smb_xa_t *);
31 31 static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *, smb_xa_t *);
32 32 static uint32_t smb_nt_trans_ioctl_set_sparse(smb_request_t *, smb_xa_t *);
33 33 static uint32_t smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *,
34 34 smb_xa_t *);
35 35 static uint32_t smb_nt_trans_ioctl_set_zero_data(smb_request_t *, smb_xa_t *);
36 36 static uint32_t smb_nt_trans_ioctl_enum_snaps(smb_request_t *, smb_xa_t *);
37 37
38 38 /*
39 39 * This table defines the list of FSCTL values for which we'll
40 40 * call a funtion to perform specific processing.
41 - *
42 - * Note: If support is added for FSCTL_SET_ZERO_DATA, it must break
43 - * any oplocks on the file to none:
44 - * smb_oplock_break(sr, node, SMB_OPLOCK_BREAK_TO_NONE);
45 41 */
46 42 static const struct {
47 43 uint32_t fcode;
48 44 uint32_t (*ioctl_func)(smb_request_t *sr, smb_xa_t *xa);
49 45 } ioctl_ret_tbl[] = {
50 46 { FSCTL_GET_OBJECT_ID, smb_nt_trans_ioctl_invalid_parm },
51 47 { FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_query_alloc_ranges },
52 48 { FSCTL_SET_ZERO_DATA, smb_nt_trans_ioctl_set_zero_data },
53 49 { FSCTL_SRV_ENUMERATE_SNAPSHOTS, smb_nt_trans_ioctl_enum_snaps },
54 50 { FSCTL_SET_SPARSE, smb_nt_trans_ioctl_set_sparse },
55 51 { FSCTL_FIND_FILES_BY_SID, smb_nt_trans_ioctl_noop }
56 52 };
57 53
58 54 /*
59 55 * smb_nt_transact_ioctl
60 56 *
61 57 * This command allows device and file system control functions to be
62 58 * transferred transparently from client to server.
63 59 *
64 60 * Setup Words Encoding Description
65 61 * =========================== =========================================
66 62 * ULONG FunctionCode; NT device or file system control code
67 63 * USHORT Fid; Handle for io or fs control. Unless BIT0
68 64 * of ISFLAGS is set.
69 65 * BOOLEAN IsFsctl; Indicates whether the command is a device
70 66 * control (FALSE) or a file system control
71 67 * (TRUE).
72 68 * UCHAR IsFlags; BIT0 - command is to be applied to share
73 69 * root handle. Share must be a DFS share.
74 70 *
75 71 * Data Block Encoding Description
76 72 * =========================== =========================================
77 73 * Data[ TotalDataCount ] Passed to the Fsctl or Ioctl
78 74 *
79 75 * Server Response Description
80 76 * =========================== ==================================
81 77 * SetupCount 1
82 78 * Setup[0] Length of information returned by
83 79 * io or fs control.
84 80 * DataCount Length of information returned by
85 81 * io or fs control.
86 82 * Data[ DataCount ] The results of the io or fs control.
87 83 */
88 84 smb_sdrc_t
89 85 smb_nt_transact_ioctl(smb_request_t *sr, smb_xa_t *xa)
90 86 {
91 87 uint32_t status = NT_STATUS_NOT_SUPPORTED;
92 88 uint32_t fcode;
93 89 unsigned char is_fsctl;
94 90 unsigned char is_flags;
95 91 int i;
96 92
97 93 if (smb_mbc_decodef(&xa->req_setup_mb, "lwbb",
98 94 &fcode, &sr->smb_fid, &is_fsctl, &is_flags) != 0) {
99 95 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
100 96 return (SDRC_ERROR);
101 97 }
102 98
103 99 /*
104 100 * Invoke handler if specified, otherwise the default
105 101 * behavior is to return NT_STATUS_NOT_SUPPORTED
106 102 */
107 103 for (i = 0; i < sizeof (ioctl_ret_tbl) / sizeof (ioctl_ret_tbl[0]);
108 104 i++) {
109 105 if (ioctl_ret_tbl[i].fcode == fcode) {
110 106 status = ioctl_ret_tbl[i].ioctl_func(sr, xa);
111 107 break;
112 108 }
113 109 }
114 110
115 111 if (status != NT_STATUS_SUCCESS) {
116 112 smbsr_error(sr, status, 0, 0);
117 113 return (SDRC_ERROR);
118 114 }
119 115
120 116 (void) smb_mbc_encodef(&xa->rep_param_mb, "l", 0);
121 117 return (SDRC_SUCCESS);
122 118 }
123 119
124 120 /* ARGSUSED */
125 121 static uint32_t
126 122 smb_nt_trans_ioctl_noop(smb_request_t *sr, smb_xa_t *xa)
127 123 {
128 124 return (NT_STATUS_SUCCESS);
129 125 }
130 126
131 127 /* ARGSUSED */
132 128 static uint32_t
133 129 smb_nt_trans_ioctl_invalid_parm(smb_request_t *sr, smb_xa_t *xa)
134 130 {
135 131 return (NT_STATUS_INVALID_PARAMETER);
136 132 }
137 133
138 134 /*
139 135 * smb_nt_trans_ioctl_set_sparse
140 136 *
141 137 * There may, or may not be a data block in this request.
142 138 * If there IS a data block, the first byte is a boolean
143 139 * specifying whether to set (non zero) or clear (zero)
144 140 * the sparse attribute of the file.
145 141 * If there is no data block, this indicates a request to
146 142 * set the sparse attribute.
147 143 */
148 144 static uint32_t
149 145 smb_nt_trans_ioctl_set_sparse(smb_request_t *sr, smb_xa_t *xa)
150 146 {
151 147 int rc = 0;
152 148 uint8_t set = 1;
153 149 smb_ofile_t *of;
154 150 smb_attr_t attr;
155 151
156 152 if (SMB_TREE_IS_READONLY(sr))
157 153 return (NT_STATUS_ACCESS_DENIED);
158 154
159 155 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
160 156 return (NT_STATUS_INVALID_PARAMETER);
161 157
162 158 smbsr_lookup_file(sr);
163 159 if (sr->fid_ofile == NULL)
164 160 return (NT_STATUS_INVALID_HANDLE);
165 161
166 162 if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
167 163 smbsr_release_file(sr);
168 164 return (NT_STATUS_INVALID_PARAMETER);
169 165 }
170 166
171 167 of = sr->fid_ofile;
172 168 if (smb_node_is_dir(of->f_node)) {
173 169 smbsr_release_file(sr);
174 170 return (NT_STATUS_INVALID_PARAMETER);
175 171 }
176 172
177 173 if (smbsr_decode_data_avail(sr)) {
178 174 if (smb_mbc_decodef(&xa->req_data_mb, "b", &set) != 0) {
179 175 smbsr_release_file(sr);
180 176 return (sr->smb_error.status);
181 177 }
182 178 }
183 179
184 180 /*
185 181 * Using kcred because we just want the DOS attrs
186 182 * and don't want access errors for this.
187 183 */
188 184 bzero(&attr, sizeof (smb_attr_t));
189 185 attr.sa_mask = SMB_AT_DOSATTR;
190 186 rc = smb_node_getattr(sr, of->f_node, zone_kcred(), of, &attr);
191 187 if (rc != 0) {
192 188 smbsr_errno(sr, rc);
193 189 smbsr_release_file(sr);
194 190 return (sr->smb_error.status);
195 191 }
196 192
197 193 attr.sa_mask = 0;
198 194 if ((set == 0) &&
199 195 (attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
200 196 attr.sa_dosattr &= ~FILE_ATTRIBUTE_SPARSE_FILE;
201 197 attr.sa_mask = SMB_AT_DOSATTR;
202 198 } else if ((set != 0) &&
203 199 !(attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
204 200 attr.sa_dosattr |= FILE_ATTRIBUTE_SPARSE_FILE;
205 201 attr.sa_mask = SMB_AT_DOSATTR;
206 202 }
207 203
208 204 if (attr.sa_mask != 0) {
209 205 rc = smb_node_setattr(sr, of->f_node, of->f_cr, of, &attr);
210 206 if (rc != 0) {
211 207 smbsr_errno(sr, rc);
212 208 smbsr_release_file(sr);
213 209 return (sr->smb_error.status);
214 210 }
|
↓ open down ↓ |
160 lines elided |
↑ open up ↑ |
215 211 }
216 212
217 213 smbsr_release_file(sr);
218 214 return (NT_STATUS_SUCCESS);
219 215 }
220 216
221 217 /*
222 218 * smb_nt_trans_ioctl_set_zero_data
223 219 *
224 220 * Check that the request is valid on the specified file.
225 - * The implementation is a noop.
221 + * The implementation is a noop. XXX - bug!
222 + * XXX: We have this in the fsclt module now. Call that.
223 + *
224 + * Note: When support is added for FSCTL_SET_ZERO_DATA, it must
225 + * break any oplocks on the file to none:
226 + * (void) smb_oplock_break_WRITE(node, ofile);
226 227 */
227 228 /* ARGSUSED */
228 229 static uint32_t
229 230 smb_nt_trans_ioctl_set_zero_data(smb_request_t *sr, smb_xa_t *xa)
230 231 {
231 232 smb_node_t *node;
232 233
233 234 if (SMB_TREE_IS_READONLY(sr))
234 235 return (NT_STATUS_ACCESS_DENIED);
235 236
236 237 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
237 238 return (NT_STATUS_INVALID_PARAMETER);
238 239
239 240 smbsr_lookup_file(sr);
240 241 if (sr->fid_ofile == NULL)
241 242 return (NT_STATUS_INVALID_HANDLE);
242 243
243 244 if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
244 245 smbsr_release_file(sr);
245 246 return (NT_STATUS_INVALID_PARAMETER);
246 247 }
247 248
248 249 node = sr->fid_ofile->f_node;
249 250 if (smb_node_is_dir(node)) {
250 251 smbsr_release_file(sr);
251 252 return (NT_STATUS_INVALID_PARAMETER);
252 253 }
253 254
254 255 smbsr_release_file(sr);
255 256 return (NT_STATUS_SUCCESS);
256 257 }
257 258
258 259 /*
259 260 * smb_nt_trans_ioctl_query_alloc_ranges
260 261 *
261 262 * Responds with either:
262 263 * - no data if the file is zero size
263 264 * - a single range containing the starting point and length requested
264 265 */
265 266 static uint32_t
266 267 smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *sr, smb_xa_t *xa)
267 268 {
268 269 int rc;
269 270 uint64_t offset, len;
270 271 smb_ofile_t *of;
271 272 smb_attr_t attr;
272 273
273 274 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
274 275 return (NT_STATUS_INVALID_PARAMETER);
275 276
276 277 smbsr_lookup_file(sr);
277 278 if (sr->fid_ofile == NULL)
278 279 return (NT_STATUS_INVALID_HANDLE);
279 280
280 281 if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
281 282 smbsr_release_file(sr);
282 283 return (NT_STATUS_INVALID_PARAMETER);
283 284 }
284 285
285 286 of = sr->fid_ofile;
286 287 if (smb_node_is_dir(of->f_node)) {
287 288 smbsr_release_file(sr);
288 289 return (NT_STATUS_INVALID_PARAMETER);
289 290 }
290 291
291 292 /* If zero size file don't return any data */
292 293 bzero(&attr, sizeof (smb_attr_t));
293 294 attr.sa_mask = SMB_AT_SIZE;
294 295 rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
295 296 if (rc != 0) {
296 297 smbsr_errno(sr, rc);
297 298 smbsr_release_file(sr);
298 299 return (sr->smb_error.status);
299 300 }
300 301
301 302 if (attr.sa_vattr.va_size == 0) {
302 303 smbsr_release_file(sr);
303 304 return (NT_STATUS_SUCCESS);
304 305 }
305 306
306 307 if (smb_mbc_decodef(&xa->req_data_mb, "qq", &offset, &len) != 0) {
307 308 smbsr_release_file(sr);
308 309 return (sr->smb_error.status);
309 310 }
310 311
311 312 /*
312 313 * Return a single range regardless of whether the file
313 314 * is sparse or not.
314 315 */
315 316 if (MBC_ROOM_FOR(&xa->rep_data_mb, 16) == 0) {
316 317 smbsr_release_file(sr);
317 318 return (NT_STATUS_BUFFER_TOO_SMALL);
318 319 }
319 320
320 321 if (smb_mbc_encodef(&xa->rep_data_mb, "qq", offset, len) != 0) {
321 322 smbsr_release_file(sr);
322 323 return (sr->smb_error.status);
323 324 }
324 325
325 326 smbsr_release_file(sr);
326 327 return (NT_STATUS_SUCCESS);
327 328 }
328 329
329 330 static uint32_t
330 331 smb_nt_trans_ioctl_enum_snaps(smb_request_t *sr, smb_xa_t *xa)
331 332 {
332 333 smb_fsctl_t fsctl;
333 334 uint32_t status;
334 335
335 336 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
336 337 return (NT_STATUS_INVALID_PARAMETER);
337 338
338 339 smbsr_lookup_file(sr);
339 340 if (sr->fid_ofile == NULL)
340 341 return (NT_STATUS_INVALID_HANDLE);
341 342
342 343 if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
343 344 smbsr_release_file(sr);
344 345 return (NT_STATUS_INVALID_PARAMETER);
345 346 }
346 347
347 348 fsctl.CtlCode = FSCTL_SRV_ENUMERATE_SNAPSHOTS;
348 349 fsctl.InputCount = xa->smb_tpscnt;
349 350 fsctl.OutputCount = 0;
350 351 fsctl.MaxOutputResp = xa->smb_mdrcnt;
351 352 fsctl.in_mbc = &xa->req_param_mb;
352 353 fsctl.out_mbc = &xa->rep_data_mb;
353 354
354 355 status = smb_vss_enum_snapshots(sr, &fsctl);
355 356
356 357 smbsr_release_file(sr);
357 358 return (status);
358 359 }
|
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX