2 Unix SMB/CIFS implementation.
6 Copyright (C) Stefan Metzmacher 2006
7 Copyright (C) Andrew Tridgell 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "../libcli/smb/smbXcli_base.h"
28 #include "torture/torture.h"
29 #include "torture/smb2/proto.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/util.h"
34 #include "system/filesys.h"
35 #include "auth/credentials/credentials.h"
36 #include "lib/cmdline/popt_common.h"
37 #include "librpc/gen_ndr/security.h"
39 #include "lib/events/events.h"
41 #include "libcli/raw/libcliraw.h"
42 #include "libcli/raw/raw_proto.h"
43 #include "libcli/libcli.h"
45 #define CHECK_STATUS(status, correct) do { \
46 if (!NT_STATUS_EQUAL(status, correct)) { \
47 torture_result(torture, TORTURE_FAIL, \
48 "(%s) Incorrect status %s - should be %s\n", \
49 __location__, nt_errstr(status), nt_errstr(correct)); \
54 #define CHECK_VAL(v, correct) do { \
55 if ((v) != (correct)) { \
56 torture_result(torture, TORTURE_FAIL, \
57 "(%s) wrong value for %s 0x%x should be 0x%x\n", \
58 __location__, #v, (int)v, (int)correct); \
63 #define CHECK_WIRE_STR(field, value) do { \
64 if (!field.s || strcmp(field.s, value)) { \
65 torture_result(torture, TORTURE_FAIL, \
66 "(%s) %s [%s] != %s\n", __location__, #field, \
72 #define WAIT_FOR_ASYNC_RESPONSE(req) \
73 while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \
74 if (tevent_loop_once(torture->ev) != 0) { \
79 #define BASEDIR "test_notify"
80 #define FNAME "smb2-notify01.dat"
82 static bool test_valid_request(struct torture_context
*torture
,
83 struct smb2_tree
*tree
)
87 struct smb2_handle dh
;
89 struct smb2_request
*req
;
90 uint32_t max_buffer_size
;
92 torture_comment(torture
, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
94 smb2_util_unlink(tree
, FNAME
);
96 status
= smb2_util_roothandle(tree
, &dh
);
97 CHECK_STATUS(status
, NT_STATUS_OK
);
99 /* 0x00080000 is the default max buffer size for Windows servers
101 max_buffer_size
= torture_setting_ulong(torture
, "cn_max_buffer_size",
104 n
.in
.recursive
= 0x0000;
105 n
.in
.buffer_size
= max_buffer_size
;
106 n
.in
.file
.handle
= dh
;
107 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
108 n
.in
.unknown
= 0x00000000;
109 req
= smb2_notify_send(tree
, &n
);
111 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
112 if (tevent_loop_once(torture
->ev
) != 0) {
117 status
= torture_setup_complex_file(tree
, FNAME
);
118 CHECK_STATUS(status
, NT_STATUS_OK
);
120 status
= smb2_notify_recv(req
, torture
, &n
);
121 CHECK_STATUS(status
, NT_STATUS_OK
);
122 CHECK_VAL(n
.out
.num_changes
, 1);
123 CHECK_VAL(n
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
124 CHECK_WIRE_STR(n
.out
.changes
[0].name
, FNAME
);
127 * if the change response doesn't fit in the buffer
128 * NOTIFY_ENUM_DIR is returned.
130 n
.in
.buffer_size
= 0x00000000;
131 req
= smb2_notify_send(tree
, &n
);
133 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
134 if (tevent_loop_once(torture
->ev
) != 0) {
139 status
= torture_setup_complex_file(tree
, FNAME
);
140 CHECK_STATUS(status
, NT_STATUS_OK
);
142 status
= smb2_notify_recv(req
, torture
, &n
);
143 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
146 * if the change response fits in the buffer we get
149 n
.in
.buffer_size
= max_buffer_size
;
150 req
= smb2_notify_send(tree
, &n
);
152 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
153 if (tevent_loop_once(torture
->ev
) != 0) {
158 status
= torture_setup_complex_file(tree
, FNAME
);
159 CHECK_STATUS(status
, NT_STATUS_OK
);
161 status
= smb2_notify_recv(req
, torture
, &n
);
162 CHECK_STATUS(status
, NT_STATUS_OK
);
163 CHECK_VAL(n
.out
.num_changes
, 3);
164 CHECK_VAL(n
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
165 CHECK_WIRE_STR(n
.out
.changes
[0].name
, FNAME
);
166 CHECK_VAL(n
.out
.changes
[1].action
, NOTIFY_ACTION_ADDED
);
167 CHECK_WIRE_STR(n
.out
.changes
[1].name
, FNAME
);
168 CHECK_VAL(n
.out
.changes
[2].action
, NOTIFY_ACTION_MODIFIED
);
169 CHECK_WIRE_STR(n
.out
.changes
[2].name
, FNAME
);
171 /* if the first notify returns NOTIFY_ENUM_DIR, all do */
172 status
= smb2_util_close(tree
, dh
);
173 CHECK_STATUS(status
, NT_STATUS_OK
);
174 status
= smb2_util_roothandle(tree
, &dh
);
175 CHECK_STATUS(status
, NT_STATUS_OK
);
177 n
.in
.recursive
= 0x0000;
178 n
.in
.buffer_size
= 0x00000001;
179 n
.in
.file
.handle
= dh
;
180 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
181 n
.in
.unknown
= 0x00000000;
182 req
= smb2_notify_send(tree
, &n
);
184 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
185 if (tevent_loop_once(torture
->ev
) != 0) {
190 status
= torture_setup_complex_file(tree
, FNAME
);
191 CHECK_STATUS(status
, NT_STATUS_OK
);
193 status
= smb2_notify_recv(req
, torture
, &n
);
194 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
196 n
.in
.buffer_size
= max_buffer_size
;
197 req
= smb2_notify_send(tree
, &n
);
198 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
199 if (tevent_loop_once(torture
->ev
) != 0) {
204 status
= torture_setup_complex_file(tree
, FNAME
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
207 status
= smb2_notify_recv(req
, torture
, &n
);
208 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
210 /* if the buffer size is too large, we get invalid parameter */
211 n
.in
.recursive
= 0x0000;
212 n
.in
.buffer_size
= max_buffer_size
+ 1;
213 n
.in
.file
.handle
= dh
;
214 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
215 n
.in
.unknown
= 0x00000000;
216 req
= smb2_notify_send(tree
, &n
);
217 status
= smb2_notify_recv(req
, torture
, &n
);
218 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
225 basic testing of change notify on directories
227 static bool torture_smb2_notify_dir(struct torture_context
*torture
,
228 struct smb2_tree
*tree1
,
229 struct smb2_tree
*tree2
)
233 union smb_notify notify
;
237 struct smb2_handle h1
, h2
;
238 struct smb2_request
*req
, *req2
;
239 const char *fname
= BASEDIR
"\\subdir-name";
240 extern int torture_numops
;
242 torture_comment(torture
, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
244 smb2_deltree(tree1
, BASEDIR
);
245 smb2_util_rmdir(tree1
, BASEDIR
);
247 get a handle on the directory
249 ZERO_STRUCT(io
.smb2
);
250 io
.generic
.level
= RAW_OPEN_SMB2
;
251 io
.smb2
.in
.create_flags
= 0;
252 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
253 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
254 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
255 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
256 NTCREATEX_SHARE_ACCESS_WRITE
;
257 io
.smb2
.in
.alloc_size
= 0;
258 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
259 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
260 io
.smb2
.in
.security_flags
= 0;
261 io
.smb2
.in
.fname
= BASEDIR
;
263 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
264 CHECK_STATUS(status
, NT_STATUS_OK
);
265 h1
= io
.smb2
.out
.file
.handle
;
267 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
268 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
;
269 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
270 CHECK_STATUS(status
, NT_STATUS_OK
);
271 h2
= io
.smb2
.out
.file
.handle
;
273 /* ask for a change notify,
274 on file or directory name changes */
275 ZERO_STRUCT(notify
.smb2
);
276 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
277 notify
.smb2
.in
.buffer_size
= 1000;
278 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
279 notify
.smb2
.in
.file
.handle
= h1
;
280 notify
.smb2
.in
.recursive
= true;
282 torture_comment(torture
, "Testing notify cancel\n");
284 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
286 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
287 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
289 torture_comment(torture
, "Testing notify mkdir\n");
291 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
292 smb2_util_mkdir(tree2
, fname
);
294 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
295 CHECK_STATUS(status
, NT_STATUS_OK
);
297 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
298 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
299 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
301 torture_comment(torture
, "Testing notify rmdir\n");
303 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
304 smb2_util_rmdir(tree2
, fname
);
306 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
307 CHECK_STATUS(status
, NT_STATUS_OK
);
308 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
309 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
310 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
312 torture_comment(torture
,
313 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
315 smb2_util_mkdir(tree2
, fname
);
316 smb2_util_rmdir(tree2
, fname
);
317 smb2_util_mkdir(tree2
, fname
);
318 smb2_util_rmdir(tree2
, fname
);
320 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
321 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
322 CHECK_STATUS(status
, NT_STATUS_OK
);
323 CHECK_VAL(notify
.smb2
.out
.num_changes
, 4);
324 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
325 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
326 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_REMOVED
);
327 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name");
328 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_ADDED
);
329 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name");
330 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_REMOVED
);
331 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name");
333 count
= torture_numops
;
334 torture_comment(torture
,
335 "Testing buffered notify on create of %d files\n", count
);
336 for (i
=0;i
<count
;i
++) {
337 struct smb2_handle h12
;
338 char *fname2
= talloc_asprintf(torture
, BASEDIR
"\\test%d.txt",
341 ZERO_STRUCT(io
.smb2
);
342 io
.generic
.level
= RAW_OPEN_SMB2
;
343 io
.smb2
.in
.create_flags
= 0;
344 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
345 io
.smb2
.in
.create_options
=
346 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
347 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
348 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
349 NTCREATEX_SHARE_ACCESS_WRITE
;
350 io
.smb2
.in
.alloc_size
= 0;
351 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
352 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
353 io
.smb2
.in
.security_flags
= 0;
354 io
.smb2
.in
.fname
= fname2
;
356 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
357 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
358 torture_comment(torture
, "Failed to create %s \n",
363 h12
= io
.smb2
.out
.file
.handle
;
365 smb2_util_close(tree1
, h12
);
368 /* (1st notify) setup a new notify on a different directory handle.
369 This new notify won't see the events above. */
370 notify
.smb2
.in
.file
.handle
= h2
;
371 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
373 /* (2nd notify) whereas this notify will see the above buffered events,
374 and it directly returns the buffered events */
375 notify
.smb2
.in
.file
.handle
= h1
;
376 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
378 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
379 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
381 /* (1st unlink) as the 2nd notify directly returns,
382 this unlink is only seen by the 1st notify and
383 the 3rd notify (later) */
384 torture_comment(torture
,
385 "Testing notify on unlink for the first file\n");
386 status
= smb2_util_unlink(tree2
, BASEDIR
"\\test0.txt");
387 CHECK_STATUS(status
, NT_STATUS_OK
);
389 /* receive the reply from the 2nd notify */
390 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
391 CHECK_STATUS(status
, NT_STATUS_OK
);
393 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
);
394 for (i
=1;i
<count
;i
++) {
395 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
396 NOTIFY_ACTION_ADDED
);
398 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
400 torture_comment(torture
, "and now from the 1st notify\n");
401 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
402 CHECK_STATUS(status
, NT_STATUS_OK
);
403 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
404 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
405 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
407 torture_comment(torture
,
408 "(3rd notify) this notify will only see the 1st unlink\n");
409 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
411 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
412 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
414 for (i
=1;i
<count
;i
++) {
415 char *fname2
= talloc_asprintf(torture
,
416 BASEDIR
"\\test%d.txt", i
);
417 status
= smb2_util_unlink(tree2
, fname2
);
418 CHECK_STATUS(status
, NT_STATUS_OK
);
422 /* receive the 3rd notify */
423 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
424 CHECK_STATUS(status
, NT_STATUS_OK
);
425 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
426 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
427 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
429 /* and we now see the rest of the unlink calls on both
430 * directory handles */
431 notify
.smb2
.in
.file
.handle
= h1
;
433 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
434 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
435 CHECK_STATUS(status
, NT_STATUS_OK
);
436 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
437 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
438 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
439 NOTIFY_ACTION_REMOVED
);
441 notify
.smb2
.in
.file
.handle
= h2
;
442 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
443 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
444 CHECK_STATUS(status
, NT_STATUS_OK
);
445 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
446 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
447 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
448 NOTIFY_ACTION_REMOVED
);
451 torture_comment(torture
,
452 "Testing if a close() on the dir handle triggers the notify reply\n");
454 notify
.smb2
.in
.file
.handle
= h1
;
455 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
457 ZERO_STRUCT(cl
.smb2
);
458 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
459 cl
.smb2
.in
.file
.handle
= h1
;
460 status
= smb2_close(tree1
, &(cl
.smb2
));
461 CHECK_STATUS(status
, NT_STATUS_OK
);
463 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
464 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
465 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
468 smb2_util_close(tree1
, h1
);
469 smb2_util_close(tree1
, h2
);
470 smb2_deltree(tree1
, BASEDIR
);
474 static struct smb2_handle
custom_smb2_create(struct smb2_tree
*tree
,
475 struct torture_context
*torture
,
476 struct smb2_create
*smb2
)
478 struct smb2_handle h1
;
481 smb2_deltree(tree
, smb2
->in
.fname
);
482 status
= smb2_create(tree
, torture
, smb2
);
483 CHECK_STATUS(status
, NT_STATUS_OK
);
484 h1
= smb2
->out
.file
.handle
;
490 testing of recursive change notify
493 static bool torture_smb2_notify_recursive(struct torture_context
*torture
,
494 struct smb2_tree
*tree1
,
495 struct smb2_tree
*tree2
)
499 union smb_notify notify
;
500 union smb_open io
, io1
;
501 union smb_setfileinfo sinfo
;
502 struct smb2_handle h1
;
503 struct smb2_request
*req1
, *req2
;
505 smb2_deltree(tree1
, BASEDIR
);
506 smb2_util_rmdir(tree1
, BASEDIR
);
508 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH RECURSION\n");
511 get a handle on the directory
513 ZERO_STRUCT(io
.smb2
);
514 io
.generic
.level
= RAW_OPEN_SMB2
;
515 io
.smb2
.in
.create_flags
= 0;
516 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
517 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
518 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
519 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
520 NTCREATEX_SHARE_ACCESS_WRITE
;
521 io
.smb2
.in
.alloc_size
= 0;
522 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
523 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
524 io
.smb2
.in
.security_flags
= 0;
525 io
.smb2
.in
.fname
= BASEDIR
;
527 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
528 CHECK_STATUS(status
, NT_STATUS_OK
);
529 h1
= io
.smb2
.out
.file
.handle
;
531 /* ask for a change notify, on file or directory name
532 changes. Setup both with and without recursion */
533 ZERO_STRUCT(notify
.smb2
);
534 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
535 notify
.smb2
.in
.buffer_size
= 1000;
536 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
537 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
538 FILE_NOTIFY_CHANGE_CREATION
;
539 notify
.smb2
.in
.file
.handle
= h1
;
541 notify
.smb2
.in
.recursive
= true;
542 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
544 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
545 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
547 notify
.smb2
.in
.recursive
= false;
548 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
550 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
551 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
553 ZERO_STRUCT(io1
.smb2
);
554 io1
.generic
.level
= RAW_OPEN_SMB2
;
555 io1
.smb2
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
556 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
557 SEC_RIGHTS_FILE_WRITE
|
559 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
560 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
561 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
562 NTCREATEX_SHARE_ACCESS_WRITE
|
563 NTCREATEX_SHARE_ACCESS_DELETE
;
564 io1
.smb2
.in
.alloc_size
= 0;
565 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
566 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
567 io1
.smb2
.in
.security_flags
= 0;
568 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
569 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
570 CHECK_STATUS(status
, NT_STATUS_OK
);
571 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
573 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
574 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
575 CHECK_STATUS(status
, NT_STATUS_OK
);
577 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
578 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
579 sinfo
.rename_information
.in
.overwrite
= 0;
580 sinfo
.rename_information
.in
.root_fid
= 0;
581 sinfo
.rename_information
.in
.new_name
=
582 BASEDIR
"\\subdir-name\\subname1-r";
583 status
= smb2_setinfo_file(tree2
, &sinfo
);
584 CHECK_STATUS(status
, NT_STATUS_OK
);
586 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
587 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
588 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
589 CHECK_STATUS(status
, NT_STATUS_OK
);
591 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
592 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
593 sinfo
.rename_information
.in
.overwrite
= true;
594 sinfo
.rename_information
.in
.root_fid
= 0;
595 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
596 status
= smb2_setinfo_file(tree2
, &sinfo
);
597 CHECK_STATUS(status
, NT_STATUS_OK
);
599 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
600 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
601 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
602 CHECK_STATUS(status
, NT_STATUS_OK
);
604 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
605 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
606 sinfo
.rename_information
.in
.overwrite
= true;
607 sinfo
.rename_information
.in
.root_fid
= 0;
608 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
609 status
= smb2_setinfo_file(tree2
, &sinfo
);
610 CHECK_STATUS(status
, NT_STATUS_OK
);
612 notify
.smb2
.in
.completion_filter
= 0;
613 notify
.smb2
.in
.recursive
= true;
615 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
617 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
618 CHECK_STATUS(status
, NT_STATUS_OK
);
619 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
620 CHECK_STATUS(status
, NT_STATUS_OK
);
621 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
622 CHECK_STATUS(status
, NT_STATUS_OK
);
624 notify
.smb2
.in
.recursive
= false;
625 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
627 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
628 CHECK_STATUS(status
, NT_STATUS_OK
);
630 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
631 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
632 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
633 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_ADDED
);
634 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name\\subname1");
635 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_OLD_NAME
);
636 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name\\subname1");
637 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_NEW_NAME
);
638 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name\\subname1-r");
639 CHECK_VAL(notify
.smb2
.out
.changes
[4].action
, NOTIFY_ACTION_ADDED
);
640 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[4].name
, "subdir-name\\subname2");
641 CHECK_VAL(notify
.smb2
.out
.changes
[5].action
, NOTIFY_ACTION_REMOVED
);
642 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[5].name
, "subdir-name\\subname2");
643 CHECK_VAL(notify
.smb2
.out
.changes
[6].action
, NOTIFY_ACTION_ADDED
);
644 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[6].name
, "subname2-r");
645 CHECK_VAL(notify
.smb2
.out
.changes
[7].action
, NOTIFY_ACTION_OLD_NAME
);
646 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[7].name
, "subname2-r");
647 CHECK_VAL(notify
.smb2
.out
.changes
[8].action
, NOTIFY_ACTION_NEW_NAME
);
648 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[8].name
, "subname3-r");
651 smb2_deltree(tree1
, BASEDIR
);
656 testing of change notify mask change
659 static bool torture_smb2_notify_mask_change(struct torture_context
*torture
,
660 struct smb2_tree
*tree1
,
661 struct smb2_tree
*tree2
)
665 union smb_notify notify
;
666 union smb_open io
, io1
;
667 struct smb2_handle h1
;
668 struct smb2_request
*req1
, *req2
;
669 union smb_setfileinfo sinfo
;
671 smb2_deltree(tree1
, BASEDIR
);
672 smb2_util_rmdir(tree1
, BASEDIR
);
674 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
677 get a handle on the directory
679 ZERO_STRUCT(io
.smb2
);
680 io
.generic
.level
= RAW_OPEN_SMB2
;
681 io
.smb2
.in
.create_flags
= 0;
682 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
683 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
684 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
685 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
686 NTCREATEX_SHARE_ACCESS_WRITE
;
687 io
.smb2
.in
.alloc_size
= 0;
688 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
689 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
690 io
.smb2
.in
.security_flags
= 0;
691 io
.smb2
.in
.fname
= BASEDIR
;
693 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
694 CHECK_STATUS(status
, NT_STATUS_OK
);
695 h1
= io
.smb2
.out
.file
.handle
;
697 /* ask for a change notify, on file or directory name
698 changes. Setup both with and without recursion */
699 ZERO_STRUCT(notify
.smb2
);
700 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
701 notify
.smb2
.in
.buffer_size
= 1000;
702 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
703 notify
.smb2
.in
.file
.handle
= h1
;
705 notify
.smb2
.in
.recursive
= true;
706 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
709 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
710 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
713 notify
.smb2
.in
.recursive
= false;
714 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
717 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
718 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
720 notify
.smb2
.in
.recursive
= true;
721 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
723 /* Set to hidden then back again. */
724 ZERO_STRUCT(io1
.smb2
);
725 io1
.generic
.level
= RAW_OPEN_SMB2
;
726 io1
.smb2
.in
.create_flags
= 0;
727 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
728 SEC_RIGHTS_FILE_WRITE
|
730 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
731 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
732 NTCREATEX_SHARE_ACCESS_WRITE
|
733 NTCREATEX_SHARE_ACCESS_DELETE
;
734 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
735 io1
.smb2
.in
.security_flags
= 0;
736 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
737 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
738 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
740 smb2_util_close(tree1
,
741 custom_smb2_create(tree1
, torture
, &(io1
.smb2
)));
742 status
= smb2_util_setatr(tree1
, BASEDIR
"\\tname1",
743 FILE_ATTRIBUTE_HIDDEN
);
744 CHECK_STATUS(status
, NT_STATUS_OK
);
745 smb2_util_unlink(tree1
, BASEDIR
"\\tname1");
747 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
748 CHECK_STATUS(status
, NT_STATUS_OK
);
750 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
751 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
752 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
754 /* Now try and change the mask to include other events.
755 * This should not work - once the mask is set on a directory
756 * h1 it seems to be fixed until the fnum is closed. */
758 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
759 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
760 FILE_NOTIFY_CHANGE_CREATION
;
761 notify
.smb2
.in
.recursive
= true;
762 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
764 notify
.smb2
.in
.recursive
= false;
765 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
767 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
768 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
769 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
770 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
771 CHECK_STATUS(status
, NT_STATUS_OK
);
772 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
775 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
776 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
777 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
778 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
779 CHECK_STATUS(status
, NT_STATUS_OK
);
780 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
781 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
782 sinfo
.rename_information
.in
.overwrite
= true;
783 sinfo
.rename_information
.in
.root_fid
= 0;
784 sinfo
.rename_information
.in
.new_name
=
785 BASEDIR
"\\subdir-name\\subname1-r";
786 status
= smb2_setinfo_file(tree2
, &sinfo
);
787 CHECK_STATUS(status
, NT_STATUS_OK
);
789 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
790 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
791 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
792 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
793 CHECK_STATUS(status
, NT_STATUS_OK
);
794 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
795 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
796 status
= smb2_setinfo_file(tree2
, &sinfo
);
797 CHECK_STATUS(status
, NT_STATUS_OK
);
798 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
800 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
801 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
802 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
803 CHECK_STATUS(status
, NT_STATUS_OK
);
804 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
805 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
806 status
= smb2_setinfo_file(tree2
, &sinfo
);
807 CHECK_STATUS(status
, NT_STATUS_OK
);
808 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
810 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
811 CHECK_STATUS(status
, NT_STATUS_OK
);
812 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
813 CHECK_STATUS(status
, NT_STATUS_OK
);
814 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
815 CHECK_STATUS(status
, NT_STATUS_OK
);
817 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
818 CHECK_STATUS(status
, NT_STATUS_OK
);
820 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
821 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
822 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subname2-r");
824 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
825 CHECK_STATUS(status
, NT_STATUS_OK
);
827 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
828 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
829 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subname3-r");
836 smb2_deltree(tree1
, BASEDIR
);
841 testing of mask bits for change notify
844 static bool torture_smb2_notify_mask(struct torture_context
*torture
,
845 struct smb2_tree
*tree1
,
846 struct smb2_tree
*tree2
)
850 union smb_notify notify
;
851 union smb_open io
, io1
;
852 struct smb2_handle h1
, h2
;
856 union smb_setfileinfo sinfo
;
858 smb2_deltree(tree1
, BASEDIR
);
859 smb2_util_rmdir(tree1
, BASEDIR
);
861 torture_comment(torture
, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
865 get a handle on the directory
867 ZERO_STRUCT(io
.smb2
);
868 io
.generic
.level
= RAW_OPEN_SMB2
;
869 io
.smb2
.in
.create_flags
= 0;
870 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
871 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
872 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
873 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
874 NTCREATEX_SHARE_ACCESS_WRITE
;
875 io
.smb2
.in
.alloc_size
= 0;
876 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
877 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
878 io
.smb2
.in
.security_flags
= 0;
879 io
.smb2
.in
.fname
= BASEDIR
;
881 ZERO_STRUCT(notify
.smb2
);
882 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
883 notify
.smb2
.in
.buffer_size
= 1000;
884 notify
.smb2
.in
.recursive
= true;
886 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \
887 expected, nchanges) \
889 do { for (mask=i=0;i<32;i++) { \
890 struct smb2_request *req; \
891 status = smb2_create(tree1, torture, &(io.smb2)); \
892 CHECK_STATUS(status, NT_STATUS_OK); \
893 h1 = io.smb2.out.file.handle; \
895 notify.smb2.in.file.handle = h1; \
896 notify.smb2.in.completion_filter = (1<<i); \
897 /* cancel initial requests so the buffer is setup */ \
898 req = smb2_notify_send(tree1, &(notify.smb2)); \
900 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
901 CHECK_STATUS(status, NT_STATUS_CANCELLED); \
902 /* send the change notify request */ \
903 req = smb2_notify_send(tree1, &(notify.smb2)); \
905 smb_msleep(200); smb2_cancel(req); \
906 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
908 smb2_util_close(tree1, h1); \
909 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
910 CHECK_STATUS(status, NT_STATUS_OK); \
911 /* special case to cope with file rename behaviour */ \
912 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \
913 notify.smb2.out.changes[0].action == \
914 NOTIFY_ACTION_MODIFIED && \
915 ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
916 Action == NOTIFY_ACTION_OLD_NAME) { \
917 torture_comment(torture, \
918 "(rename file special handling OK)\n"); \
919 } else if (nchanges != notify.smb2.out.num_changes) { \
920 torture_result(torture, TORTURE_FAIL, \
921 "ERROR: nchanges=%d expected=%d "\
922 "action=%d filter=0x%08x\n", \
923 notify.smb2.out.num_changes, \
925 notify.smb2.out.changes[0].action, \
926 notify.smb2.in.completion_filter); \
928 } else if (notify.smb2.out.changes[0].action != Action) { \
929 torture_result(torture, TORTURE_FAIL, \
930 "ERROR: nchanges=%d action=%d " \
931 "expectedAction=%d filter=0x%08x\n", \
932 notify.smb2.out.num_changes, \
933 notify.smb2.out.changes[0].action, \
935 notify.smb2.in.completion_filter); \
937 } else if (strcmp(notify.smb2.out.changes[0].name.s, \
939 torture_result(torture, TORTURE_FAIL, \
940 "ERROR: nchanges=%d action=%d " \
941 "filter=0x%08x name=%s\n", \
942 notify.smb2.out.num_changes, \
943 notify.smb2.out.changes[0].action, \
944 notify.smb2.in.completion_filter, \
945 notify.smb2.out.changes[0].name.s); \
953 torture_comment(torture
, "Testing mkdir\n");
954 NOTIFY_MASK_TEST("Testing mkdir",;,
955 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
956 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
958 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
960 torture_comment(torture
, "Testing create file\n");
961 ZERO_STRUCT(io1
.smb2
);
962 io1
.generic
.level
= RAW_OPEN_SMB2
;
963 io1
.smb2
.in
.create_flags
= 0;
964 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
965 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
966 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
967 NTCREATEX_SHARE_ACCESS_WRITE
;
968 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
969 io1
.smb2
.in
.security_flags
= 0;
970 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
971 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
972 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
974 NOTIFY_MASK_TEST("Testing create file",;,
975 smb2_util_close(tree2
, custom_smb2_create(tree2
,
976 torture
, &(io1
.smb2
)));,
977 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
979 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
981 torture_comment(torture
, "Testing unlink\n");
982 NOTIFY_MASK_TEST("Testing unlink",
983 smb2_util_close(tree2
, custom_smb2_create(tree2
,
984 torture
, &(io1
.smb2
)));,
985 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
987 NOTIFY_ACTION_REMOVED
,
988 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
990 torture_comment(torture
, "Testing rmdir\n");
991 NOTIFY_MASK_TEST("Testing rmdir",
992 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
993 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
995 NOTIFY_ACTION_REMOVED
,
996 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
998 torture_comment(torture
, "Testing rename file\n");
1000 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1001 sinfo
.rename_information
.in
.file
.handle
= h1
;
1002 sinfo
.rename_information
.in
.overwrite
= true;
1003 sinfo
.rename_information
.in
.root_fid
= 0;
1004 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
1005 NOTIFY_MASK_TEST("Testing rename file",
1006 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1007 torture
, &(io1
.smb2
)));,
1008 smb2_setinfo_file(tree2
, &sinfo
);,
1009 smb2_util_unlink(tree2
, BASEDIR
"\\tname2");,
1010 NOTIFY_ACTION_OLD_NAME
,
1011 FILE_NOTIFY_CHANGE_FILE_NAME
, 2);
1013 torture_comment(torture
, "Testing rename dir\n");
1015 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1016 sinfo
.rename_information
.in
.file
.handle
= h1
;
1017 sinfo
.rename_information
.in
.overwrite
= true;
1018 sinfo
.rename_information
.in
.root_fid
= 0;
1019 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
1020 NOTIFY_MASK_TEST("Testing rename dir",
1021 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
1022 smb2_setinfo_file(tree2
, &sinfo
);,
1023 smb2_util_rmdir(tree2
, BASEDIR
"\\tname2");,
1024 NOTIFY_ACTION_OLD_NAME
,
1025 FILE_NOTIFY_CHANGE_DIR_NAME
, 2);
1027 torture_comment(torture
, "Testing set path attribute\n");
1028 NOTIFY_MASK_TEST("Testing set path attribute",
1029 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1030 torture
, &(io
.smb2
)));,
1031 smb2_util_setatr(tree2
, BASEDIR
"\\tname1",
1032 FILE_ATTRIBUTE_HIDDEN
);,
1033 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1034 NOTIFY_ACTION_MODIFIED
,
1035 FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
1037 torture_comment(torture
, "Testing set path write time\n");
1039 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1040 sinfo
.generic
.in
.file
.handle
= h1
;
1041 sinfo
.basic_info
.in
.write_time
= 1000;
1042 NOTIFY_MASK_TEST("Testing set path write time",
1043 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1044 torture
, &(io1
.smb2
)));,
1045 smb2_setinfo_file(tree2
, &sinfo
);,
1046 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1047 NOTIFY_ACTION_MODIFIED
,
1048 FILE_NOTIFY_CHANGE_LAST_WRITE
, 1);
1050 if (torture_setting_bool(torture
, "samba3", false)) {
1051 torture_comment(torture
,
1052 "Samba3 does not yet support create times "
1057 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1058 sinfo
.generic
.in
.file
.handle
= h1
;
1059 sinfo
.basic_info
.in
.create_time
= 0;
1060 torture_comment(torture
, "Testing set file create time\n");
1061 NOTIFY_MASK_TEST("Testing set file create time",
1062 smb2_create_complex_file(tree2
,
1063 BASEDIR
"\\tname1", &h2
);,
1064 smb2_setinfo_file(tree2
, &sinfo
);,
1065 (smb2_util_close(tree2
, h2
),
1066 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1067 NOTIFY_ACTION_MODIFIED
,
1068 FILE_NOTIFY_CHANGE_CREATION
, 1);
1072 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1073 sinfo
.generic
.in
.file
.handle
= h1
;
1074 sinfo
.basic_info
.in
.access_time
= 0;
1075 torture_comment(torture
, "Testing set file access time\n");
1076 NOTIFY_MASK_TEST("Testing set file access time",
1077 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1078 smb2_setinfo_file(tree2
, &sinfo
);,
1079 (smb2_util_close(tree2
, h2
),
1080 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1081 NOTIFY_ACTION_MODIFIED
,
1082 FILE_NOTIFY_CHANGE_LAST_ACCESS
, 1);
1085 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1086 sinfo
.generic
.in
.file
.handle
= h1
;
1087 sinfo
.basic_info
.in
.change_time
= 0;
1088 torture_comment(torture
, "Testing set file change time\n");
1089 NOTIFY_MASK_TEST("Testing set file change time",
1090 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1091 smb2_setinfo_file(tree2
, &sinfo
);,
1092 (smb2_util_close(tree2
, h2
),
1093 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1094 NOTIFY_ACTION_MODIFIED
,
1098 torture_comment(torture
, "Testing write\n");
1099 NOTIFY_MASK_TEST("Testing write",
1100 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1101 smb2_util_write(tree2
, h2
, &c
, 10000, 1);,
1102 (smb2_util_close(tree2
, h2
),
1103 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1104 NOTIFY_ACTION_MODIFIED
,
1108 smb2_deltree(tree1
, BASEDIR
);
1113 basic testing of change notify on files
1115 static bool torture_smb2_notify_file(struct torture_context
*torture
,
1116 struct smb2_tree
*tree
)
1122 union smb_notify notify
;
1123 struct smb2_request
*req
;
1124 struct smb2_handle h1
;
1125 const char *fname
= BASEDIR
"\\file.txt";
1127 smb2_deltree(tree
, BASEDIR
);
1128 smb2_util_rmdir(tree
, BASEDIR
);
1130 torture_comment(torture
, "TESTING CHANGE NOTIFY ON FILES\n");
1131 status
= torture_smb2_testdir(tree
, BASEDIR
, &h1
);
1132 CHECK_STATUS(status
, NT_STATUS_OK
);
1134 ZERO_STRUCT(io
.smb2
);
1135 io
.generic
.level
= RAW_OPEN_SMB2
;
1136 io
.smb2
.in
.create_flags
= 0;
1137 io
.smb2
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
1138 io
.smb2
.in
.create_options
= 0;
1139 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1140 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1141 NTCREATEX_SHARE_ACCESS_WRITE
;
1142 io
.smb2
.in
.alloc_size
= 0;
1143 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1144 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1145 io
.smb2
.in
.security_flags
= 0;
1146 io
.smb2
.in
.fname
= fname
;
1147 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1148 CHECK_STATUS(status
, NT_STATUS_OK
);
1149 h1
= io
.smb2
.out
.file
.handle
;
1151 /* ask for a change notify,
1152 on file or directory name changes */
1153 ZERO_STRUCT(notify
.smb2
);
1154 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1155 notify
.smb2
.in
.file
.handle
= h1
;
1156 notify
.smb2
.in
.buffer_size
= 1000;
1157 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_STREAM_NAME
;
1158 notify
.smb2
.in
.recursive
= false;
1160 torture_comment(torture
,
1161 "Testing if notifies on file handles are invalid (should be)\n");
1163 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1164 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1165 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1167 ZERO_STRUCT(cl
.smb2
);
1168 cl
.close
.level
= RAW_CLOSE_SMB2
;
1169 cl
.close
.in
.file
.handle
= h1
;
1170 status
= smb2_close(tree
, &(cl
.smb2
));
1171 CHECK_STATUS(status
, NT_STATUS_OK
);
1173 status
= smb2_util_unlink(tree
, fname
);
1174 CHECK_STATUS(status
, NT_STATUS_OK
);
1177 smb2_deltree(tree
, BASEDIR
);
1181 basic testing of change notifies followed by a tdis
1184 static bool torture_smb2_notify_tree_disconnect(
1185 struct torture_context
*torture
,
1186 struct smb2_tree
*tree
)
1190 union smb_notify notify
;
1192 struct smb2_handle h1
;
1193 struct smb2_request
*req
;
1195 smb2_deltree(tree
, BASEDIR
);
1196 smb2_util_rmdir(tree
, BASEDIR
);
1198 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY "
1199 "TREE-DISCONNECT\n");
1202 get a handle on the directory
1204 ZERO_STRUCT(io
.smb2
);
1205 io
.generic
.level
= RAW_OPEN_SMB2
;
1206 io
.smb2
.in
.create_flags
= 0;
1207 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1208 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1209 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1210 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1211 NTCREATEX_SHARE_ACCESS_WRITE
;
1212 io
.smb2
.in
.alloc_size
= 0;
1213 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1214 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1215 io
.smb2
.in
.security_flags
= 0;
1216 io
.smb2
.in
.fname
= BASEDIR
;
1218 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1219 CHECK_STATUS(status
, NT_STATUS_OK
);
1220 h1
= io
.smb2
.out
.file
.handle
;
1222 /* ask for a change notify,
1223 on file or directory name changes */
1224 ZERO_STRUCT(notify
.smb2
);
1225 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1226 notify
.smb2
.in
.buffer_size
= 1000;
1227 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1228 notify
.smb2
.in
.file
.handle
= h1
;
1229 notify
.smb2
.in
.recursive
= true;
1231 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1233 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1235 status
= smb2_tdis(tree
);
1236 CHECK_STATUS(status
, NT_STATUS_OK
);
1238 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1240 smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1241 CHECK_STATUS(status
, NT_STATUS_OK
);
1242 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1245 smb2_deltree(tree
, BASEDIR
);
1250 basic testing of change notifies followed by a ulogoff
1253 static bool torture_smb2_notify_ulogoff(struct torture_context
*torture
,
1254 struct smb2_tree
*tree1
)
1258 union smb_notify notify
;
1260 struct smb2_handle h1
;
1261 struct smb2_request
*req
;
1263 smb2_deltree(tree1
, BASEDIR
);
1264 smb2_util_rmdir(tree1
, BASEDIR
);
1266 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1269 get a handle on the directory
1271 ZERO_STRUCT(io
.smb2
);
1272 io
.generic
.level
= RAW_OPEN_SMB2
;
1273 io
.smb2
.in
.create_flags
= 0;
1274 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1275 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1276 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1277 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1278 NTCREATEX_SHARE_ACCESS_WRITE
;
1279 io
.smb2
.in
.alloc_size
= 0;
1280 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1281 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1282 io
.smb2
.in
.security_flags
= 0;
1283 io
.smb2
.in
.fname
= BASEDIR
;
1285 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1286 CHECK_STATUS(status
, NT_STATUS_OK
);
1288 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1289 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1290 CHECK_STATUS(status
, NT_STATUS_OK
);
1291 h1
= io
.smb2
.out
.file
.handle
;
1293 /* ask for a change notify,
1294 on file or directory name changes */
1295 ZERO_STRUCT(notify
.smb2
);
1296 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1297 notify
.smb2
.in
.buffer_size
= 1000;
1298 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1299 notify
.smb2
.in
.file
.handle
= h1
;
1300 notify
.smb2
.in
.recursive
= true;
1302 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1304 WAIT_FOR_ASYNC_RESPONSE(req
);
1306 status
= smb2_logoff(tree1
->session
);
1307 CHECK_STATUS(status
, NT_STATUS_OK
);
1309 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1310 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1313 smb2_deltree(tree1
, BASEDIR
);
1317 static void tcp_dis_handler(struct smb2_transport
*t
, void *p
)
1319 struct smb2_tree
*tree
= (struct smb2_tree
*)p
;
1320 smb2_transport_dead(tree
->session
->transport
,
1321 NT_STATUS_LOCAL_DISCONNECT
);
1327 basic testing of change notifies followed by tcp disconnect
1330 static bool torture_smb2_notify_tcp_disconnect(
1331 struct torture_context
*torture
,
1332 struct smb2_tree
*tree
)
1336 union smb_notify notify
;
1338 struct smb2_handle h1
;
1339 struct smb2_request
*req
;
1341 smb2_deltree(tree
, BASEDIR
);
1342 smb2_util_rmdir(tree
, BASEDIR
);
1344 torture_comment(torture
,
1345 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1348 get a handle on the directory
1350 ZERO_STRUCT(io
.smb2
);
1351 io
.generic
.level
= RAW_OPEN_SMB2
;
1352 io
.smb2
.in
.create_flags
= 0;
1353 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1354 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1355 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1356 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1357 NTCREATEX_SHARE_ACCESS_WRITE
;
1358 io
.smb2
.in
.alloc_size
= 0;
1359 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1360 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1361 io
.smb2
.in
.security_flags
= 0;
1362 io
.smb2
.in
.fname
= BASEDIR
;
1364 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1365 CHECK_STATUS(status
, NT_STATUS_OK
);
1366 h1
= io
.smb2
.out
.file
.handle
;
1368 /* ask for a change notify,
1369 on file or directory name changes */
1370 ZERO_STRUCT(notify
.smb2
);
1371 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1372 notify
.smb2
.in
.buffer_size
= 1000;
1373 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1374 notify
.smb2
.in
.file
.handle
= h1
;
1375 notify
.smb2
.in
.recursive
= true;
1377 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1379 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1380 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1382 notify
.smb2
.in
.recursive
= true;
1383 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1384 smb2_transport_idle_handler(tree
->session
->transport
,
1385 tcp_dis_handler
, 250, tree
);
1387 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1388 CHECK_STATUS(status
, NT_STATUS_LOCAL_DISCONNECT
);
1395 test setting up two change notify requests on one handle
1398 static bool torture_smb2_notify_double(struct torture_context
*torture
,
1399 struct smb2_tree
*tree1
,
1400 struct smb2_tree
*tree2
)
1404 union smb_notify notify
;
1406 struct smb2_handle h1
;
1407 struct smb2_request
*req1
, *req2
;
1409 smb2_deltree(tree1
, BASEDIR
);
1410 smb2_util_rmdir(tree1
, BASEDIR
);
1412 torture_comment(torture
,
1413 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1416 get a handle on the directory
1418 ZERO_STRUCT(io
.smb2
);
1419 io
.generic
.level
= RAW_OPEN_SMB2
;
1420 io
.smb2
.in
.create_flags
= 0;
1421 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
1422 SEC_RIGHTS_FILE_WRITE
|
1423 SEC_RIGHTS_FILE_ALL
;
1424 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1425 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1426 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1427 NTCREATEX_SHARE_ACCESS_WRITE
;
1428 io
.smb2
.in
.alloc_size
= 0;
1429 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1430 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1431 io
.smb2
.in
.security_flags
= 0;
1432 io
.smb2
.in
.fname
= BASEDIR
;
1434 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1435 CHECK_STATUS(status
, NT_STATUS_OK
);
1436 h1
= io
.smb2
.out
.file
.handle
;
1438 /* ask for a change notify,
1439 on file or directory name changes */
1440 ZERO_STRUCT(notify
.smb2
);
1441 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1442 notify
.smb2
.in
.buffer_size
= 1000;
1443 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1444 notify
.smb2
.in
.file
.handle
= h1
;
1445 notify
.smb2
.in
.recursive
= true;
1447 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1449 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1450 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1452 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1454 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1455 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1457 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name");
1458 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1459 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1461 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1462 CHECK_STATUS(status
, NT_STATUS_OK
);
1463 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1464 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1466 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name2");
1468 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1469 CHECK_STATUS(status
, NT_STATUS_OK
);
1470 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1471 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name2");
1474 smb2_deltree(tree1
, BASEDIR
);
1480 test multiple change notifies at different depths and with/without recursion
1483 static bool torture_smb2_notify_tree(struct torture_context
*torture
,
1484 struct smb2_tree
*tree
)
1487 union smb_notify notify
;
1489 struct smb2_request
*req
;
1496 struct smb2_handle h1
;
1499 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 30 },
1500 {BASEDIR
"\\zqy", true, FILE_NOTIFY_CHANGE_NAME
, 8 },
1501 {BASEDIR
"\\atsy", true, FILE_NOTIFY_CHANGE_NAME
, 4 },
1502 {BASEDIR
"\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1503 {BASEDIR
"\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME
, 13 },
1504 {BASEDIR
"\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME
, 7 },
1505 {BASEDIR
"\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1506 {BASEDIR
"\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1507 {BASEDIR
"\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1508 {BASEDIR
"\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1509 {BASEDIR
"\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1510 {BASEDIR
"\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1511 {BASEDIR
"\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1512 {BASEDIR
, true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1513 {BASEDIR
, false,FILE_NOTIFY_CHANGE_NAME
, 6 },
1514 {BASEDIR
"\\atsy", false,FILE_NOTIFY_CHANGE_NAME
, 4 },
1515 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1516 {BASEDIR
"\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1517 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1518 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1522 bool all_done
= false;
1524 smb2_deltree(tree
, BASEDIR
);
1525 smb2_util_rmdir(tree
, BASEDIR
);
1527 torture_comment(torture
, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1529 ZERO_STRUCT(io
.smb2
);
1530 io
.generic
.level
= RAW_OPEN_SMB2
;
1531 io
.smb2
.in
.create_flags
= 0;
1532 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1533 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1534 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1535 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1536 NTCREATEX_SHARE_ACCESS_WRITE
;
1537 io
.smb2
.in
.alloc_size
= 0;
1538 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1539 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1540 io
.smb2
.in
.security_flags
= 0;
1541 io
.smb2
.in
.fname
= BASEDIR
;
1542 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1543 CHECK_STATUS(status
, NT_STATUS_OK
);
1545 ZERO_STRUCT(notify
.smb2
);
1546 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1547 notify
.smb2
.in
.buffer_size
= 20000;
1550 setup the directory tree, and the notify buffer on each directory
1552 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1553 io
.smb2
.in
.fname
= dirs
[i
].path
;
1554 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1555 CHECK_STATUS(status
, NT_STATUS_OK
);
1556 dirs
[i
].h1
= io
.smb2
.out
.file
.handle
;
1558 notify
.smb2
.in
.completion_filter
= dirs
[i
].filter
;
1559 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1560 notify
.smb2
.in
.recursive
= dirs
[i
].recursive
;
1561 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1563 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1564 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1567 /* trigger 2 events in each dir */
1568 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1569 char *path
= talloc_asprintf(torture
, "%s\\test.dir",
1571 smb2_util_mkdir(tree
, path
);
1572 smb2_util_rmdir(tree
, path
);
1576 /* give a bit of time for the events to propogate */
1577 tv
= timeval_current();
1580 /* count events that have happened in each dir */
1581 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1582 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1583 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1585 notify
.smb2
.out
.num_changes
= 0;
1586 status
= smb2_notify_recv(req
, torture
,
1588 dirs
[i
].counted
+= notify
.smb2
.out
.num_changes
;
1593 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1594 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1598 } while (!all_done
&& timeval_elapsed(&tv
) < 20);
1600 torture_comment(torture
, "took %.4f seconds to propogate all events\n",
1601 timeval_elapsed(&tv
));
1603 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1604 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1605 torture_comment(torture
,
1606 "ERROR: i=%d expected %d got %d for '%s'\n",
1607 i
, dirs
[i
].expected
, dirs
[i
].counted
,
1614 run from the back, closing and deleting
1616 for (i
=ARRAY_SIZE(dirs
)-1;i
>=0;i
--) {
1617 smb2_util_close(tree
, dirs
[i
].h1
);
1618 smb2_util_rmdir(tree
, dirs
[i
].path
);
1622 smb2_deltree(tree
, BASEDIR
);
1623 smb2_util_rmdir(tree
, BASEDIR
);
1628 Test response when cached server events exceed single NT NOTFIY response
1632 static bool torture_smb2_notify_overflow(struct torture_context
*torture
,
1633 struct smb2_tree
*tree
)
1637 union smb_notify notify
;
1639 struct smb2_handle h1
, h2
;
1641 struct smb2_request
*req1
;
1644 smb2_deltree(tree
, BASEDIR
);
1645 smb2_util_rmdir(tree
, BASEDIR
);
1647 torture_comment(torture
, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1649 /* get a handle on the directory */
1650 ZERO_STRUCT(io
.smb2
);
1651 io
.generic
.level
= RAW_OPEN_SMB2
;
1652 io
.smb2
.in
.create_flags
= 0;
1653 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1654 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1655 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1656 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1657 NTCREATEX_SHARE_ACCESS_WRITE
;
1658 io
.smb2
.in
.alloc_size
= 0;
1659 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1660 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1661 io
.smb2
.in
.security_flags
= 0;
1662 io
.smb2
.in
.fname
= BASEDIR
;
1664 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1665 CHECK_STATUS(status
, NT_STATUS_OK
);
1666 h1
= io
.smb2
.out
.file
.handle
;
1668 /* ask for a change notify, on name changes. */
1669 ZERO_STRUCT(notify
.smb2
);
1670 notify
.smb2
.level
= RAW_NOTIFY_NTTRANS
;
1671 notify
.smb2
.in
.buffer_size
= 1000;
1672 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1673 notify
.smb2
.in
.file
.handle
= h1
;
1675 notify
.smb2
.in
.recursive
= true;
1676 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1678 /* cancel initial requests so the buffer is setup */
1680 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1681 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1683 /* open a lot of files, filling up the server side notify buffer */
1684 torture_comment(torture
,
1685 "Testing overflowed buffer notify on create of %d files\n",
1688 for (i
=0;i
<count
;i
++) {
1689 char *fname
= talloc_asprintf(torture
,
1690 BASEDIR
"\\test%d.txt", i
);
1692 ZERO_STRUCT(io1
.smb2
);
1693 io1
.generic
.level
= RAW_OPEN_SMB2
;
1694 io1
.smb2
.in
.create_flags
= 0;
1695 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1696 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1697 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1698 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1699 NTCREATEX_SHARE_ACCESS_WRITE
;
1700 io1
.smb2
.in
.alloc_size
= 0;
1701 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1702 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1703 io1
.smb2
.in
.security_flags
= 0;
1704 io1
.smb2
.in
.fname
= fname
;
1706 h2
= custom_smb2_create(tree
, torture
, &(io1
.smb2
));
1708 smb2_util_close(tree
, h2
);
1711 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1712 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1713 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
1714 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1717 smb2_deltree(tree
, BASEDIR
);
1722 Test if notifications are returned for changes to the base directory.
1726 static bool torture_smb2_notify_basedir(struct torture_context
*torture
,
1727 struct smb2_tree
*tree1
,
1728 struct smb2_tree
*tree2
)
1732 union smb_notify notify
;
1734 struct smb2_handle h1
;
1735 struct smb2_request
*req1
;
1737 smb2_deltree(tree1
, BASEDIR
);
1738 smb2_util_rmdir(tree1
, BASEDIR
);
1740 torture_comment(torture
, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1742 /* get a handle on the directory */
1743 ZERO_STRUCT(io
.smb2
);
1744 io
.generic
.level
= RAW_OPEN_SMB2
;
1745 io
.smb2
.in
.create_flags
= 0;
1746 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1747 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1748 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1749 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1750 NTCREATEX_SHARE_ACCESS_WRITE
;
1751 io
.smb2
.in
.alloc_size
= 0;
1752 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1753 io
.smb2
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1754 io
.smb2
.in
.security_flags
= 0;
1755 io
.smb2
.in
.fname
= BASEDIR
;
1757 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1758 CHECK_STATUS(status
, NT_STATUS_OK
);
1759 h1
= io
.smb2
.out
.file
.handle
;
1761 /* create a test file that will also be modified */
1762 io
.smb2
.in
.fname
= BASEDIR
"\\tname1";
1763 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1764 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1765 CHECK_STATUS(status
,NT_STATUS_OK
);
1766 smb2_util_close(tree2
, io
.smb2
.out
.file
.handle
);
1768 /* ask for a change notify, on attribute changes. */
1769 ZERO_STRUCT(notify
.smb2
);
1770 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1771 notify
.smb2
.in
.buffer_size
= 1000;
1772 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
1773 notify
.smb2
.in
.file
.handle
= h1
;
1774 notify
.smb2
.in
.recursive
= true;
1776 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1778 /* set attribute on the base dir */
1779 smb2_util_setatr(tree2
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
);
1781 /* set attribute on a file to assure we receive a notification */
1782 smb2_util_setatr(tree2
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
);
1785 /* check how many responses were given, expect only 1 for the file */
1786 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1787 CHECK_STATUS(status
, NT_STATUS_OK
);
1788 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1789 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
1790 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
1793 smb2_deltree(tree1
, BASEDIR
);
1799 create a secondary tree connect - used to test for a bug in Samba3 messaging
1802 static struct smb2_tree
*secondary_tcon(struct smb2_tree
*tree
,
1803 struct torture_context
*tctx
)
1806 const char *share
, *host
;
1807 struct smb2_tree
*tree1
;
1808 union smb_tcon tcon
;
1810 share
= torture_setting_string(tctx
, "share", NULL
);
1811 host
= torture_setting_string(tctx
, "host", NULL
);
1813 torture_comment(tctx
,
1814 "create a second tree context on the same session\n");
1815 tree1
= smb2_tree_init(tree
->session
, tctx
, false);
1816 if (tree1
== NULL
) {
1817 torture_comment(tctx
, "Out of memory\n");
1821 ZERO_STRUCT(tcon
.smb2
);
1822 tcon
.generic
.level
= RAW_TCON_SMB2
;
1823 tcon
.smb2
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
1824 status
= smb2_tree_connect(tree
->session
, &(tcon
.smb2
));
1825 if (!NT_STATUS_IS_OK(status
)) {
1827 torture_comment(tctx
,"Failed to create secondary tree\n");
1831 smb2cli_tcon_set_values(tree1
->smbXcli
,
1832 tree1
->session
->smbXcli
,
1834 tcon
.smb2
.out
.share_type
,
1835 tcon
.smb2
.out
.flags
,
1836 tcon
.smb2
.out
.capabilities
,
1837 tcon
.smb2
.out
.access_mask
);
1839 torture_comment(tctx
,"tid1=%d tid2=%d\n",
1840 smb2cli_tcon_current_id(tree
->smbXcli
),
1841 smb2cli_tcon_current_id(tree1
->smbXcli
));
1848 very simple change notify test
1850 static bool torture_smb2_notify_tcon(struct torture_context
*torture
,
1851 struct smb2_tree
*tree
)
1855 union smb_notify notify
;
1857 struct smb2_handle h1
;
1858 struct smb2_request
*req
= NULL
;
1859 struct smb2_tree
*tree1
= NULL
;
1860 const char *fname
= BASEDIR
"\\subdir-name";
1862 smb2_deltree(tree
, BASEDIR
);
1863 smb2_util_rmdir(tree
, BASEDIR
);
1865 torture_comment(torture
, "TESTING SIMPLE CHANGE NOTIFY\n");
1868 get a handle on the directory
1871 ZERO_STRUCT(io
.smb2
);
1872 io
.generic
.level
= RAW_OPEN_SMB2
;
1873 io
.smb2
.in
.create_flags
= 0;
1874 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1875 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1876 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
|
1877 FILE_ATTRIBUTE_DIRECTORY
;
1878 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1879 NTCREATEX_SHARE_ACCESS_WRITE
;
1880 io
.smb2
.in
.alloc_size
= 0;
1881 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1882 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1883 io
.smb2
.in
.security_flags
= 0;
1884 io
.smb2
.in
.fname
= BASEDIR
;
1886 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1887 CHECK_STATUS(status
, NT_STATUS_OK
);
1888 h1
= io
.smb2
.out
.file
.handle
;
1890 /* ask for a change notify,
1891 on file or directory name changes */
1892 ZERO_STRUCT(notify
.smb2
);
1893 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1894 notify
.smb2
.in
.buffer_size
= 1000;
1895 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1896 notify
.smb2
.in
.file
.handle
= h1
;
1897 notify
.smb2
.in
.recursive
= true;
1899 torture_comment(torture
, "Testing notify mkdir\n");
1900 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1902 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1903 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1905 notify
.smb2
.in
.recursive
= true;
1906 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1907 status
= smb2_util_mkdir(tree
, fname
);
1908 CHECK_STATUS(status
, NT_STATUS_OK
);
1910 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1911 CHECK_STATUS(status
, NT_STATUS_OK
);
1913 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1914 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1915 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1917 torture_comment(torture
, "Testing notify rmdir\n");
1918 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1919 status
= smb2_util_rmdir(tree
, fname
);
1920 CHECK_STATUS(status
, NT_STATUS_OK
);
1922 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1923 CHECK_STATUS(status
, NT_STATUS_OK
);
1924 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1925 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1926 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1928 torture_comment(torture
, "SIMPLE CHANGE NOTIFY OK\n");
1930 torture_comment(torture
, "TESTING WITH SECONDARY TCON\n");
1931 tree1
= secondary_tcon(tree
, torture
);
1933 torture_comment(torture
, "Testing notify mkdir\n");
1934 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1935 smb2_util_mkdir(tree1
, fname
);
1937 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1938 CHECK_STATUS(status
, NT_STATUS_OK
);
1940 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1941 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1942 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1944 torture_comment(torture
, "Testing notify rmdir\n");
1945 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1946 smb2_util_rmdir(tree
, fname
);
1948 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1949 CHECK_STATUS(status
, NT_STATUS_OK
);
1950 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1951 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1952 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1954 torture_comment(torture
, "CHANGE NOTIFY WITH TCON OK\n");
1956 torture_comment(torture
, "Disconnecting secondary tree\n");
1957 status
= smb2_tdis(tree1
);
1958 CHECK_STATUS(status
, NT_STATUS_OK
);
1961 torture_comment(torture
, "Testing notify mkdir\n");
1962 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1963 smb2_util_mkdir(tree
, fname
);
1965 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1966 CHECK_STATUS(status
, NT_STATUS_OK
);
1968 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1969 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1970 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1972 torture_comment(torture
, "Testing notify rmdir\n");
1973 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1974 smb2_util_rmdir(tree
, fname
);
1976 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1977 CHECK_STATUS(status
, NT_STATUS_OK
);
1978 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1979 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1980 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1982 torture_comment(torture
, "CHANGE NOTIFY WITH TDIS OK\n");
1984 smb2_util_close(tree
, h1
);
1985 smb2_deltree(tree
, BASEDIR
);
1991 basic testing of SMB2 change notify
1993 struct torture_suite
*torture_smb2_notify_init(void)
1995 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "notify");
1997 torture_suite_add_1smb2_test(suite
, "valid-req", test_valid_request
);
1998 torture_suite_add_1smb2_test(suite
, "tcon", torture_smb2_notify_tcon
);
1999 torture_suite_add_2smb2_test(suite
, "dir", torture_smb2_notify_dir
);
2000 torture_suite_add_2smb2_test(suite
, "mask", torture_smb2_notify_mask
);
2001 torture_suite_add_1smb2_test(suite
, "tdis", torture_smb2_notify_tree_disconnect
);
2002 torture_suite_add_2smb2_test(suite
, "mask-change", torture_smb2_notify_mask_change
);
2003 torture_suite_add_1smb2_test(suite
, "logoff", torture_smb2_notify_ulogoff
);
2004 torture_suite_add_1smb2_test(suite
, "tree", torture_smb2_notify_tree
);
2005 torture_suite_add_2smb2_test(suite
, "basedir", torture_smb2_notify_basedir
);
2006 torture_suite_add_2smb2_test(suite
, "double", torture_smb2_notify_double
);
2007 torture_suite_add_1smb2_test(suite
, "file", torture_smb2_notify_file
);
2008 torture_suite_add_1smb2_test(suite
, "tcp", torture_smb2_notify_tcp_disconnect
);
2009 torture_suite_add_2smb2_test(suite
, "rec", torture_smb2_notify_recursive
);
2010 torture_suite_add_1smb2_test(suite
, "overflow", torture_smb2_notify_overflow
);
2012 suite
->description
= talloc_strdup(suite
, "SMB2-NOTIFY tests");