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 BASEDIR "test_notify"
73 #define FNAME "smb2-notify01.dat"
75 static bool test_valid_request(struct torture_context
*torture
,
76 struct smb2_tree
*tree
)
80 struct smb2_handle dh
;
82 struct smb2_request
*req
;
83 uint32_t max_buffer_size
;
85 torture_comment(torture
, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
87 smb2_util_unlink(tree
, FNAME
);
89 status
= smb2_util_roothandle(tree
, &dh
);
90 CHECK_STATUS(status
, NT_STATUS_OK
);
92 /* 0x00080000 is the default max buffer size for Windows servers
94 max_buffer_size
= torture_setting_ulong(torture
, "cn_max_buffer_size",
97 n
.in
.recursive
= 0x0000;
98 n
.in
.buffer_size
= max_buffer_size
;
99 n
.in
.file
.handle
= dh
;
100 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
101 n
.in
.unknown
= 0x00000000;
102 req
= smb2_notify_send(tree
, &n
);
104 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
105 if (tevent_loop_once(torture
->ev
) != 0) {
110 status
= torture_setup_complex_file(tree
, FNAME
);
111 CHECK_STATUS(status
, NT_STATUS_OK
);
113 status
= smb2_notify_recv(req
, torture
, &n
);
114 CHECK_STATUS(status
, NT_STATUS_OK
);
115 CHECK_VAL(n
.out
.num_changes
, 1);
116 CHECK_VAL(n
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
117 CHECK_WIRE_STR(n
.out
.changes
[0].name
, FNAME
);
120 * if the change response doesn't fit in the buffer
121 * NOTIFY_ENUM_DIR is returned.
123 n
.in
.buffer_size
= 0x00000000;
124 req
= smb2_notify_send(tree
, &n
);
126 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
127 if (tevent_loop_once(torture
->ev
) != 0) {
132 status
= torture_setup_complex_file(tree
, FNAME
);
133 CHECK_STATUS(status
, NT_STATUS_OK
);
135 status
= smb2_notify_recv(req
, torture
, &n
);
136 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
139 * if the change response fits in the buffer we get
142 n
.in
.buffer_size
= max_buffer_size
;
143 req
= smb2_notify_send(tree
, &n
);
145 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
146 if (tevent_loop_once(torture
->ev
) != 0) {
151 status
= torture_setup_complex_file(tree
, FNAME
);
152 CHECK_STATUS(status
, NT_STATUS_OK
);
154 status
= smb2_notify_recv(req
, torture
, &n
);
155 CHECK_STATUS(status
, NT_STATUS_OK
);
156 CHECK_VAL(n
.out
.num_changes
, 3);
157 CHECK_VAL(n
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
158 CHECK_WIRE_STR(n
.out
.changes
[0].name
, FNAME
);
159 CHECK_VAL(n
.out
.changes
[1].action
, NOTIFY_ACTION_ADDED
);
160 CHECK_WIRE_STR(n
.out
.changes
[1].name
, FNAME
);
161 CHECK_VAL(n
.out
.changes
[2].action
, NOTIFY_ACTION_MODIFIED
);
162 CHECK_WIRE_STR(n
.out
.changes
[2].name
, FNAME
);
164 /* if the first notify returns NOTIFY_ENUM_DIR, all do */
165 status
= smb2_util_close(tree
, dh
);
166 CHECK_STATUS(status
, NT_STATUS_OK
);
167 status
= smb2_util_roothandle(tree
, &dh
);
168 CHECK_STATUS(status
, NT_STATUS_OK
);
170 n
.in
.recursive
= 0x0000;
171 n
.in
.buffer_size
= 0x00000001;
172 n
.in
.file
.handle
= dh
;
173 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
174 n
.in
.unknown
= 0x00000000;
175 req
= smb2_notify_send(tree
, &n
);
177 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
178 if (tevent_loop_once(torture
->ev
) != 0) {
183 status
= torture_setup_complex_file(tree
, FNAME
);
184 CHECK_STATUS(status
, NT_STATUS_OK
);
186 status
= smb2_notify_recv(req
, torture
, &n
);
187 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
189 n
.in
.buffer_size
= max_buffer_size
;
190 req
= smb2_notify_send(tree
, &n
);
191 while (!req
->cancel
.can_cancel
&& req
->state
<= SMB2_REQUEST_RECV
) {
192 if (tevent_loop_once(torture
->ev
) != 0) {
197 status
= torture_setup_complex_file(tree
, FNAME
);
198 CHECK_STATUS(status
, NT_STATUS_OK
);
200 status
= smb2_notify_recv(req
, torture
, &n
);
201 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
203 /* if the buffer size is too large, we get invalid parameter */
204 n
.in
.recursive
= 0x0000;
205 n
.in
.buffer_size
= max_buffer_size
+ 1;
206 n
.in
.file
.handle
= dh
;
207 n
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ALL
;
208 n
.in
.unknown
= 0x00000000;
209 req
= smb2_notify_send(tree
, &n
);
210 status
= smb2_notify_recv(req
, torture
, &n
);
211 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
218 basic testing of change notify on directories
220 static bool torture_smb2_notify_dir(struct torture_context
*torture
,
221 struct smb2_tree
*tree1
,
222 struct smb2_tree
*tree2
)
226 union smb_notify notify
;
230 struct smb2_handle h1
, h2
;
231 struct smb2_request
*req
, *req2
;
232 const char *fname
= BASEDIR
"\\subdir-name";
233 extern int torture_numops
;
235 torture_comment(torture
, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
237 smb2_deltree(tree1
, BASEDIR
);
238 smb2_util_rmdir(tree1
, BASEDIR
);
240 get a handle on the directory
242 ZERO_STRUCT(io
.smb2
);
243 io
.generic
.level
= RAW_OPEN_SMB2
;
244 io
.smb2
.in
.create_flags
= 0;
245 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
246 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
247 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
248 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
249 NTCREATEX_SHARE_ACCESS_WRITE
;
250 io
.smb2
.in
.alloc_size
= 0;
251 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
252 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
253 io
.smb2
.in
.security_flags
= 0;
254 io
.smb2
.in
.fname
= BASEDIR
;
256 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
257 CHECK_STATUS(status
, NT_STATUS_OK
);
258 h1
= io
.smb2
.out
.file
.handle
;
260 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
261 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
;
262 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
263 CHECK_STATUS(status
, NT_STATUS_OK
);
264 h2
= io
.smb2
.out
.file
.handle
;
266 /* ask for a change notify,
267 on file or directory name changes */
268 ZERO_STRUCT(notify
.smb2
);
269 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
270 notify
.smb2
.in
.buffer_size
= 1000;
271 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
272 notify
.smb2
.in
.file
.handle
= h1
;
273 notify
.smb2
.in
.recursive
= true;
275 torture_comment(torture
, "Testing notify cancel\n");
277 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
279 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
280 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
282 torture_comment(torture
, "Testing notify mkdir\n");
284 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
285 smb2_util_mkdir(tree2
, fname
);
287 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
288 CHECK_STATUS(status
, NT_STATUS_OK
);
290 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
291 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
292 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
294 torture_comment(torture
, "Testing notify rmdir\n");
296 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
297 smb2_util_rmdir(tree2
, fname
);
299 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
300 CHECK_STATUS(status
, NT_STATUS_OK
);
301 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
302 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
303 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
305 torture_comment(torture
,
306 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
308 smb2_util_mkdir(tree2
, fname
);
309 smb2_util_rmdir(tree2
, fname
);
310 smb2_util_mkdir(tree2
, fname
);
311 smb2_util_rmdir(tree2
, fname
);
313 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
314 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
315 CHECK_STATUS(status
, NT_STATUS_OK
);
316 CHECK_VAL(notify
.smb2
.out
.num_changes
, 4);
317 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
318 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
319 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_REMOVED
);
320 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name");
321 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_ADDED
);
322 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name");
323 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_REMOVED
);
324 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name");
326 count
= torture_numops
;
327 torture_comment(torture
,
328 "Testing buffered notify on create of %d files\n", count
);
329 for (i
=0;i
<count
;i
++) {
330 struct smb2_handle h12
;
331 char *fname2
= talloc_asprintf(torture
, BASEDIR
"\\test%d.txt",
334 ZERO_STRUCT(io
.smb2
);
335 io
.generic
.level
= RAW_OPEN_SMB2
;
336 io
.smb2
.in
.create_flags
= 0;
337 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
338 io
.smb2
.in
.create_options
=
339 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
340 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
341 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
342 NTCREATEX_SHARE_ACCESS_WRITE
;
343 io
.smb2
.in
.alloc_size
= 0;
344 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
345 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
346 io
.smb2
.in
.security_flags
= 0;
347 io
.smb2
.in
.fname
= fname2
;
349 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
350 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
351 torture_comment(torture
, "Failed to create %s \n",
356 h12
= io
.smb2
.out
.file
.handle
;
358 smb2_util_close(tree1
, h12
);
361 /* (1st notify) setup a new notify on a different directory handle.
362 This new notify won't see the events above. */
363 notify
.smb2
.in
.file
.handle
= h2
;
364 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
366 /* (2nd notify) whereas this notify will see the above buffered events,
367 and it directly returns the buffered events */
368 notify
.smb2
.in
.file
.handle
= h1
;
369 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
371 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
372 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
374 /* (1st unlink) as the 2nd notify directly returns,
375 this unlink is only seen by the 1st notify and
376 the 3rd notify (later) */
377 torture_comment(torture
,
378 "Testing notify on unlink for the first file\n");
379 status
= smb2_util_unlink(tree2
, BASEDIR
"\\test0.txt");
380 CHECK_STATUS(status
, NT_STATUS_OK
);
382 /* receive the reply from the 2nd notify */
383 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
384 CHECK_STATUS(status
, NT_STATUS_OK
);
386 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
);
387 for (i
=1;i
<count
;i
++) {
388 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
389 NOTIFY_ACTION_ADDED
);
391 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
393 torture_comment(torture
, "and now from the 1st notify\n");
394 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
395 CHECK_STATUS(status
, NT_STATUS_OK
);
396 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
397 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
398 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
400 torture_comment(torture
,
401 "(3rd notify) this notify will only see the 1st unlink\n");
402 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
404 status
= smb2_util_unlink(tree1
, BASEDIR
"\\nonexistent.txt");
405 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
407 for (i
=1;i
<count
;i
++) {
408 char *fname2
= talloc_asprintf(torture
,
409 BASEDIR
"\\test%d.txt", i
);
410 status
= smb2_util_unlink(tree2
, fname2
);
411 CHECK_STATUS(status
, NT_STATUS_OK
);
415 /* receive the 3rd notify */
416 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
417 CHECK_STATUS(status
, NT_STATUS_OK
);
418 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
419 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
420 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "test0.txt");
422 /* and we now see the rest of the unlink calls on both
423 * directory handles */
424 notify
.smb2
.in
.file
.handle
= h1
;
426 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
427 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
428 CHECK_STATUS(status
, NT_STATUS_OK
);
429 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
430 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
431 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
432 NOTIFY_ACTION_REMOVED
);
434 notify
.smb2
.in
.file
.handle
= h2
;
435 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
436 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
437 CHECK_STATUS(status
, NT_STATUS_OK
);
438 CHECK_VAL(notify
.smb2
.out
.num_changes
, count
-1);
439 for (i
=0;i
<notify
.smb2
.out
.num_changes
;i
++) {
440 CHECK_VAL(notify
.smb2
.out
.changes
[i
].action
,
441 NOTIFY_ACTION_REMOVED
);
444 torture_comment(torture
,
445 "Testing if a close() on the dir handle triggers the notify reply\n");
447 notify
.smb2
.in
.file
.handle
= h1
;
448 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
450 ZERO_STRUCT(cl
.smb2
);
451 cl
.smb2
.level
= RAW_CLOSE_SMB2
;
452 cl
.smb2
.in
.file
.handle
= h1
;
453 status
= smb2_close(tree1
, &(cl
.smb2
));
454 CHECK_STATUS(status
, NT_STATUS_OK
);
456 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
457 CHECK_STATUS(status
, STATUS_NOTIFY_CLEANUP
);
458 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
461 smb2_util_close(tree1
, h1
);
462 smb2_util_close(tree1
, h2
);
463 smb2_deltree(tree1
, BASEDIR
);
467 static struct smb2_handle
custom_smb2_create(struct smb2_tree
*tree
,
468 struct torture_context
*torture
,
469 struct smb2_create
*smb2
)
471 struct smb2_handle h1
;
474 smb2_deltree(tree
, smb2
->in
.fname
);
475 status
= smb2_create(tree
, torture
, smb2
);
476 CHECK_STATUS(status
, NT_STATUS_OK
);
477 h1
= smb2
->out
.file
.handle
;
483 testing of recursive change notify
486 static bool torture_smb2_notify_recursive(struct torture_context
*torture
,
487 struct smb2_tree
*tree1
,
488 struct smb2_tree
*tree2
)
492 union smb_notify notify
;
493 union smb_open io
, io1
;
494 union smb_setfileinfo sinfo
;
495 struct smb2_handle h1
;
496 struct smb2_request
*req1
, *req2
;
498 smb2_deltree(tree1
, BASEDIR
);
499 smb2_util_rmdir(tree1
, BASEDIR
);
501 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH RECURSION\n");
504 get a handle on the directory
506 ZERO_STRUCT(io
.smb2
);
507 io
.generic
.level
= RAW_OPEN_SMB2
;
508 io
.smb2
.in
.create_flags
= 0;
509 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
510 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
511 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
512 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
513 NTCREATEX_SHARE_ACCESS_WRITE
;
514 io
.smb2
.in
.alloc_size
= 0;
515 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
516 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
517 io
.smb2
.in
.security_flags
= 0;
518 io
.smb2
.in
.fname
= BASEDIR
;
520 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
521 CHECK_STATUS(status
, NT_STATUS_OK
);
522 h1
= io
.smb2
.out
.file
.handle
;
524 /* ask for a change notify, on file or directory name
525 changes. Setup both with and without recursion */
526 ZERO_STRUCT(notify
.smb2
);
527 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
528 notify
.smb2
.in
.buffer_size
= 1000;
529 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
530 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
531 FILE_NOTIFY_CHANGE_CREATION
;
532 notify
.smb2
.in
.file
.handle
= h1
;
534 notify
.smb2
.in
.recursive
= true;
535 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
537 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
538 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
540 notify
.smb2
.in
.recursive
= false;
541 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
543 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
544 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
546 ZERO_STRUCT(io1
.smb2
);
547 io1
.generic
.level
= RAW_OPEN_SMB2
;
548 io1
.smb2
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
549 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
550 SEC_RIGHTS_FILE_WRITE
|
552 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
553 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
554 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
555 NTCREATEX_SHARE_ACCESS_WRITE
|
556 NTCREATEX_SHARE_ACCESS_DELETE
;
557 io1
.smb2
.in
.alloc_size
= 0;
558 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
559 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
560 io1
.smb2
.in
.security_flags
= 0;
561 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
562 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
563 CHECK_STATUS(status
, NT_STATUS_OK
);
564 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
566 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
567 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
568 CHECK_STATUS(status
, NT_STATUS_OK
);
570 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
571 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
572 sinfo
.rename_information
.in
.overwrite
= 0;
573 sinfo
.rename_information
.in
.root_fid
= 0;
574 sinfo
.rename_information
.in
.new_name
=
575 BASEDIR
"\\subdir-name\\subname1-r";
576 status
= smb2_setinfo_file(tree2
, &sinfo
);
577 CHECK_STATUS(status
, NT_STATUS_OK
);
579 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
580 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
581 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
582 CHECK_STATUS(status
, NT_STATUS_OK
);
584 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
585 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
586 sinfo
.rename_information
.in
.overwrite
= true;
587 sinfo
.rename_information
.in
.root_fid
= 0;
588 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
589 status
= smb2_setinfo_file(tree2
, &sinfo
);
590 CHECK_STATUS(status
, NT_STATUS_OK
);
592 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
593 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
594 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
595 CHECK_STATUS(status
, NT_STATUS_OK
);
597 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
598 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
599 sinfo
.rename_information
.in
.overwrite
= true;
600 sinfo
.rename_information
.in
.root_fid
= 0;
601 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
602 status
= smb2_setinfo_file(tree2
, &sinfo
);
603 CHECK_STATUS(status
, NT_STATUS_OK
);
605 notify
.smb2
.in
.completion_filter
= 0;
606 notify
.smb2
.in
.recursive
= true;
608 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
610 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
611 CHECK_STATUS(status
, NT_STATUS_OK
);
612 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
613 CHECK_STATUS(status
, NT_STATUS_OK
);
614 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
615 CHECK_STATUS(status
, NT_STATUS_OK
);
617 notify
.smb2
.in
.recursive
= false;
618 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
620 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
621 CHECK_STATUS(status
, NT_STATUS_OK
);
623 CHECK_VAL(notify
.smb2
.out
.num_changes
, 9);
624 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
625 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
626 CHECK_VAL(notify
.smb2
.out
.changes
[1].action
, NOTIFY_ACTION_ADDED
);
627 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[1].name
, "subdir-name\\subname1");
628 CHECK_VAL(notify
.smb2
.out
.changes
[2].action
, NOTIFY_ACTION_OLD_NAME
);
629 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[2].name
, "subdir-name\\subname1");
630 CHECK_VAL(notify
.smb2
.out
.changes
[3].action
, NOTIFY_ACTION_NEW_NAME
);
631 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[3].name
, "subdir-name\\subname1-r");
632 CHECK_VAL(notify
.smb2
.out
.changes
[4].action
, NOTIFY_ACTION_ADDED
);
633 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[4].name
, "subdir-name\\subname2");
634 CHECK_VAL(notify
.smb2
.out
.changes
[5].action
, NOTIFY_ACTION_REMOVED
);
635 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[5].name
, "subdir-name\\subname2");
636 CHECK_VAL(notify
.smb2
.out
.changes
[6].action
, NOTIFY_ACTION_ADDED
);
637 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[6].name
, "subname2-r");
638 CHECK_VAL(notify
.smb2
.out
.changes
[7].action
, NOTIFY_ACTION_OLD_NAME
);
639 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[7].name
, "subname2-r");
640 CHECK_VAL(notify
.smb2
.out
.changes
[8].action
, NOTIFY_ACTION_NEW_NAME
);
641 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[8].name
, "subname3-r");
644 smb2_deltree(tree1
, BASEDIR
);
649 testing of change notify mask change
652 static bool torture_smb2_notify_mask_change(struct torture_context
*torture
,
653 struct smb2_tree
*tree1
,
654 struct smb2_tree
*tree2
)
658 union smb_notify notify
;
659 union smb_open io
, io1
;
660 struct smb2_handle h1
;
661 struct smb2_request
*req1
, *req2
;
662 union smb_setfileinfo sinfo
;
664 smb2_deltree(tree1
, BASEDIR
);
665 smb2_util_rmdir(tree1
, BASEDIR
);
667 torture_comment(torture
, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
670 get a handle on the directory
672 ZERO_STRUCT(io
.smb2
);
673 io
.generic
.level
= RAW_OPEN_SMB2
;
674 io
.smb2
.in
.create_flags
= 0;
675 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
676 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
677 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
678 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
679 NTCREATEX_SHARE_ACCESS_WRITE
;
680 io
.smb2
.in
.alloc_size
= 0;
681 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
682 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
683 io
.smb2
.in
.security_flags
= 0;
684 io
.smb2
.in
.fname
= BASEDIR
;
686 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
687 CHECK_STATUS(status
, NT_STATUS_OK
);
688 h1
= io
.smb2
.out
.file
.handle
;
690 /* ask for a change notify, on file or directory name
691 changes. Setup both with and without recursion */
692 ZERO_STRUCT(notify
.smb2
);
693 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
694 notify
.smb2
.in
.buffer_size
= 1000;
695 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
696 notify
.smb2
.in
.file
.handle
= h1
;
698 notify
.smb2
.in
.recursive
= true;
699 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
702 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
703 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
706 notify
.smb2
.in
.recursive
= false;
707 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
710 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
711 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
713 notify
.smb2
.in
.recursive
= true;
714 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
716 /* Set to hidden then back again. */
717 ZERO_STRUCT(io1
.smb2
);
718 io1
.generic
.level
= RAW_OPEN_SMB2
;
719 io1
.smb2
.in
.create_flags
= 0;
720 io1
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
721 SEC_RIGHTS_FILE_WRITE
|
723 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
724 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
725 NTCREATEX_SHARE_ACCESS_WRITE
|
726 NTCREATEX_SHARE_ACCESS_DELETE
;
727 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
728 io1
.smb2
.in
.security_flags
= 0;
729 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
730 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
731 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
733 smb2_util_close(tree1
,
734 custom_smb2_create(tree1
, torture
, &(io1
.smb2
)));
735 status
= smb2_util_setatr(tree1
, BASEDIR
"\\tname1",
736 FILE_ATTRIBUTE_HIDDEN
);
737 CHECK_STATUS(status
, NT_STATUS_OK
);
738 smb2_util_unlink(tree1
, BASEDIR
"\\tname1");
740 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
741 CHECK_STATUS(status
, NT_STATUS_OK
);
743 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
744 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
745 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
747 /* Now try and change the mask to include other events.
748 * This should not work - once the mask is set on a directory
749 * h1 it seems to be fixed until the fnum is closed. */
751 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
|
752 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
753 FILE_NOTIFY_CHANGE_CREATION
;
754 notify
.smb2
.in
.recursive
= true;
755 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
757 notify
.smb2
.in
.recursive
= false;
758 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
760 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
761 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
762 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name";
763 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
764 CHECK_STATUS(status
, NT_STATUS_OK
);
765 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
768 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname1";
769 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
770 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
771 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
772 CHECK_STATUS(status
, NT_STATUS_OK
);
773 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
774 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
775 sinfo
.rename_information
.in
.overwrite
= true;
776 sinfo
.rename_information
.in
.root_fid
= 0;
777 sinfo
.rename_information
.in
.new_name
=
778 BASEDIR
"\\subdir-name\\subname1-r";
779 status
= smb2_setinfo_file(tree2
, &sinfo
);
780 CHECK_STATUS(status
, NT_STATUS_OK
);
782 io1
.smb2
.in
.fname
= BASEDIR
"\\subdir-name\\subname2";
783 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
784 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
785 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
786 CHECK_STATUS(status
, NT_STATUS_OK
);
787 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
788 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname2-r";
789 status
= smb2_setinfo_file(tree2
, &sinfo
);
790 CHECK_STATUS(status
, NT_STATUS_OK
);
791 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
793 io1
.smb2
.in
.fname
= BASEDIR
"\\subname2-r";
794 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
795 status
= smb2_create(tree2
, torture
, &(io1
.smb2
));
796 CHECK_STATUS(status
, NT_STATUS_OK
);
797 sinfo
.rename_information
.in
.file
.handle
= io1
.smb2
.out
.file
.handle
;
798 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\subname3-r";
799 status
= smb2_setinfo_file(tree2
, &sinfo
);
800 CHECK_STATUS(status
, NT_STATUS_OK
);
801 smb2_util_close(tree2
, io1
.smb2
.out
.file
.handle
);
803 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name\\subname1-r");
804 CHECK_STATUS(status
, NT_STATUS_OK
);
805 status
= smb2_util_rmdir(tree2
, BASEDIR
"\\subdir-name");
806 CHECK_STATUS(status
, NT_STATUS_OK
);
807 status
= smb2_util_unlink(tree2
, BASEDIR
"\\subname3-r");
808 CHECK_STATUS(status
, NT_STATUS_OK
);
810 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
811 CHECK_STATUS(status
, NT_STATUS_OK
);
813 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
814 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
815 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subname2-r");
817 status
= smb2_notify_recv(req2
, 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
, "subname3-r");
829 smb2_deltree(tree1
, BASEDIR
);
834 testing of mask bits for change notify
837 static bool torture_smb2_notify_mask(struct torture_context
*torture
,
838 struct smb2_tree
*tree1
,
839 struct smb2_tree
*tree2
)
843 union smb_notify notify
;
844 union smb_open io
, io1
;
845 struct smb2_handle h1
, h2
;
849 union smb_setfileinfo sinfo
;
851 smb2_deltree(tree1
, BASEDIR
);
852 smb2_util_rmdir(tree1
, BASEDIR
);
854 torture_comment(torture
, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
858 get a handle on the directory
860 ZERO_STRUCT(io
.smb2
);
861 io
.generic
.level
= RAW_OPEN_SMB2
;
862 io
.smb2
.in
.create_flags
= 0;
863 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
864 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
865 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
866 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
867 NTCREATEX_SHARE_ACCESS_WRITE
;
868 io
.smb2
.in
.alloc_size
= 0;
869 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
870 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
871 io
.smb2
.in
.security_flags
= 0;
872 io
.smb2
.in
.fname
= BASEDIR
;
874 ZERO_STRUCT(notify
.smb2
);
875 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
876 notify
.smb2
.in
.buffer_size
= 1000;
877 notify
.smb2
.in
.recursive
= true;
879 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \
880 expected, nchanges) \
882 do { for (mask=i=0;i<32;i++) { \
883 struct smb2_request *req; \
884 status = smb2_create(tree1, torture, &(io.smb2)); \
885 CHECK_STATUS(status, NT_STATUS_OK); \
886 h1 = io.smb2.out.file.handle; \
888 notify.smb2.in.file.handle = h1; \
889 notify.smb2.in.completion_filter = (1<<i); \
890 /* cancel initial requests so the buffer is setup */ \
891 req = smb2_notify_send(tree1, &(notify.smb2)); \
893 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
894 CHECK_STATUS(status, NT_STATUS_CANCELLED); \
895 /* send the change notify request */ \
896 req = smb2_notify_send(tree1, &(notify.smb2)); \
898 smb_msleep(200); smb2_cancel(req); \
899 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
901 smb2_util_close(tree1, h1); \
902 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
903 CHECK_STATUS(status, NT_STATUS_OK); \
904 /* special case to cope with file rename behaviour */ \
905 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \
906 notify.smb2.out.changes[0].action == \
907 NOTIFY_ACTION_MODIFIED && \
908 ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
909 Action == NOTIFY_ACTION_OLD_NAME) { \
910 torture_comment(torture, \
911 "(rename file special handling OK)\n"); \
912 } else if (nchanges != notify.smb2.out.num_changes) { \
913 torture_result(torture, TORTURE_FAIL, \
914 "ERROR: nchanges=%d expected=%d "\
915 "action=%d filter=0x%08x\n", \
916 notify.smb2.out.num_changes, \
918 notify.smb2.out.changes[0].action, \
919 notify.smb2.in.completion_filter); \
921 } else if (notify.smb2.out.changes[0].action != Action) { \
922 torture_result(torture, TORTURE_FAIL, \
923 "ERROR: nchanges=%d action=%d " \
924 "expectedAction=%d filter=0x%08x\n", \
925 notify.smb2.out.num_changes, \
926 notify.smb2.out.changes[0].action, \
928 notify.smb2.in.completion_filter); \
930 } else if (strcmp(notify.smb2.out.changes[0].name.s, \
932 torture_result(torture, TORTURE_FAIL, \
933 "ERROR: nchanges=%d action=%d " \
934 "filter=0x%08x name=%s\n", \
935 notify.smb2.out.num_changes, \
936 notify.smb2.out.changes[0].action, \
937 notify.smb2.in.completion_filter, \
938 notify.smb2.out.changes[0].name.s); \
946 torture_comment(torture
, "Testing mkdir\n");
947 NOTIFY_MASK_TEST("Testing mkdir",;,
948 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
949 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
951 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
953 torture_comment(torture
, "Testing create file\n");
954 ZERO_STRUCT(io1
.smb2
);
955 io1
.generic
.level
= RAW_OPEN_SMB2
;
956 io1
.smb2
.in
.create_flags
= 0;
957 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
958 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
959 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
960 NTCREATEX_SHARE_ACCESS_WRITE
;
961 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
962 io1
.smb2
.in
.security_flags
= 0;
963 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
964 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
965 io1
.smb2
.in
.fname
= BASEDIR
"\\tname1";
967 NOTIFY_MASK_TEST("Testing create file",;,
968 smb2_util_close(tree2
, custom_smb2_create(tree2
,
969 torture
, &(io1
.smb2
)));,
970 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
972 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
974 torture_comment(torture
, "Testing unlink\n");
975 NOTIFY_MASK_TEST("Testing unlink",
976 smb2_util_close(tree2
, custom_smb2_create(tree2
,
977 torture
, &(io1
.smb2
)));,
978 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
980 NOTIFY_ACTION_REMOVED
,
981 FILE_NOTIFY_CHANGE_FILE_NAME
, 1);
983 torture_comment(torture
, "Testing rmdir\n");
984 NOTIFY_MASK_TEST("Testing rmdir",
985 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
986 smb2_util_rmdir(tree2
, BASEDIR
"\\tname1");,
988 NOTIFY_ACTION_REMOVED
,
989 FILE_NOTIFY_CHANGE_DIR_NAME
, 1);
991 torture_comment(torture
, "Testing rename file\n");
993 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
994 sinfo
.rename_information
.in
.file
.handle
= h1
;
995 sinfo
.rename_information
.in
.overwrite
= true;
996 sinfo
.rename_information
.in
.root_fid
= 0;
997 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
998 NOTIFY_MASK_TEST("Testing rename file",
999 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1000 torture
, &(io1
.smb2
)));,
1001 smb2_setinfo_file(tree2
, &sinfo
);,
1002 smb2_util_unlink(tree2
, BASEDIR
"\\tname2");,
1003 NOTIFY_ACTION_OLD_NAME
,
1004 FILE_NOTIFY_CHANGE_FILE_NAME
, 2);
1006 torture_comment(torture
, "Testing rename dir\n");
1008 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1009 sinfo
.rename_information
.in
.file
.handle
= h1
;
1010 sinfo
.rename_information
.in
.overwrite
= true;
1011 sinfo
.rename_information
.in
.root_fid
= 0;
1012 sinfo
.rename_information
.in
.new_name
= BASEDIR
"\\tname2";
1013 NOTIFY_MASK_TEST("Testing rename dir",
1014 smb2_util_mkdir(tree2
, BASEDIR
"\\tname1");,
1015 smb2_setinfo_file(tree2
, &sinfo
);,
1016 smb2_util_rmdir(tree2
, BASEDIR
"\\tname2");,
1017 NOTIFY_ACTION_OLD_NAME
,
1018 FILE_NOTIFY_CHANGE_DIR_NAME
, 2);
1020 torture_comment(torture
, "Testing set path attribute\n");
1021 NOTIFY_MASK_TEST("Testing set path attribute",
1022 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1023 torture
, &(io
.smb2
)));,
1024 smb2_util_setatr(tree2
, BASEDIR
"\\tname1",
1025 FILE_ATTRIBUTE_HIDDEN
);,
1026 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1027 NOTIFY_ACTION_MODIFIED
,
1028 FILE_NOTIFY_CHANGE_ATTRIBUTES
, 1);
1030 torture_comment(torture
, "Testing set path write time\n");
1032 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1033 sinfo
.generic
.in
.file
.handle
= h1
;
1034 sinfo
.basic_info
.in
.write_time
= 1000;
1035 NOTIFY_MASK_TEST("Testing set path write time",
1036 smb2_util_close(tree2
, custom_smb2_create(tree2
,
1037 torture
, &(io1
.smb2
)));,
1038 smb2_setinfo_file(tree2
, &sinfo
);,
1039 smb2_util_unlink(tree2
, BASEDIR
"\\tname1");,
1040 NOTIFY_ACTION_MODIFIED
,
1041 FILE_NOTIFY_CHANGE_LAST_WRITE
, 1);
1043 if (torture_setting_bool(torture
, "samba3", false)) {
1044 torture_comment(torture
,
1045 "Samba3 does not yet support create times "
1050 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1051 sinfo
.generic
.in
.file
.handle
= h1
;
1052 sinfo
.basic_info
.in
.create_time
= 0;
1053 torture_comment(torture
, "Testing set file create time\n");
1054 NOTIFY_MASK_TEST("Testing set file create time",
1055 smb2_create_complex_file(tree2
,
1056 BASEDIR
"\\tname1", &h2
);,
1057 smb2_setinfo_file(tree2
, &sinfo
);,
1058 (smb2_util_close(tree2
, h2
),
1059 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1060 NOTIFY_ACTION_MODIFIED
,
1061 FILE_NOTIFY_CHANGE_CREATION
, 1);
1065 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1066 sinfo
.generic
.in
.file
.handle
= h1
;
1067 sinfo
.basic_info
.in
.access_time
= 0;
1068 torture_comment(torture
, "Testing set file access time\n");
1069 NOTIFY_MASK_TEST("Testing set file access time",
1070 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1071 smb2_setinfo_file(tree2
, &sinfo
);,
1072 (smb2_util_close(tree2
, h2
),
1073 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1074 NOTIFY_ACTION_MODIFIED
,
1075 FILE_NOTIFY_CHANGE_LAST_ACCESS
, 1);
1078 sinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1079 sinfo
.generic
.in
.file
.handle
= h1
;
1080 sinfo
.basic_info
.in
.change_time
= 0;
1081 torture_comment(torture
, "Testing set file change time\n");
1082 NOTIFY_MASK_TEST("Testing set file change time",
1083 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1084 smb2_setinfo_file(tree2
, &sinfo
);,
1085 (smb2_util_close(tree2
, h2
),
1086 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1087 NOTIFY_ACTION_MODIFIED
,
1091 torture_comment(torture
, "Testing write\n");
1092 NOTIFY_MASK_TEST("Testing write",
1093 smb2_create_complex_file(tree2
, BASEDIR
"\\tname1", &h2
);,
1094 smb2_util_write(tree2
, h2
, &c
, 10000, 1);,
1095 (smb2_util_close(tree2
, h2
),
1096 smb2_util_unlink(tree2
, BASEDIR
"\\tname1"));,
1097 NOTIFY_ACTION_MODIFIED
,
1101 smb2_deltree(tree1
, BASEDIR
);
1106 basic testing of change notify on files
1108 static bool torture_smb2_notify_file(struct torture_context
*torture
,
1109 struct smb2_tree
*tree
)
1115 union smb_notify notify
;
1116 struct smb2_request
*req
;
1117 struct smb2_handle h1
;
1118 const char *fname
= BASEDIR
"\\file.txt";
1120 smb2_deltree(tree
, BASEDIR
);
1121 smb2_util_rmdir(tree
, BASEDIR
);
1123 torture_comment(torture
, "TESTING CHANGE NOTIFY ON FILES\n");
1124 status
= torture_smb2_testdir(tree
, BASEDIR
, &h1
);
1125 CHECK_STATUS(status
, NT_STATUS_OK
);
1127 ZERO_STRUCT(io
.smb2
);
1128 io
.generic
.level
= RAW_OPEN_SMB2
;
1129 io
.smb2
.in
.create_flags
= 0;
1130 io
.smb2
.in
.desired_access
= SEC_FLAG_MAXIMUM_ALLOWED
;
1131 io
.smb2
.in
.create_options
= 0;
1132 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1133 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1134 NTCREATEX_SHARE_ACCESS_WRITE
;
1135 io
.smb2
.in
.alloc_size
= 0;
1136 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1137 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1138 io
.smb2
.in
.security_flags
= 0;
1139 io
.smb2
.in
.fname
= fname
;
1140 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1141 CHECK_STATUS(status
, NT_STATUS_OK
);
1142 h1
= io
.smb2
.out
.file
.handle
;
1144 /* ask for a change notify,
1145 on file or directory name changes */
1146 ZERO_STRUCT(notify
.smb2
);
1147 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1148 notify
.smb2
.in
.file
.handle
= h1
;
1149 notify
.smb2
.in
.buffer_size
= 1000;
1150 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_STREAM_NAME
;
1151 notify
.smb2
.in
.recursive
= false;
1153 torture_comment(torture
,
1154 "Testing if notifies on file handles are invalid (should be)\n");
1156 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1157 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1158 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1160 ZERO_STRUCT(cl
.smb2
);
1161 cl
.close
.level
= RAW_CLOSE_SMB2
;
1162 cl
.close
.in
.file
.handle
= h1
;
1163 status
= smb2_close(tree
, &(cl
.smb2
));
1164 CHECK_STATUS(status
, NT_STATUS_OK
);
1166 status
= smb2_util_unlink(tree
, fname
);
1167 CHECK_STATUS(status
, NT_STATUS_OK
);
1170 smb2_deltree(tree
, BASEDIR
);
1174 basic testing of change notifies followed by a tdis
1177 static bool torture_smb2_notify_tree_disconnect(
1178 struct torture_context
*torture
,
1179 struct smb2_tree
*tree
)
1183 union smb_notify notify
;
1185 struct smb2_handle h1
;
1186 struct smb2_request
*req
;
1188 smb2_deltree(tree
, BASEDIR
);
1189 smb2_util_rmdir(tree
, BASEDIR
);
1191 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY "
1192 "TREE-DISCONNECT\n");
1195 get a handle on the directory
1197 ZERO_STRUCT(io
.smb2
);
1198 io
.generic
.level
= RAW_OPEN_SMB2
;
1199 io
.smb2
.in
.create_flags
= 0;
1200 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1201 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1202 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1203 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1204 NTCREATEX_SHARE_ACCESS_WRITE
;
1205 io
.smb2
.in
.alloc_size
= 0;
1206 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1207 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1208 io
.smb2
.in
.security_flags
= 0;
1209 io
.smb2
.in
.fname
= BASEDIR
;
1211 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1212 CHECK_STATUS(status
, NT_STATUS_OK
);
1213 h1
= io
.smb2
.out
.file
.handle
;
1215 /* ask for a change notify,
1216 on file or directory name changes */
1217 ZERO_STRUCT(notify
.smb2
);
1218 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1219 notify
.smb2
.in
.buffer_size
= 1000;
1220 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1221 notify
.smb2
.in
.file
.handle
= h1
;
1222 notify
.smb2
.in
.recursive
= true;
1224 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1226 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1228 status
= smb2_tdis(tree
);
1229 CHECK_STATUS(status
, NT_STATUS_OK
);
1231 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1233 smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1234 CHECK_STATUS(status
, NT_STATUS_OK
);
1235 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1238 smb2_deltree(tree
, BASEDIR
);
1243 basic testing of change notifies followed by a ulogoff
1246 static bool torture_smb2_notify_ulogoff(struct torture_context
*torture
,
1247 struct smb2_tree
*tree1
,
1248 struct smb2_tree
*tree2
)
1252 union smb_notify notify
;
1254 struct smb2_handle h1
;
1255 struct smb2_request
*req
;
1257 smb2_deltree(tree1
, BASEDIR
);
1258 smb2_util_rmdir(tree1
, BASEDIR
);
1260 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1263 get a handle on the directory
1265 ZERO_STRUCT(io
.smb2
);
1266 io
.generic
.level
= RAW_OPEN_SMB2
;
1267 io
.smb2
.in
.create_flags
= 0;
1268 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1269 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1270 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1271 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1272 NTCREATEX_SHARE_ACCESS_WRITE
;
1273 io
.smb2
.in
.alloc_size
= 0;
1274 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1275 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1276 io
.smb2
.in
.security_flags
= 0;
1277 io
.smb2
.in
.fname
= BASEDIR
;
1279 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1280 CHECK_STATUS(status
, NT_STATUS_OK
);
1282 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1283 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1284 CHECK_STATUS(status
, NT_STATUS_OK
);
1285 h1
= io
.smb2
.out
.file
.handle
;
1287 /* ask for a change notify,
1288 on file or directory name changes */
1289 ZERO_STRUCT(notify
.smb2
);
1290 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1291 notify
.smb2
.in
.buffer_size
= 1000;
1292 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1293 notify
.smb2
.in
.file
.handle
= h1
;
1294 notify
.smb2
.in
.recursive
= true;
1296 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1298 status
= smb2_logoff(tree2
->session
);
1299 CHECK_STATUS(status
, NT_STATUS_OK
);
1301 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1302 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1305 smb2_deltree(tree1
, BASEDIR
);
1309 static void tcp_dis_handler(struct smb2_transport
*t
, void *p
)
1311 struct smb2_tree
*tree
= (struct smb2_tree
*)p
;
1312 smb2_transport_dead(tree
->session
->transport
,
1313 NT_STATUS_LOCAL_DISCONNECT
);
1319 basic testing of change notifies followed by tcp disconnect
1322 static bool torture_smb2_notify_tcp_disconnect(
1323 struct torture_context
*torture
,
1324 struct smb2_tree
*tree
)
1328 union smb_notify notify
;
1330 struct smb2_handle h1
;
1331 struct smb2_request
*req
;
1333 smb2_deltree(tree
, BASEDIR
);
1334 smb2_util_rmdir(tree
, BASEDIR
);
1336 torture_comment(torture
,
1337 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1340 get a handle on the directory
1342 ZERO_STRUCT(io
.smb2
);
1343 io
.generic
.level
= RAW_OPEN_SMB2
;
1344 io
.smb2
.in
.create_flags
= 0;
1345 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1346 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1347 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1348 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1349 NTCREATEX_SHARE_ACCESS_WRITE
;
1350 io
.smb2
.in
.alloc_size
= 0;
1351 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1352 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1353 io
.smb2
.in
.security_flags
= 0;
1354 io
.smb2
.in
.fname
= BASEDIR
;
1356 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1357 CHECK_STATUS(status
, NT_STATUS_OK
);
1358 h1
= io
.smb2
.out
.file
.handle
;
1360 /* ask for a change notify,
1361 on file or directory name changes */
1362 ZERO_STRUCT(notify
.smb2
);
1363 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1364 notify
.smb2
.in
.buffer_size
= 1000;
1365 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1366 notify
.smb2
.in
.file
.handle
= h1
;
1367 notify
.smb2
.in
.recursive
= true;
1369 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1371 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1372 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1374 notify
.smb2
.in
.recursive
= true;
1375 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1376 smb2_transport_idle_handler(tree
->session
->transport
,
1377 tcp_dis_handler
, 250, tree
);
1379 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1380 CHECK_STATUS(status
, NT_STATUS_LOCAL_DISCONNECT
);
1387 test setting up two change notify requests on one handle
1390 static bool torture_smb2_notify_double(struct torture_context
*torture
,
1391 struct smb2_tree
*tree1
,
1392 struct smb2_tree
*tree2
)
1396 union smb_notify notify
;
1398 struct smb2_handle h1
;
1399 struct smb2_request
*req1
, *req2
;
1401 smb2_deltree(tree1
, BASEDIR
);
1402 smb2_util_rmdir(tree1
, BASEDIR
);
1404 torture_comment(torture
,
1405 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1408 get a handle on the directory
1410 ZERO_STRUCT(io
.smb2
);
1411 io
.generic
.level
= RAW_OPEN_SMB2
;
1412 io
.smb2
.in
.create_flags
= 0;
1413 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
1414 SEC_RIGHTS_FILE_WRITE
|
1415 SEC_RIGHTS_FILE_ALL
;
1416 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1417 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1418 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1419 NTCREATEX_SHARE_ACCESS_WRITE
;
1420 io
.smb2
.in
.alloc_size
= 0;
1421 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1422 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1423 io
.smb2
.in
.security_flags
= 0;
1424 io
.smb2
.in
.fname
= BASEDIR
;
1426 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1427 CHECK_STATUS(status
, NT_STATUS_OK
);
1428 h1
= io
.smb2
.out
.file
.handle
;
1430 /* ask for a change notify,
1431 on file or directory name changes */
1432 ZERO_STRUCT(notify
.smb2
);
1433 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1434 notify
.smb2
.in
.buffer_size
= 1000;
1435 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1436 notify
.smb2
.in
.file
.handle
= h1
;
1437 notify
.smb2
.in
.recursive
= true;
1439 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1441 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1442 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1444 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1446 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1447 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1449 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name");
1450 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1451 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1453 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1454 CHECK_STATUS(status
, NT_STATUS_OK
);
1455 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1456 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1458 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name2");
1460 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1461 CHECK_STATUS(status
, NT_STATUS_OK
);
1462 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1463 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name2");
1466 smb2_deltree(tree1
, BASEDIR
);
1472 test multiple change notifies at different depths and with/without recursion
1475 static bool torture_smb2_notify_tree(struct torture_context
*torture
,
1476 struct smb2_tree
*tree
)
1479 union smb_notify notify
;
1481 struct smb2_request
*req
;
1488 struct smb2_handle h1
;
1491 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 30 },
1492 {BASEDIR
"\\zqy", true, FILE_NOTIFY_CHANGE_NAME
, 8 },
1493 {BASEDIR
"\\atsy", true, FILE_NOTIFY_CHANGE_NAME
, 4 },
1494 {BASEDIR
"\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1495 {BASEDIR
"\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME
, 13 },
1496 {BASEDIR
"\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME
, 7 },
1497 {BASEDIR
"\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1498 {BASEDIR
"\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1499 {BASEDIR
"\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1500 {BASEDIR
"\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1501 {BASEDIR
"\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1502 {BASEDIR
"\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1503 {BASEDIR
"\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1504 {BASEDIR
, true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1505 {BASEDIR
, false,FILE_NOTIFY_CHANGE_NAME
, 6 },
1506 {BASEDIR
"\\atsy", false,FILE_NOTIFY_CHANGE_NAME
, 4 },
1507 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1508 {BASEDIR
"\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1509 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1510 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1514 bool all_done
= false;
1516 smb2_deltree(tree
, BASEDIR
);
1517 smb2_util_rmdir(tree
, BASEDIR
);
1519 torture_comment(torture
, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1521 ZERO_STRUCT(io
.smb2
);
1522 io
.generic
.level
= RAW_OPEN_SMB2
;
1523 io
.smb2
.in
.create_flags
= 0;
1524 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1525 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1526 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1527 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1528 NTCREATEX_SHARE_ACCESS_WRITE
;
1529 io
.smb2
.in
.alloc_size
= 0;
1530 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1531 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1532 io
.smb2
.in
.security_flags
= 0;
1533 io
.smb2
.in
.fname
= BASEDIR
;
1534 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1535 CHECK_STATUS(status
, NT_STATUS_OK
);
1537 ZERO_STRUCT(notify
.smb2
);
1538 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1539 notify
.smb2
.in
.buffer_size
= 20000;
1542 setup the directory tree, and the notify buffer on each directory
1544 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1545 io
.smb2
.in
.fname
= dirs
[i
].path
;
1546 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1547 CHECK_STATUS(status
, NT_STATUS_OK
);
1548 dirs
[i
].h1
= io
.smb2
.out
.file
.handle
;
1550 notify
.smb2
.in
.completion_filter
= dirs
[i
].filter
;
1551 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1552 notify
.smb2
.in
.recursive
= dirs
[i
].recursive
;
1553 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1555 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1556 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1559 /* trigger 2 events in each dir */
1560 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1561 char *path
= talloc_asprintf(torture
, "%s\\test.dir",
1563 smb2_util_mkdir(tree
, path
);
1564 smb2_util_rmdir(tree
, path
);
1568 /* give a bit of time for the events to propogate */
1569 tv
= timeval_current();
1572 /* count events that have happened in each dir */
1573 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1574 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1575 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1577 notify
.smb2
.out
.num_changes
= 0;
1578 status
= smb2_notify_recv(req
, torture
,
1580 dirs
[i
].counted
+= notify
.smb2
.out
.num_changes
;
1585 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1586 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1590 } while (!all_done
&& timeval_elapsed(&tv
) < 20);
1592 torture_comment(torture
, "took %.4f seconds to propogate all events\n",
1593 timeval_elapsed(&tv
));
1595 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1596 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1597 torture_comment(torture
,
1598 "ERROR: i=%d expected %d got %d for '%s'\n",
1599 i
, dirs
[i
].expected
, dirs
[i
].counted
,
1606 run from the back, closing and deleting
1608 for (i
=ARRAY_SIZE(dirs
)-1;i
>=0;i
--) {
1609 smb2_util_close(tree
, dirs
[i
].h1
);
1610 smb2_util_rmdir(tree
, dirs
[i
].path
);
1614 smb2_deltree(tree
, BASEDIR
);
1615 smb2_util_rmdir(tree
, BASEDIR
);
1620 Test response when cached server events exceed single NT NOTFIY response
1624 static bool torture_smb2_notify_overflow(struct torture_context
*torture
,
1625 struct smb2_tree
*tree
)
1629 union smb_notify notify
;
1631 struct smb2_handle h1
, h2
;
1633 struct smb2_request
*req1
;
1636 smb2_deltree(tree
, BASEDIR
);
1637 smb2_util_rmdir(tree
, BASEDIR
);
1639 torture_comment(torture
, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1641 /* get a handle on the directory */
1642 ZERO_STRUCT(io
.smb2
);
1643 io
.generic
.level
= RAW_OPEN_SMB2
;
1644 io
.smb2
.in
.create_flags
= 0;
1645 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1646 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1647 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1648 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1649 NTCREATEX_SHARE_ACCESS_WRITE
;
1650 io
.smb2
.in
.alloc_size
= 0;
1651 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1652 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1653 io
.smb2
.in
.security_flags
= 0;
1654 io
.smb2
.in
.fname
= BASEDIR
;
1656 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1657 CHECK_STATUS(status
, NT_STATUS_OK
);
1658 h1
= io
.smb2
.out
.file
.handle
;
1660 /* ask for a change notify, on name changes. */
1661 ZERO_STRUCT(notify
.smb2
);
1662 notify
.smb2
.level
= RAW_NOTIFY_NTTRANS
;
1663 notify
.smb2
.in
.buffer_size
= 1000;
1664 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1665 notify
.smb2
.in
.file
.handle
= h1
;
1667 notify
.smb2
.in
.recursive
= true;
1668 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1670 /* cancel initial requests so the buffer is setup */
1672 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1673 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1675 /* open a lot of files, filling up the server side notify buffer */
1676 torture_comment(torture
,
1677 "Testing overflowed buffer notify on create of %d files\n",
1680 for (i
=0;i
<count
;i
++) {
1681 char *fname
= talloc_asprintf(torture
,
1682 BASEDIR
"\\test%d.txt", i
);
1684 ZERO_STRUCT(io1
.smb2
);
1685 io1
.generic
.level
= RAW_OPEN_SMB2
;
1686 io1
.smb2
.in
.create_flags
= 0;
1687 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1688 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1689 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1690 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1691 NTCREATEX_SHARE_ACCESS_WRITE
;
1692 io1
.smb2
.in
.alloc_size
= 0;
1693 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1694 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1695 io1
.smb2
.in
.security_flags
= 0;
1696 io1
.smb2
.in
.fname
= fname
;
1698 h2
= custom_smb2_create(tree
, torture
, &(io1
.smb2
));
1700 smb2_util_close(tree
, h2
);
1703 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1704 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1705 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
1706 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1709 smb2_deltree(tree
, BASEDIR
);
1714 Test if notifications are returned for changes to the base directory.
1718 static bool torture_smb2_notify_basedir(struct torture_context
*torture
,
1719 struct smb2_tree
*tree1
,
1720 struct smb2_tree
*tree2
)
1724 union smb_notify notify
;
1726 struct smb2_handle h1
;
1727 struct smb2_request
*req1
;
1729 smb2_deltree(tree1
, BASEDIR
);
1730 smb2_util_rmdir(tree1
, BASEDIR
);
1732 torture_comment(torture
, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1734 /* get a handle on the directory */
1735 ZERO_STRUCT(io
.smb2
);
1736 io
.generic
.level
= RAW_OPEN_SMB2
;
1737 io
.smb2
.in
.create_flags
= 0;
1738 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1739 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1740 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1741 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1742 NTCREATEX_SHARE_ACCESS_WRITE
;
1743 io
.smb2
.in
.alloc_size
= 0;
1744 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1745 io
.smb2
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1746 io
.smb2
.in
.security_flags
= 0;
1747 io
.smb2
.in
.fname
= BASEDIR
;
1749 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1750 CHECK_STATUS(status
, NT_STATUS_OK
);
1751 h1
= io
.smb2
.out
.file
.handle
;
1753 /* create a test file that will also be modified */
1754 io
.smb2
.in
.fname
= BASEDIR
"\\tname1";
1755 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1756 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1757 CHECK_STATUS(status
,NT_STATUS_OK
);
1758 smb2_util_close(tree2
, io
.smb2
.out
.file
.handle
);
1760 /* ask for a change notify, on attribute changes. */
1761 ZERO_STRUCT(notify
.smb2
);
1762 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1763 notify
.smb2
.in
.buffer_size
= 1000;
1764 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
1765 notify
.smb2
.in
.file
.handle
= h1
;
1766 notify
.smb2
.in
.recursive
= true;
1768 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1770 /* set attribute on the base dir */
1771 smb2_util_setatr(tree2
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
);
1773 /* set attribute on a file to assure we receive a notification */
1774 smb2_util_setatr(tree2
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
);
1777 /* check how many responses were given, expect only 1 for the file */
1778 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1779 CHECK_STATUS(status
, NT_STATUS_OK
);
1780 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1781 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
1782 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
1785 smb2_deltree(tree1
, BASEDIR
);
1791 create a secondary tree connect - used to test for a bug in Samba3 messaging
1794 static struct smb2_tree
*secondary_tcon(struct smb2_tree
*tree
,
1795 struct torture_context
*tctx
)
1798 const char *share
, *host
;
1799 struct smb2_tree
*tree1
;
1800 union smb_tcon tcon
;
1802 share
= torture_setting_string(tctx
, "share", NULL
);
1803 host
= torture_setting_string(tctx
, "host", NULL
);
1805 torture_comment(tctx
,
1806 "create a second tree context on the same session\n");
1807 tree1
= smb2_tree_init(tree
->session
, tctx
, false);
1808 if (tree1
== NULL
) {
1809 torture_comment(tctx
, "Out of memory\n");
1813 ZERO_STRUCT(tcon
.smb2
);
1814 tcon
.generic
.level
= RAW_TCON_SMB2
;
1815 tcon
.smb2
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
1816 status
= smb2_tree_connect(tree
->session
, &(tcon
.smb2
));
1817 if (!NT_STATUS_IS_OK(status
)) {
1819 torture_comment(tctx
,"Failed to create secondary tree\n");
1823 smb2cli_tcon_set_values(tree1
->smbXcli
,
1824 tree1
->session
->smbXcli
,
1826 tcon
.smb2
.out
.share_type
,
1827 tcon
.smb2
.out
.flags
,
1828 tcon
.smb2
.out
.capabilities
,
1829 tcon
.smb2
.out
.access_mask
);
1831 torture_comment(tctx
,"tid1=%d tid2=%d\n",
1832 smb2cli_tcon_current_id(tree
->smbXcli
),
1833 smb2cli_tcon_current_id(tree1
->smbXcli
));
1840 very simple change notify test
1842 static bool torture_smb2_notify_tcon(struct torture_context
*torture
,
1843 struct smb2_tree
*tree
)
1847 union smb_notify notify
;
1849 struct smb2_handle h1
;
1850 struct smb2_request
*req
= NULL
;
1851 struct smb2_tree
*tree1
= NULL
;
1852 const char *fname
= BASEDIR
"\\subdir-name";
1854 smb2_deltree(tree
, BASEDIR
);
1855 smb2_util_rmdir(tree
, BASEDIR
);
1857 torture_comment(torture
, "TESTING SIMPLE CHANGE NOTIFY\n");
1860 get a handle on the directory
1863 ZERO_STRUCT(io
.smb2
);
1864 io
.generic
.level
= RAW_OPEN_SMB2
;
1865 io
.smb2
.in
.create_flags
= 0;
1866 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1867 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1868 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
|
1869 FILE_ATTRIBUTE_DIRECTORY
;
1870 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1871 NTCREATEX_SHARE_ACCESS_WRITE
;
1872 io
.smb2
.in
.alloc_size
= 0;
1873 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1874 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1875 io
.smb2
.in
.security_flags
= 0;
1876 io
.smb2
.in
.fname
= BASEDIR
;
1878 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1879 CHECK_STATUS(status
, NT_STATUS_OK
);
1880 h1
= io
.smb2
.out
.file
.handle
;
1882 /* ask for a change notify,
1883 on file or directory name changes */
1884 ZERO_STRUCT(notify
.smb2
);
1885 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1886 notify
.smb2
.in
.buffer_size
= 1000;
1887 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1888 notify
.smb2
.in
.file
.handle
= h1
;
1889 notify
.smb2
.in
.recursive
= true;
1891 torture_comment(torture
, "Testing notify mkdir\n");
1892 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1894 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1895 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1897 notify
.smb2
.in
.recursive
= true;
1898 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1899 status
= smb2_util_mkdir(tree
, fname
);
1900 CHECK_STATUS(status
, NT_STATUS_OK
);
1902 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1903 CHECK_STATUS(status
, NT_STATUS_OK
);
1905 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1906 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1907 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1909 torture_comment(torture
, "Testing notify rmdir\n");
1910 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1911 status
= smb2_util_rmdir(tree
, fname
);
1912 CHECK_STATUS(status
, NT_STATUS_OK
);
1914 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1915 CHECK_STATUS(status
, NT_STATUS_OK
);
1916 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1917 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1918 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1920 torture_comment(torture
, "SIMPLE CHANGE NOTIFY OK\n");
1922 torture_comment(torture
, "TESTING WITH SECONDARY TCON\n");
1923 tree1
= secondary_tcon(tree
, torture
);
1925 torture_comment(torture
, "Testing notify mkdir\n");
1926 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1927 smb2_util_mkdir(tree1
, fname
);
1929 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1930 CHECK_STATUS(status
, NT_STATUS_OK
);
1932 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1933 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1934 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1936 torture_comment(torture
, "Testing notify rmdir\n");
1937 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1938 smb2_util_rmdir(tree
, fname
);
1940 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1941 CHECK_STATUS(status
, NT_STATUS_OK
);
1942 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1943 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1944 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1946 torture_comment(torture
, "CHANGE NOTIFY WITH TCON OK\n");
1948 torture_comment(torture
, "Disconnecting secondary tree\n");
1949 status
= smb2_tdis(tree1
);
1950 CHECK_STATUS(status
, NT_STATUS_OK
);
1953 torture_comment(torture
, "Testing notify mkdir\n");
1954 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1955 smb2_util_mkdir(tree
, fname
);
1957 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1958 CHECK_STATUS(status
, NT_STATUS_OK
);
1960 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1961 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
1962 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1964 torture_comment(torture
, "Testing notify rmdir\n");
1965 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1966 smb2_util_rmdir(tree
, fname
);
1968 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1969 CHECK_STATUS(status
, NT_STATUS_OK
);
1970 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1971 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1972 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1974 torture_comment(torture
, "CHANGE NOTIFY WITH TDIS OK\n");
1976 smb2_util_close(tree
, h1
);
1977 smb2_deltree(tree
, BASEDIR
);
1983 basic testing of SMB2 change notify
1985 struct torture_suite
*torture_smb2_notify_init(void)
1987 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "notify");
1989 torture_suite_add_1smb2_test(suite
, "valid-req", test_valid_request
);
1990 torture_suite_add_1smb2_test(suite
, "tcon", torture_smb2_notify_tcon
);
1991 torture_suite_add_2smb2_test(suite
, "dir", torture_smb2_notify_dir
);
1992 torture_suite_add_2smb2_test(suite
, "mask", torture_smb2_notify_mask
);
1993 torture_suite_add_1smb2_test(suite
, "tdis", torture_smb2_notify_tree_disconnect
);
1994 torture_suite_add_2smb2_test(suite
, "mask-change", torture_smb2_notify_mask_change
);
1995 torture_suite_add_2smb2_test(suite
, "logoff", torture_smb2_notify_ulogoff
);
1996 torture_suite_add_1smb2_test(suite
, "tree", torture_smb2_notify_tree
);
1997 torture_suite_add_2smb2_test(suite
, "basedir", torture_smb2_notify_basedir
);
1998 torture_suite_add_2smb2_test(suite
, "double", torture_smb2_notify_double
);
1999 torture_suite_add_1smb2_test(suite
, "file", torture_smb2_notify_file
);
2000 torture_suite_add_1smb2_test(suite
, "tcp", torture_smb2_notify_tcp_disconnect
);
2001 torture_suite_add_2smb2_test(suite
, "rec", torture_smb2_notify_recursive
);
2002 torture_suite_add_1smb2_test(suite
, "overflow", torture_smb2_notify_overflow
);
2004 suite
->description
= talloc_strdup(suite
, "SMB2-NOTIFY tests");