Print this page
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_fsinfo.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 2013 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <smbsrv/smb_kproto.h>
27 27 #include <smbsrv/smb_fsops.h>
28 28 #include <smbsrv/smbinfo.h>
29 29
30 30 static int smb_trans2_set_fs_ctrl_info(smb_request_t *, smb_xa_t *);
31 31
32 32 /*
33 33 * smb_com_query_information_disk
34 34 *
35 35 * The SMB_COM_QUERY_INFORMATION_DISK command is used to determine the
36 36 * capacity and remaining free space on the drive hosting the directory
37 37 * structure indicated by Tid in the SMB header.
38 38 *
39 39 * The blocking/allocation units used in this response may be independent
40 40 * of the actual physical or logical blocking/allocation algorithm(s) used
41 41 * internally by the server. However, they must accurately reflect the
42 42 * amount of space on the server.
43 43 *
44 44 * This SMB only returns 16 bits of information for each field, which may
45 45 * not be large enough for some disk systems. In particular TotalUnits is
46 46 * commonly > 64K. Fortunately, it turns out the all the client cares
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
47 47 * about is the total disk size, in bytes, and the free space, in bytes.
48 48 * So, it is reasonable for a server to adjust the relative values of
49 49 * BlocksPerUnit and BlockSize to accommodate. If after all adjustment,
50 50 * the numbers are still too high, the largest possible values for
51 51 * TotalUnit or FreeUnits (i.e. 0xFFFF) should be returned.
52 52 */
53 53
54 54 smb_sdrc_t
55 55 smb_pre_query_information_disk(smb_request_t *sr)
56 56 {
57 - DTRACE_SMB_1(op__QueryInformationDisk__start, smb_request_t *, sr);
57 + DTRACE_SMB_START(op__QueryInformationDisk, smb_request_t *, sr);
58 58 return (SDRC_SUCCESS);
59 59 }
60 60
61 61 void
62 62 smb_post_query_information_disk(smb_request_t *sr)
63 63 {
64 - DTRACE_SMB_1(op__QueryInformationDisk__done, smb_request_t *, sr);
64 + DTRACE_SMB_DONE(op__QueryInformationDisk, smb_request_t *, sr);
65 65 }
66 66
67 67 smb_sdrc_t
68 68 smb_com_query_information_disk(smb_request_t *sr)
69 69 {
70 70 int rc;
71 71 fsblkcnt64_t total_blocks, free_blocks;
72 72 unsigned long block_size, unit_size;
73 73 unsigned short blocks_per_unit, bytes_per_block;
74 74 unsigned short total_units, free_units;
75 75 smb_fssize_t fssize;
76 76
77 77 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
78 78 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
79 79 return (SDRC_ERROR);
80 80 }
81 81
82 82 if (smb_fssize(sr, &fssize) != 0)
83 83 return (SDRC_ERROR);
84 84
85 85 unit_size = fssize.fs_sectors_per_unit;
86 86 block_size = fssize.fs_bytes_per_sector;
87 87 total_blocks = fssize.fs_caller_units;
88 88 free_blocks = fssize.fs_caller_avail;
89 89
90 90 /*
91 91 * It seems that DOS clients cannot handle block sizes
92 92 * bigger than 512 KB. So we have to set the block size at
93 93 * most to 512
94 94 */
95 95 while (block_size > 512) {
96 96 block_size >>= 1;
97 97 unit_size <<= 1;
98 98 }
99 99
100 100 /* adjust blocks and sizes until they fit into a word */
101 101 while (total_blocks >= 0xFFFF) {
102 102 total_blocks >>= 1;
103 103 free_blocks >>= 1;
104 104 if ((unit_size <<= 1) > 0xFFFF) {
105 105 unit_size >>= 1;
106 106 total_blocks = 0xFFFF;
107 107 free_blocks <<= 1;
108 108 break;
109 109 }
110 110 }
111 111
112 112 total_units = (total_blocks >= 0xFFFF) ?
113 113 0xFFFF : (unsigned short)total_blocks;
114 114 free_units = (free_blocks >= 0xFFFF) ?
115 115 0xFFFF : (unsigned short)free_blocks;
116 116 bytes_per_block = (unsigned short)block_size;
117 117 blocks_per_unit = (unsigned short)unit_size;
118 118
119 119 rc = smbsr_encode_result(sr, 5, 0, "bwwww2.w",
120 120 5,
121 121 total_units, /* total_units */
122 122 blocks_per_unit, /* blocks_per_unit */
123 123 bytes_per_block, /* blocksize */
124 124 free_units, /* free_units */
125 125 0); /* bcc */
126 126
127 127 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
128 128 }
129 129
130 130 /*
131 131 * smb_com_trans2_query_fs_information
132 132 *
133 133 * This transaction requests information about the filesystem.
134 134 * The following information levels are supported:
135 135 *
136 136 * InformationLevel Value
137 137 * ================================== ======
138 138 * SMB_INFO_ALLOCATION 1
139 139 * SMB_INFO_VOLUME 2
140 140 * SMB_QUERY_FS_VOLUME_INFO 0x102
141 141 * SMB_QUERY_FS_SIZE_INFO 0x103
142 142 * SMB_QUERY_FS_DEVICE_INFO 0x104
143 143 * SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
144 144 * SMB_FILE_FS_VOLUME_INFORMATION 1001
145 145 * SMB_FILE_FS_SIZE_INFORMATION 1003
146 146 * SMB_FILE_FS_DEVICE_INFORMATION 1004
147 147 * SMB_FILE_FS_ATTRIBUTE_INFORMATION 1005
148 148 * SMB_FILE_FS_CONTROL_INFORMATION 1006
149 149 * SMB_FILE_FS_FULLSIZE_INFORMATION 1007
150 150 *
151 151 * The fsid provides a system-wide unique file system ID.
152 152 * fsid.val[0] is the 32-bit dev for the file system of the share root
153 153 * smb_node.
154 154 * fsid.val[1] is the file system type.
155 155 */
156 156 smb_sdrc_t
157 157 smb_com_trans2_query_fs_information(smb_request_t *sr, smb_xa_t *xa)
158 158 {
159 159 uint32_t flags;
160 160 char *encode_str, *tmpbuf;
161 161 uint64_t max_int;
162 162 uint16_t infolev;
163 163 int rc, length, buflen;
164 164 smb_tree_t *tree;
165 165 smb_node_t *snode;
166 166 char *fsname = "NTFS";
167 167 fsid_t fsid;
168 168 smb_fssize_t fssize;
169 169 smb_msgbuf_t mb;
170 170
171 171 tree = sr->tid_tree;
172 172
173 173 if (!STYPE_ISDSK(tree->t_res_type)) {
174 174 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
175 175 ERRDOS, ERROR_ACCESS_DENIED);
176 176 return (SDRC_ERROR);
177 177 }
178 178
179 179 if (smb_mbc_decodef(&xa->req_param_mb, "w", &infolev) != 0)
180 180 return (SDRC_ERROR);
181 181
182 182 snode = tree->t_snode;
183 183 fsid = SMB_NODE_FSID(snode);
184 184
185 185 switch (infolev) {
186 186 case SMB_INFO_ALLOCATION:
187 187 if (smb_fssize(sr, &fssize) != 0)
188 188 return (SDRC_ERROR);
189 189
190 190 max_int = (uint64_t)UINT_MAX;
191 191 if (fssize.fs_caller_units > max_int)
192 192 fssize.fs_caller_units = max_int;
193 193 if (fssize.fs_caller_avail > max_int)
194 194 fssize.fs_caller_avail = max_int;
195 195
196 196 (void) smb_mbc_encodef(&xa->rep_data_mb, "llllw",
197 197 0,
198 198 fssize.fs_sectors_per_unit,
199 199 fssize.fs_caller_units,
200 200 fssize.fs_caller_avail,
201 201 fssize.fs_bytes_per_sector);
202 202 break;
203 203
204 204 case SMB_INFO_VOLUME:
205 205 /*
206 206 * In this response, the unicode volume label is NOT
207 207 * expected to be aligned. Encode ('U') into a temporary
208 208 * buffer, then encode buffer as a byte stream ('#c').
209 209 */
210 210 if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
211 211 (sr->session->native_os == NATIVE_OS_WIN95)) {
212 212 length = smb_wcequiv_strlen(tree->t_volume);
213 213 buflen = length + sizeof (smb_wchar_t);
214 214 tmpbuf = smb_srm_zalloc(sr, buflen);
215 215 smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen,
216 216 SMB_MSGBUF_UNICODE);
217 217 rc = smb_msgbuf_encode(&mb, "U", tree->t_volume);
218 218 if (rc >= 0) {
219 219 rc = smb_mbc_encodef(&xa->rep_data_mb,
220 220 "%lb#c", sr, fsid.val[0],
221 221 length, length, tmpbuf);
222 222 }
223 223 smb_msgbuf_term(&mb);
224 224 } else {
225 225 length = strlen(tree->t_volume);
226 226 rc = smb_mbc_encodef(&xa->rep_data_mb, "%lbs", sr,
227 227 fsid.val[0], length, tree->t_volume);
228 228 }
229 229
230 230 if (rc < 0)
231 231 return (SDRC_ERROR);
232 232 break;
233 233
234 234 case SMB_QUERY_FS_VOLUME_INFO:
235 235 case SMB_FILE_FS_VOLUME_INFORMATION:
236 236 if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
237 237 (sr->session->native_os == NATIVE_OS_WIN95)) {
238 238 length = smb_wcequiv_strlen(tree->t_volume);
239 239 encode_str = "%qllb.U";
240 240 } else {
241 241 length = strlen(tree->t_volume);
242 242 encode_str = "%qllb.s";
243 243 }
244 244
245 245 /*
246 246 * NT has the "supports objects" flag set to 1.
247 247 */
248 248 (void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
249 249 0ll, /* Volume creation time */
250 250 fsid.val[0], /* Volume serial number */
251 251 length, /* label length */
252 252 0, /* Supports objects */
253 253 tree->t_volume);
254 254 break;
255 255
256 256 case SMB_QUERY_FS_SIZE_INFO:
257 257 case SMB_FILE_FS_SIZE_INFORMATION:
258 258 if (smb_fssize(sr, &fssize) != 0)
259 259 return (SDRC_ERROR);
260 260
261 261 (void) smb_mbc_encodef(&xa->rep_data_mb, "qqll",
262 262 fssize.fs_caller_units,
263 263 fssize.fs_caller_avail,
264 264 fssize.fs_sectors_per_unit,
265 265 fssize.fs_bytes_per_sector);
266 266 break;
267 267
268 268 case SMB_QUERY_FS_DEVICE_INFO:
269 269 case SMB_FILE_FS_DEVICE_INFORMATION:
270 270 (void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
271 271 FILE_DEVICE_FILE_SYSTEM,
272 272 FILE_DEVICE_IS_MOUNTED);
273 273 break;
274 274
275 275 case SMB_QUERY_FS_ATTRIBUTE_INFO:
276 276 case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
277 277 if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) ||
278 278 (sr->session->native_os == NATIVE_OS_WINNT) ||
279 279 (sr->session->native_os == NATIVE_OS_WIN2000) ||
280 280 (sr->session->native_os == NATIVE_OS_WIN95) ||
281 281 (sr->session->native_os == NATIVE_OS_MACOS)) {
282 282 length = smb_wcequiv_strlen(fsname);
283 283 encode_str = "%lllU";
284 284 sr->smb_flg2 |= SMB_FLAGS2_UNICODE;
285 285 } else {
286 286 length = strlen(fsname);
287 287 encode_str = "%llls";
288 288 }
289 289
290 290 flags = FILE_CASE_PRESERVED_NAMES;
291 291
292 292 if (tree->t_flags & SMB_TREE_UNICODE_ON_DISK)
293 293 flags |= FILE_UNICODE_ON_DISK;
294 294
295 295 if (tree->t_flags & SMB_TREE_SUPPORTS_ACLS)
296 296 flags |= FILE_PERSISTENT_ACLS;
297 297
298 298 if ((tree->t_flags & SMB_TREE_CASEINSENSITIVE) == 0)
299 299 flags |= FILE_CASE_SENSITIVE_SEARCH;
300 300
301 301 if (tree->t_flags & SMB_TREE_STREAMS)
302 302 flags |= FILE_NAMED_STREAMS;
303 303
304 304 if (tree->t_flags & SMB_TREE_QUOTA)
305 305 flags |= FILE_VOLUME_QUOTAS;
306 306
307 307 if (tree->t_flags & SMB_TREE_SPARSE)
308 308 flags |= FILE_SUPPORTS_SPARSE_FILES;
309 309
310 310 (void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
311 311 flags,
312 312 MAXNAMELEN, /* max name */
313 313 length, /* label length */
314 314 fsname);
315 315 break;
316 316
317 317 case SMB_FILE_FS_CONTROL_INFORMATION:
318 318 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
319 319 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
320 320 ERRDOS, ERROR_NOT_SUPPORTED);
321 321 return (SDRC_ERROR);
322 322 }
323 323
324 324 (void) smb_mbc_encodef(&xa->rep_data_mb, "qqqqqll",
325 325 0, /* free space start filtering - MUST be 0 */
326 326 0, /* free space threshold - MUST be 0 */
327 327 0, /* free space stop filtering - MUST be 0 */
328 328 SMB_QUOTA_UNLIMITED, /* default quota threshold */
329 329 SMB_QUOTA_UNLIMITED, /* default quota limit */
330 330 FILE_VC_QUOTA_ENFORCE, /* fs control flag */
331 331 0); /* pad bytes */
332 332 break;
333 333
334 334 case SMB_FILE_FS_FULLSIZE_INFORMATION:
335 335 if (smb_fssize(sr, &fssize) != 0)
336 336 return (SDRC_ERROR);
337 337
338 338 (void) smb_mbc_encodef(&xa->rep_data_mb, "qqqll",
339 339 fssize.fs_caller_units,
340 340 fssize.fs_caller_avail,
341 341 fssize.fs_volume_avail,
342 342 fssize.fs_sectors_per_unit,
343 343 fssize.fs_bytes_per_sector);
344 344 break;
345 345
346 346 case SMB_FILE_FS_LABEL_INFORMATION:
347 347 case SMB_FILE_FS_OBJECTID_INFORMATION:
348 348 case SMB_FILE_FS_DRIVERPATH_INFORMATION:
349 349 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
350 350 ERRDOS, ERROR_NOT_SUPPORTED);
351 351 return (SDRC_ERROR);
352 352
353 353 default:
354 354 smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
355 355 ERRDOS, ERROR_INVALID_LEVEL);
356 356 return (SDRC_ERROR);
357 357 }
358 358
359 359 return (SDRC_SUCCESS);
360 360 }
361 361
362 362 /*
363 363 * smb_fssize
364 364 *
365 365 * File system size information, for the volume and for the user
366 366 * initiating the request.
367 367 *
368 368 * If there's no quota entry for the user initiating the request,
369 369 * caller_units and caller_avail are the total and available units
370 370 * for the volume (volume_units, volume_avail).
371 371 * If there is a quota entry for the user initiating the request,
372 372 * and it is not SMB_QUOTA_UNLIMITED, calculate caller_units and
373 373 * caller_avail as follows:
374 374 * caller_units = quota limit / bytes_per_unit
375 375 * caller_avail = remaining quota / bytes_per_unit
376 376 *
377 377 * A quota limit of SMB_QUOTA_UNLIMITED means that the user's quota
378 378 * is specfied as unlimited. A quota limit of 0 means there is no
379 379 * quota specified for the user.
380 380 *
381 381 * Returns: 0 (success) or an errno value
382 382 */
383 383 int
384 384 smb_fssize(smb_request_t *sr, smb_fssize_t *fssize)
385 385 {
386 386 smb_node_t *node;
387 387 struct statvfs64 df;
388 388 uid_t uid;
389 389 smb_quota_t quota;
390 390 int spu; /* sectors per unit */
391 391 int rc;
392 392
393 393 bzero(fssize, sizeof (smb_fssize_t));
394 394 node = sr->tid_tree->t_snode;
395 395 if ((rc = smb_fsop_statfs(sr->user_cr, node, &df)) != 0)
396 396 return (rc);
397 397
398 398 if (df.f_frsize < DEV_BSIZE)
399 399 df.f_frsize = DEV_BSIZE;
400 400 if (df.f_bsize < df.f_frsize)
401 401 df.f_bsize = df.f_frsize;
402 402 spu = df.f_bsize / df.f_frsize;
403 403
404 404 fssize->fs_bytes_per_sector = (uint16_t)df.f_frsize;
405 405 fssize->fs_sectors_per_unit = spu;
406 406
407 407 if (df.f_bavail > df.f_blocks)
408 408 df.f_bavail = 0;
409 409
410 410 fssize->fs_volume_units = df.f_blocks / spu;
411 411 fssize->fs_volume_avail = df.f_bavail / spu;
412 412 fssize->fs_caller_units = df.f_blocks / spu;
413 413 fssize->fs_caller_avail = df.f_bavail / spu;
414 414
415 415 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA))
416 416 return (0);
417 417
418 418 uid = crgetuid(sr->uid_user->u_cred);
419 419 if (smb_quota_query_user_quota(sr, uid, "a) != NT_STATUS_SUCCESS)
420 420 return (0);
421 421
422 422 if ((quota.q_limit != SMB_QUOTA_UNLIMITED) && (quota.q_limit != 0)) {
423 423 fssize->fs_caller_units = quota.q_limit / df.f_bsize;
424 424 if (quota.q_limit <= quota.q_used)
425 425 fssize->fs_caller_avail = 0;
426 426 else
427 427 fssize->fs_caller_avail =
428 428 (quota.q_limit - quota.q_used) / df.f_bsize;
429 429 }
430 430
431 431 return (0);
432 432 }
433 433
434 434 /*
435 435 * smb_com_trans2_set_fs_information
436 436 *
437 437 * This transaction sets filesystem information.
438 438 * The following information levels are supported:
439 439 *
440 440 * InformationLevel Value
441 441 * ================================== ======
442 442 * SMB_FILE_FS_CONTROL_INFORMATION 1006
443 443 */
444 444 smb_sdrc_t
445 445 smb_com_trans2_set_fs_information(smb_request_t *sr, smb_xa_t *xa)
446 446 {
447 447 smb_tree_t *tree;
448 448 uint16_t infolev;
449 449
450 450 tree = sr->tid_tree;
451 451 if (!STYPE_ISDSK(tree->t_res_type)) {
452 452 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
453 453 ERRDOS, ERROR_ACCESS_DENIED);
454 454 return (SDRC_ERROR);
455 455 }
456 456
457 457 if (smb_mbc_decodef(&xa->req_param_mb, "ww",
458 458 &sr->smb_fid, &infolev) != 0)
459 459 return (SDRC_ERROR);
460 460
461 461 switch (infolev) {
462 462 case SMB_FILE_FS_CONTROL_INFORMATION:
463 463 if (smb_trans2_set_fs_ctrl_info(sr, xa) != 0)
464 464 return (SDRC_ERROR);
465 465 break;
466 466
467 467 case SMB_FILE_FS_VOLUME_INFORMATION:
468 468 case SMB_FILE_FS_LABEL_INFORMATION:
469 469 case SMB_FILE_FS_SIZE_INFORMATION:
470 470 case SMB_FILE_FS_DEVICE_INFORMATION:
471 471 case SMB_FILE_FS_ATTRIBUTE_INFORMATION:
472 472 case SMB_FILE_FS_FULLSIZE_INFORMATION:
473 473 case SMB_FILE_FS_OBJECTID_INFORMATION:
474 474 case SMB_FILE_FS_DRIVERPATH_INFORMATION:
475 475 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
476 476 ERRDOS, ERROR_NOT_SUPPORTED);
477 477 return (SDRC_ERROR);
478 478
479 479 default:
480 480 smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
481 481 ERRDOS, ERROR_INVALID_LEVEL);
482 482 return (SDRC_ERROR);
483 483 }
484 484
485 485 return (SDRC_SUCCESS);
486 486 }
487 487
488 488 /*
489 489 * smb_trans2_set_fs_ctrl_info
490 490 *
491 491 * Only users with Admin privileges (i.e. of the BUILTIN/Administrators
492 492 * group) will be allowed to set quotas.
493 493 *
494 494 * Currently QUOTAS are always ENFORCED and the default values
495 495 * are always SMB_QUOTA_UNLIMITED (none). Any attempt to set
496 496 * values other than these will result in NT_STATUS_NOT_SUPPORTED.
497 497 */
498 498 static int
499 499 smb_trans2_set_fs_ctrl_info(smb_request_t *sr, smb_xa_t *xa)
500 500 {
501 501 int rc;
502 502 uint64_t fstart, fthresh, fstop, qthresh, qlimit;
503 503 uint32_t qctrl, qpad;
504 504
505 505 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_QUOTA)) {
506 506 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
507 507 ERRDOS, ERROR_NOT_SUPPORTED);
508 508 return (-1);
509 509 }
510 510
511 511 if (!smb_user_is_admin(sr->uid_user)) {
512 512 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
513 513 ERRDOS, ERROR_ACCESS_DENIED);
514 514 return (-1);
515 515 }
516 516
517 517 rc = smb_mbc_decodef(&xa->req_data_mb, "qqqqqll", &fstart,
518 518 &fthresh, &fstop, &qthresh, &qlimit, &qctrl, &qpad);
519 519
520 520 if ((rc != 0) || (fstart != 0) || (fthresh != 0) || (fstop != 0)) {
521 521 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
522 522 ERRDOS, ERROR_INVALID_PARAMETER);
523 523 return (-1);
524 524 }
525 525
526 526 /* Only support ENFORCED quotas with UNLIMITED default */
527 527 if ((qctrl != FILE_VC_QUOTA_ENFORCE) ||
528 528 (qlimit != SMB_QUOTA_UNLIMITED) ||
529 529 (qthresh != SMB_QUOTA_UNLIMITED)) {
530 530 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
531 531 ERRDOS, ERROR_NOT_SUPPORTED);
532 532 return (-1);
533 533 }
534 534
535 535 return (0);
536 536 }
|
↓ open down ↓ |
462 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX