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+CANCEL 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 testing of change notifies followed by a tdis - no cancel
1253 static bool torture_smb2_notify_tree_disconnect_1(
1254 struct torture_context
*torture
,
1255 struct smb2_tree
*tree
)
1259 union smb_notify notify
;
1261 struct smb2_handle h1
;
1262 struct smb2_request
*req
;
1264 smb2_deltree(tree
, BASEDIR
);
1265 smb2_util_rmdir(tree
, BASEDIR
);
1267 torture_comment(torture
, "TESTING CHANGE NOTIFY ASYNC FOLLOWED BY "
1268 "TREE-DISCONNECT\n");
1271 get a handle on the directory
1273 ZERO_STRUCT(io
.smb2
);
1274 io
.generic
.level
= RAW_OPEN_SMB2
;
1275 io
.smb2
.in
.create_flags
= 0;
1276 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1277 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1278 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1279 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1280 NTCREATEX_SHARE_ACCESS_WRITE
;
1281 io
.smb2
.in
.alloc_size
= 0;
1282 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1283 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1284 io
.smb2
.in
.security_flags
= 0;
1285 io
.smb2
.in
.fname
= BASEDIR
;
1287 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1288 CHECK_STATUS(status
, NT_STATUS_OK
);
1289 h1
= io
.smb2
.out
.file
.handle
;
1291 /* ask for a change notify,
1292 on file or directory name changes */
1293 ZERO_STRUCT(notify
.smb2
);
1294 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1295 notify
.smb2
.in
.buffer_size
= 1000;
1296 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1297 notify
.smb2
.in
.file
.handle
= h1
;
1298 notify
.smb2
.in
.recursive
= true;
1300 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1301 WAIT_FOR_ASYNC_RESPONSE(req
);
1303 status
= smb2_tdis(tree
);
1304 CHECK_STATUS(status
, NT_STATUS_OK
);
1306 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1307 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1310 smb2_deltree(tree
, BASEDIR
);
1315 basic testing of change notifies followed by a ulogoff
1318 static bool torture_smb2_notify_ulogoff(struct torture_context
*torture
,
1319 struct smb2_tree
*tree1
)
1323 union smb_notify notify
;
1325 struct smb2_handle h1
;
1326 struct smb2_request
*req
;
1328 smb2_deltree(tree1
, BASEDIR
);
1329 smb2_util_rmdir(tree1
, BASEDIR
);
1331 torture_comment(torture
, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1334 get a handle on the directory
1336 ZERO_STRUCT(io
.smb2
);
1337 io
.generic
.level
= RAW_OPEN_SMB2
;
1338 io
.smb2
.in
.create_flags
= 0;
1339 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1340 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1341 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1342 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1343 NTCREATEX_SHARE_ACCESS_WRITE
;
1344 io
.smb2
.in
.alloc_size
= 0;
1345 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1346 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1347 io
.smb2
.in
.security_flags
= 0;
1348 io
.smb2
.in
.fname
= BASEDIR
;
1350 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1351 CHECK_STATUS(status
, NT_STATUS_OK
);
1353 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
1354 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1355 CHECK_STATUS(status
, NT_STATUS_OK
);
1356 h1
= io
.smb2
.out
.file
.handle
;
1358 /* ask for a change notify,
1359 on file or directory name changes */
1360 ZERO_STRUCT(notify
.smb2
);
1361 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1362 notify
.smb2
.in
.buffer_size
= 1000;
1363 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1364 notify
.smb2
.in
.file
.handle
= h1
;
1365 notify
.smb2
.in
.recursive
= true;
1367 req
= smb2_notify_send(tree1
, &(notify
.smb2
));
1369 WAIT_FOR_ASYNC_RESPONSE(req
);
1371 status
= smb2_logoff(tree1
->session
);
1372 CHECK_STATUS(status
, NT_STATUS_OK
);
1374 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1375 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1378 smb2_deltree(tree1
, BASEDIR
);
1382 static void tcp_dis_handler(struct smb2_transport
*t
, void *p
)
1384 struct smb2_tree
*tree
= (struct smb2_tree
*)p
;
1385 smb2_transport_dead(tree
->session
->transport
,
1386 NT_STATUS_LOCAL_DISCONNECT
);
1392 basic testing of change notifies followed by tcp disconnect
1395 static bool torture_smb2_notify_tcp_disconnect(
1396 struct torture_context
*torture
,
1397 struct smb2_tree
*tree
)
1401 union smb_notify notify
;
1403 struct smb2_handle h1
;
1404 struct smb2_request
*req
;
1406 smb2_deltree(tree
, BASEDIR
);
1407 smb2_util_rmdir(tree
, BASEDIR
);
1409 torture_comment(torture
,
1410 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1413 get a handle on the directory
1415 ZERO_STRUCT(io
.smb2
);
1416 io
.generic
.level
= RAW_OPEN_SMB2
;
1417 io
.smb2
.in
.create_flags
= 0;
1418 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1419 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1420 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1421 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1422 NTCREATEX_SHARE_ACCESS_WRITE
;
1423 io
.smb2
.in
.alloc_size
= 0;
1424 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1425 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1426 io
.smb2
.in
.security_flags
= 0;
1427 io
.smb2
.in
.fname
= BASEDIR
;
1429 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1430 CHECK_STATUS(status
, NT_STATUS_OK
);
1431 h1
= io
.smb2
.out
.file
.handle
;
1433 /* ask for a change notify,
1434 on file or directory name changes */
1435 ZERO_STRUCT(notify
.smb2
);
1436 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1437 notify
.smb2
.in
.buffer_size
= 1000;
1438 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1439 notify
.smb2
.in
.file
.handle
= h1
;
1440 notify
.smb2
.in
.recursive
= true;
1442 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1444 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1445 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1447 notify
.smb2
.in
.recursive
= true;
1448 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1449 smb2_transport_idle_handler(tree
->session
->transport
,
1450 tcp_dis_handler
, 250, tree
);
1452 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1453 CHECK_STATUS(status
, NT_STATUS_LOCAL_DISCONNECT
);
1460 test setting up two change notify requests on one handle
1463 static bool torture_smb2_notify_double(struct torture_context
*torture
,
1464 struct smb2_tree
*tree1
,
1465 struct smb2_tree
*tree2
)
1469 union smb_notify notify
;
1471 struct smb2_handle h1
;
1472 struct smb2_request
*req1
, *req2
;
1474 smb2_deltree(tree1
, BASEDIR
);
1475 smb2_util_rmdir(tree1
, BASEDIR
);
1477 torture_comment(torture
,
1478 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1481 get a handle on the directory
1483 ZERO_STRUCT(io
.smb2
);
1484 io
.generic
.level
= RAW_OPEN_SMB2
;
1485 io
.smb2
.in
.create_flags
= 0;
1486 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_READ
|
1487 SEC_RIGHTS_FILE_WRITE
|
1488 SEC_RIGHTS_FILE_ALL
;
1489 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1490 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1491 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1492 NTCREATEX_SHARE_ACCESS_WRITE
;
1493 io
.smb2
.in
.alloc_size
= 0;
1494 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1495 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1496 io
.smb2
.in
.security_flags
= 0;
1497 io
.smb2
.in
.fname
= BASEDIR
;
1499 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1500 CHECK_STATUS(status
, NT_STATUS_OK
);
1501 h1
= io
.smb2
.out
.file
.handle
;
1503 /* ask for a change notify,
1504 on file or directory name changes */
1505 ZERO_STRUCT(notify
.smb2
);
1506 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1507 notify
.smb2
.in
.buffer_size
= 1000;
1508 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1509 notify
.smb2
.in
.file
.handle
= h1
;
1510 notify
.smb2
.in
.recursive
= true;
1512 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1514 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1515 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1517 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1519 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1520 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1522 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name");
1523 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1524 req2
= smb2_notify_send(tree1
, &(notify
.smb2
));
1526 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1527 CHECK_STATUS(status
, NT_STATUS_OK
);
1528 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1529 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1531 smb2_util_mkdir(tree2
, BASEDIR
"\\subdir-name2");
1533 status
= smb2_notify_recv(req2
, torture
, &(notify
.smb2
));
1534 CHECK_STATUS(status
, NT_STATUS_OK
);
1535 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1536 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name2");
1539 smb2_deltree(tree1
, BASEDIR
);
1545 test multiple change notifies at different depths and with/without recursion
1548 static bool torture_smb2_notify_tree(struct torture_context
*torture
,
1549 struct smb2_tree
*tree
)
1552 union smb_notify notify
;
1554 struct smb2_request
*req
;
1561 struct smb2_handle h1
;
1564 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 30 },
1565 {BASEDIR
"\\zqy", true, FILE_NOTIFY_CHANGE_NAME
, 8 },
1566 {BASEDIR
"\\atsy", true, FILE_NOTIFY_CHANGE_NAME
, 4 },
1567 {BASEDIR
"\\abc\\foo", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1568 {BASEDIR
"\\abc\\blah", true, FILE_NOTIFY_CHANGE_NAME
, 13 },
1569 {BASEDIR
"\\abc\\blah", false, FILE_NOTIFY_CHANGE_NAME
, 7 },
1570 {BASEDIR
"\\abc\\blah\\a", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1571 {BASEDIR
"\\abc\\blah\\b", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1572 {BASEDIR
"\\abc\\blah\\c", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1573 {BASEDIR
"\\abc\\fooblah", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1574 {BASEDIR
"\\zqy\\xx", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1575 {BASEDIR
"\\zqy\\yyy", true, FILE_NOTIFY_CHANGE_NAME
, 2 },
1576 {BASEDIR
"\\zqy\\..", true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1577 {BASEDIR
, true, FILE_NOTIFY_CHANGE_NAME
, 40 },
1578 {BASEDIR
, false,FILE_NOTIFY_CHANGE_NAME
, 6 },
1579 {BASEDIR
"\\atsy", false,FILE_NOTIFY_CHANGE_NAME
, 4 },
1580 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1581 {BASEDIR
"\\abc", false,FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1582 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_FILE_NAME
, 0 },
1583 {BASEDIR
"\\abc", true, FILE_NOTIFY_CHANGE_NAME
, 24 },
1587 bool all_done
= false;
1589 smb2_deltree(tree
, BASEDIR
);
1590 smb2_util_rmdir(tree
, BASEDIR
);
1592 torture_comment(torture
, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1594 ZERO_STRUCT(io
.smb2
);
1595 io
.generic
.level
= RAW_OPEN_SMB2
;
1596 io
.smb2
.in
.create_flags
= 0;
1597 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1598 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1599 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1600 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1601 NTCREATEX_SHARE_ACCESS_WRITE
;
1602 io
.smb2
.in
.alloc_size
= 0;
1603 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1604 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1605 io
.smb2
.in
.security_flags
= 0;
1606 io
.smb2
.in
.fname
= BASEDIR
;
1607 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1608 CHECK_STATUS(status
, NT_STATUS_OK
);
1610 ZERO_STRUCT(notify
.smb2
);
1611 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1612 notify
.smb2
.in
.buffer_size
= 20000;
1615 setup the directory tree, and the notify buffer on each directory
1617 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1618 io
.smb2
.in
.fname
= dirs
[i
].path
;
1619 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1620 CHECK_STATUS(status
, NT_STATUS_OK
);
1621 dirs
[i
].h1
= io
.smb2
.out
.file
.handle
;
1623 notify
.smb2
.in
.completion_filter
= dirs
[i
].filter
;
1624 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1625 notify
.smb2
.in
.recursive
= dirs
[i
].recursive
;
1626 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1628 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1629 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1632 /* trigger 2 events in each dir */
1633 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1634 char *path
= talloc_asprintf(torture
, "%s\\test.dir",
1636 smb2_util_mkdir(tree
, path
);
1637 smb2_util_rmdir(tree
, path
);
1641 /* give a bit of time for the events to propogate */
1642 tv
= timeval_current();
1645 /* count events that have happened in each dir */
1646 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1647 notify
.smb2
.in
.file
.handle
= dirs
[i
].h1
;
1648 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1650 notify
.smb2
.out
.num_changes
= 0;
1651 status
= smb2_notify_recv(req
, torture
,
1653 dirs
[i
].counted
+= notify
.smb2
.out
.num_changes
;
1658 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1659 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1663 } while (!all_done
&& timeval_elapsed(&tv
) < 20);
1665 torture_comment(torture
, "took %.4f seconds to propogate all events\n",
1666 timeval_elapsed(&tv
));
1668 for (i
=0;i
<ARRAY_SIZE(dirs
);i
++) {
1669 if (dirs
[i
].counted
!= dirs
[i
].expected
) {
1670 torture_comment(torture
,
1671 "ERROR: i=%d expected %d got %d for '%s'\n",
1672 i
, dirs
[i
].expected
, dirs
[i
].counted
,
1679 run from the back, closing and deleting
1681 for (i
=ARRAY_SIZE(dirs
)-1;i
>=0;i
--) {
1682 smb2_util_close(tree
, dirs
[i
].h1
);
1683 smb2_util_rmdir(tree
, dirs
[i
].path
);
1687 smb2_deltree(tree
, BASEDIR
);
1688 smb2_util_rmdir(tree
, BASEDIR
);
1693 Test response when cached server events exceed single NT NOTFIY response
1697 static bool torture_smb2_notify_overflow(struct torture_context
*torture
,
1698 struct smb2_tree
*tree
)
1702 union smb_notify notify
;
1704 struct smb2_handle h1
, h2
;
1706 struct smb2_request
*req1
;
1709 smb2_deltree(tree
, BASEDIR
);
1710 smb2_util_rmdir(tree
, BASEDIR
);
1712 torture_comment(torture
, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1714 /* get a handle on the directory */
1715 ZERO_STRUCT(io
.smb2
);
1716 io
.generic
.level
= RAW_OPEN_SMB2
;
1717 io
.smb2
.in
.create_flags
= 0;
1718 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1719 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1720 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1721 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1722 NTCREATEX_SHARE_ACCESS_WRITE
;
1723 io
.smb2
.in
.alloc_size
= 0;
1724 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1725 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1726 io
.smb2
.in
.security_flags
= 0;
1727 io
.smb2
.in
.fname
= BASEDIR
;
1729 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1730 CHECK_STATUS(status
, NT_STATUS_OK
);
1731 h1
= io
.smb2
.out
.file
.handle
;
1733 /* ask for a change notify, on name changes. */
1734 ZERO_STRUCT(notify
.smb2
);
1735 notify
.smb2
.level
= RAW_NOTIFY_NTTRANS
;
1736 notify
.smb2
.in
.buffer_size
= 1000;
1737 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1738 notify
.smb2
.in
.file
.handle
= h1
;
1740 notify
.smb2
.in
.recursive
= true;
1741 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1743 /* cancel initial requests so the buffer is setup */
1745 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1746 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1748 /* open a lot of files, filling up the server side notify buffer */
1749 torture_comment(torture
,
1750 "Testing overflowed buffer notify on create of %d files\n",
1753 for (i
=0;i
<count
;i
++) {
1754 char *fname
= talloc_asprintf(torture
,
1755 BASEDIR
"\\test%d.txt", i
);
1757 ZERO_STRUCT(io1
.smb2
);
1758 io1
.generic
.level
= RAW_OPEN_SMB2
;
1759 io1
.smb2
.in
.create_flags
= 0;
1760 io1
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1761 io1
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1762 io1
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1763 io1
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1764 NTCREATEX_SHARE_ACCESS_WRITE
;
1765 io1
.smb2
.in
.alloc_size
= 0;
1766 io1
.smb2
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1767 io1
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1768 io1
.smb2
.in
.security_flags
= 0;
1769 io1
.smb2
.in
.fname
= fname
;
1771 h2
= custom_smb2_create(tree
, torture
, &(io1
.smb2
));
1773 smb2_util_close(tree
, h2
);
1776 req1
= smb2_notify_send(tree
, &(notify
.smb2
));
1777 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1778 CHECK_STATUS(status
, STATUS_NOTIFY_ENUM_DIR
);
1779 CHECK_VAL(notify
.smb2
.out
.num_changes
, 0);
1782 smb2_deltree(tree
, BASEDIR
);
1787 Test if notifications are returned for changes to the base directory.
1791 static bool torture_smb2_notify_basedir(struct torture_context
*torture
,
1792 struct smb2_tree
*tree1
,
1793 struct smb2_tree
*tree2
)
1797 union smb_notify notify
;
1799 struct smb2_handle h1
;
1800 struct smb2_request
*req1
;
1802 smb2_deltree(tree1
, BASEDIR
);
1803 smb2_util_rmdir(tree1
, BASEDIR
);
1805 torture_comment(torture
, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1807 /* get a handle on the directory */
1808 ZERO_STRUCT(io
.smb2
);
1809 io
.generic
.level
= RAW_OPEN_SMB2
;
1810 io
.smb2
.in
.create_flags
= 0;
1811 io
.smb2
.in
.desired_access
= SEC_FILE_ALL
;
1812 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1813 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1814 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1815 NTCREATEX_SHARE_ACCESS_WRITE
;
1816 io
.smb2
.in
.alloc_size
= 0;
1817 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1818 io
.smb2
.in
.impersonation_level
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1819 io
.smb2
.in
.security_flags
= 0;
1820 io
.smb2
.in
.fname
= BASEDIR
;
1822 status
= smb2_create(tree1
, torture
, &(io
.smb2
));
1823 CHECK_STATUS(status
, NT_STATUS_OK
);
1824 h1
= io
.smb2
.out
.file
.handle
;
1826 /* create a test file that will also be modified */
1827 io
.smb2
.in
.fname
= BASEDIR
"\\tname1";
1828 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1829 status
= smb2_create(tree2
, torture
, &(io
.smb2
));
1830 CHECK_STATUS(status
,NT_STATUS_OK
);
1831 smb2_util_close(tree2
, io
.smb2
.out
.file
.handle
);
1833 /* ask for a change notify, on attribute changes. */
1834 ZERO_STRUCT(notify
.smb2
);
1835 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1836 notify
.smb2
.in
.buffer_size
= 1000;
1837 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
1838 notify
.smb2
.in
.file
.handle
= h1
;
1839 notify
.smb2
.in
.recursive
= true;
1841 req1
= smb2_notify_send(tree1
, &(notify
.smb2
));
1843 /* set attribute on the base dir */
1844 smb2_util_setatr(tree2
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
);
1846 /* set attribute on a file to assure we receive a notification */
1847 smb2_util_setatr(tree2
, BASEDIR
"\\tname1", FILE_ATTRIBUTE_HIDDEN
);
1850 /* check how many responses were given, expect only 1 for the file */
1851 status
= smb2_notify_recv(req1
, torture
, &(notify
.smb2
));
1852 CHECK_STATUS(status
, NT_STATUS_OK
);
1853 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1854 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_MODIFIED
);
1855 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "tname1");
1858 smb2_deltree(tree1
, BASEDIR
);
1864 create a secondary tree connect - used to test for a bug in Samba3 messaging
1867 static struct smb2_tree
*secondary_tcon(struct smb2_tree
*tree
,
1868 struct torture_context
*tctx
)
1871 const char *share
, *host
;
1872 struct smb2_tree
*tree1
;
1873 union smb_tcon tcon
;
1875 share
= torture_setting_string(tctx
, "share", NULL
);
1876 host
= torture_setting_string(tctx
, "host", NULL
);
1878 torture_comment(tctx
,
1879 "create a second tree context on the same session\n");
1880 tree1
= smb2_tree_init(tree
->session
, tctx
, false);
1881 if (tree1
== NULL
) {
1882 torture_comment(tctx
, "Out of memory\n");
1886 ZERO_STRUCT(tcon
.smb2
);
1887 tcon
.generic
.level
= RAW_TCON_SMB2
;
1888 tcon
.smb2
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
1889 status
= smb2_tree_connect(tree
->session
, &(tcon
.smb2
));
1890 if (!NT_STATUS_IS_OK(status
)) {
1892 torture_comment(tctx
,"Failed to create secondary tree\n");
1896 smb2cli_tcon_set_values(tree1
->smbXcli
,
1897 tree1
->session
->smbXcli
,
1899 tcon
.smb2
.out
.share_type
,
1900 tcon
.smb2
.out
.flags
,
1901 tcon
.smb2
.out
.capabilities
,
1902 tcon
.smb2
.out
.access_mask
);
1904 torture_comment(tctx
,"tid1=%d tid2=%d\n",
1905 smb2cli_tcon_current_id(tree
->smbXcli
),
1906 smb2cli_tcon_current_id(tree1
->smbXcli
));
1913 very simple change notify test
1915 static bool torture_smb2_notify_tcon(struct torture_context
*torture
,
1916 struct smb2_tree
*tree
)
1920 union smb_notify notify
;
1922 struct smb2_handle h1
;
1923 struct smb2_request
*req
= NULL
;
1924 struct smb2_tree
*tree1
= NULL
;
1925 const char *fname
= BASEDIR
"\\subdir-name";
1927 smb2_deltree(tree
, BASEDIR
);
1928 smb2_util_rmdir(tree
, BASEDIR
);
1930 torture_comment(torture
, "TESTING SIMPLE CHANGE NOTIFY\n");
1933 get a handle on the directory
1936 ZERO_STRUCT(io
.smb2
);
1937 io
.generic
.level
= RAW_OPEN_SMB2
;
1938 io
.smb2
.in
.create_flags
= 0;
1939 io
.smb2
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1940 io
.smb2
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1941 io
.smb2
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
|
1942 FILE_ATTRIBUTE_DIRECTORY
;
1943 io
.smb2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1944 NTCREATEX_SHARE_ACCESS_WRITE
;
1945 io
.smb2
.in
.alloc_size
= 0;
1946 io
.smb2
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
1947 io
.smb2
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1948 io
.smb2
.in
.security_flags
= 0;
1949 io
.smb2
.in
.fname
= BASEDIR
;
1951 status
= smb2_create(tree
, torture
, &(io
.smb2
));
1952 CHECK_STATUS(status
, NT_STATUS_OK
);
1953 h1
= io
.smb2
.out
.file
.handle
;
1955 /* ask for a change notify,
1956 on file or directory name changes */
1957 ZERO_STRUCT(notify
.smb2
);
1958 notify
.smb2
.level
= RAW_NOTIFY_SMB2
;
1959 notify
.smb2
.in
.buffer_size
= 1000;
1960 notify
.smb2
.in
.completion_filter
= FILE_NOTIFY_CHANGE_NAME
;
1961 notify
.smb2
.in
.file
.handle
= h1
;
1962 notify
.smb2
.in
.recursive
= true;
1964 torture_comment(torture
, "Testing notify mkdir\n");
1965 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1967 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1968 CHECK_STATUS(status
, NT_STATUS_CANCELLED
);
1970 notify
.smb2
.in
.recursive
= true;
1971 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1972 status
= smb2_util_mkdir(tree
, fname
);
1973 CHECK_STATUS(status
, NT_STATUS_OK
);
1975 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1976 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_ADDED
);
1980 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1982 torture_comment(torture
, "Testing notify rmdir\n");
1983 req
= smb2_notify_send(tree
, &(notify
.smb2
));
1984 status
= smb2_util_rmdir(tree
, fname
);
1985 CHECK_STATUS(status
, NT_STATUS_OK
);
1987 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
1988 CHECK_STATUS(status
, NT_STATUS_OK
);
1989 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
1990 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
1991 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
1993 torture_comment(torture
, "SIMPLE CHANGE NOTIFY OK\n");
1995 torture_comment(torture
, "TESTING WITH SECONDARY TCON\n");
1996 tree1
= secondary_tcon(tree
, torture
);
1998 torture_comment(torture
, "Testing notify mkdir\n");
1999 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2000 smb2_util_mkdir(tree1
, fname
);
2002 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2003 CHECK_STATUS(status
, NT_STATUS_OK
);
2005 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2006 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
2007 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2009 torture_comment(torture
, "Testing notify rmdir\n");
2010 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2011 smb2_util_rmdir(tree
, fname
);
2013 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2014 CHECK_STATUS(status
, NT_STATUS_OK
);
2015 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2016 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
2017 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2019 torture_comment(torture
, "CHANGE NOTIFY WITH TCON OK\n");
2021 torture_comment(torture
, "Disconnecting secondary tree\n");
2022 status
= smb2_tdis(tree1
);
2023 CHECK_STATUS(status
, NT_STATUS_OK
);
2026 torture_comment(torture
, "Testing notify mkdir\n");
2027 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2028 smb2_util_mkdir(tree
, fname
);
2030 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2031 CHECK_STATUS(status
, NT_STATUS_OK
);
2033 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2034 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_ADDED
);
2035 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2037 torture_comment(torture
, "Testing notify rmdir\n");
2038 req
= smb2_notify_send(tree
, &(notify
.smb2
));
2039 smb2_util_rmdir(tree
, fname
);
2041 status
= smb2_notify_recv(req
, torture
, &(notify
.smb2
));
2042 CHECK_STATUS(status
, NT_STATUS_OK
);
2043 CHECK_VAL(notify
.smb2
.out
.num_changes
, 1);
2044 CHECK_VAL(notify
.smb2
.out
.changes
[0].action
, NOTIFY_ACTION_REMOVED
);
2045 CHECK_WIRE_STR(notify
.smb2
.out
.changes
[0].name
, "subdir-name");
2047 torture_comment(torture
, "CHANGE NOTIFY WITH TDIS OK\n");
2049 smb2_util_close(tree
, h1
);
2050 smb2_deltree(tree
, BASEDIR
);
2056 basic testing of SMB2 change notify
2058 struct torture_suite
*torture_smb2_notify_init(void)
2060 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "notify");
2062 torture_suite_add_1smb2_test(suite
, "valid-req", test_valid_request
);
2063 torture_suite_add_1smb2_test(suite
, "tcon", torture_smb2_notify_tcon
);
2064 torture_suite_add_2smb2_test(suite
, "dir", torture_smb2_notify_dir
);
2065 torture_suite_add_2smb2_test(suite
, "mask", torture_smb2_notify_mask
);
2066 torture_suite_add_1smb2_test(suite
, "tdis", torture_smb2_notify_tree_disconnect
);
2067 torture_suite_add_1smb2_test(suite
, "tdis1", torture_smb2_notify_tree_disconnect_1
);
2068 torture_suite_add_2smb2_test(suite
, "mask-change", torture_smb2_notify_mask_change
);
2069 torture_suite_add_1smb2_test(suite
, "logoff", torture_smb2_notify_ulogoff
);
2070 torture_suite_add_1smb2_test(suite
, "tree", torture_smb2_notify_tree
);
2071 torture_suite_add_2smb2_test(suite
, "basedir", torture_smb2_notify_basedir
);
2072 torture_suite_add_2smb2_test(suite
, "double", torture_smb2_notify_double
);
2073 torture_suite_add_1smb2_test(suite
, "file", torture_smb2_notify_file
);
2074 torture_suite_add_1smb2_test(suite
, "tcp", torture_smb2_notify_tcp_disconnect
);
2075 torture_suite_add_2smb2_test(suite
, "rec", torture_smb2_notify_recursive
);
2076 torture_suite_add_1smb2_test(suite
, "overflow", torture_smb2_notify_overflow
);
2078 suite
->description
= talloc_strdup(suite
, "SMB2-NOTIFY tests");