s4:torture:smb2: check for success of talloc in secondary_tcon()
[samba.git] / source4 / torture / smb2 / notify.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    SMB2 notify test suite
5
6    Copyright (C) Stefan Metzmacher 2006
7    Copyright (C) Andrew Tridgell 2009
8
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.
13
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.
18
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/>.
21 */
22
23 #include "includes.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "libcli/security/security.h"
31 #include "torture/util.h"
32
33 #include "system/filesys.h"
34 #include "auth/credentials/credentials.h"
35 #include "lib/cmdline/popt_common.h"
36 #include "librpc/gen_ndr/security.h"
37
38 #include "lib/events/events.h"
39
40 #include "libcli/raw/libcliraw.h"
41 #include "libcli/raw/raw_proto.h"
42 #include "libcli/libcli.h"
43
44 #define CHECK_STATUS(status, correct) do { \
45         if (!NT_STATUS_EQUAL(status, correct)) { \
46                 torture_result(torture, TORTURE_FAIL, \
47                        "(%s) Incorrect status %s - should be %s\n", \
48                        __location__, nt_errstr(status), nt_errstr(correct)); \
49                 ret = false; \
50                 goto done; \
51         }} while (0)
52
53 #define CHECK_VAL(v, correct) do { \
54         if ((v) != (correct)) { \
55                 torture_result(torture, TORTURE_FAIL, \
56                        "(%s) wrong value for %s  0x%x should be 0x%x\n", \
57                        __location__, #v, (int)v, (int)correct); \
58                 ret = false; \
59                 goto done; \
60         }} while (0)
61
62 #define CHECK_WIRE_STR(field, value) do { \
63         if (!field.s || strcmp(field.s, value)) { \
64                 torture_result(torture, TORTURE_FAIL, \
65                         "(%s) %s [%s] != %s\n",  __location__, #field, \
66                         field.s, value); \
67                 ret = false; \
68                 goto done; \
69         }} while (0)
70
71 #define BASEDIR "test_notify"
72 #define FNAME "smb2-notify01.dat"
73
74 static bool test_valid_request(struct torture_context *torture,
75                                struct smb2_tree *tree)
76 {
77         bool ret = true;
78         NTSTATUS status;
79         struct smb2_handle dh;
80         struct smb2_notify n;
81         struct smb2_request *req;
82         uint32_t max_buffer_size;
83
84         torture_comment(torture, "TESTING VALIDITY OF CHANGE NOTIFY REQUEST\n");
85
86         smb2_util_unlink(tree, FNAME);
87
88         status = smb2_util_roothandle(tree, &dh);
89         CHECK_STATUS(status, NT_STATUS_OK);
90
91         /* 0x00080000 is the default max buffer size for Windows servers
92          * pre-Win7 */
93         max_buffer_size = torture_setting_ulong(torture, "cn_max_buffer_size",
94                                                 0x00080000);
95
96         n.in.recursive          = 0x0000;
97         n.in.buffer_size        = max_buffer_size;
98         n.in.file.handle        = dh;
99         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
100         n.in.unknown            = 0x00000000;
101         req = smb2_notify_send(tree, &n);
102
103         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
104                 if (tevent_loop_once(torture->ev) != 0) {
105                         break;
106                 }
107         }
108
109         status = torture_setup_complex_file(tree, FNAME);
110         CHECK_STATUS(status, NT_STATUS_OK);
111
112         status = smb2_notify_recv(req, torture, &n);
113         CHECK_STATUS(status, NT_STATUS_OK);
114         CHECK_VAL(n.out.num_changes, 1);
115         CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_ADDED);
116         CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
117
118         /*
119          * if the change response doesn't fit in the buffer
120          * NOTIFY_ENUM_DIR is returned.
121          */
122         n.in.buffer_size        = 0x00000000;
123         req = smb2_notify_send(tree, &n);
124
125         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
126                 if (tevent_loop_once(torture->ev) != 0) {
127                         break;
128                 }
129         }
130
131         status = torture_setup_complex_file(tree, FNAME);
132         CHECK_STATUS(status, NT_STATUS_OK);
133
134         status = smb2_notify_recv(req, torture, &n);
135         CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);
136
137         /*
138          * if the change response fits in the buffer we get
139          * NT_STATUS_OK again
140          */
141         n.in.buffer_size        = max_buffer_size;
142         req = smb2_notify_send(tree, &n);
143
144         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
145                 if (tevent_loop_once(torture->ev) != 0) {
146                         break;
147                 }
148         }
149
150         status = torture_setup_complex_file(tree, FNAME);
151         CHECK_STATUS(status, NT_STATUS_OK);
152
153         status = smb2_notify_recv(req, torture, &n);
154         CHECK_STATUS(status, NT_STATUS_OK);
155         CHECK_VAL(n.out.num_changes, 3);
156         CHECK_VAL(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);
157         CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
158         CHECK_VAL(n.out.changes[1].action, NOTIFY_ACTION_ADDED);
159         CHECK_WIRE_STR(n.out.changes[1].name, FNAME);
160         CHECK_VAL(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED);
161         CHECK_WIRE_STR(n.out.changes[2].name, FNAME);
162
163         /* if the first notify returns NOTIFY_ENUM_DIR, all do */
164         status = smb2_util_close(tree, dh);
165         CHECK_STATUS(status, NT_STATUS_OK);
166         status = smb2_util_roothandle(tree, &dh);
167         CHECK_STATUS(status, NT_STATUS_OK);
168
169         n.in.recursive          = 0x0000;
170         n.in.buffer_size        = 0x00000001;
171         n.in.file.handle        = dh;
172         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
173         n.in.unknown            = 0x00000000;
174         req = smb2_notify_send(tree, &n);
175
176         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
177                 if (tevent_loop_once(torture->ev) != 0) {
178                         break;
179                 }
180         }
181
182         status = torture_setup_complex_file(tree, FNAME);
183         CHECK_STATUS(status, NT_STATUS_OK);
184
185         status = smb2_notify_recv(req, torture, &n);
186         CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);
187
188         n.in.buffer_size        = max_buffer_size;
189         req = smb2_notify_send(tree, &n);
190         while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
191                 if (tevent_loop_once(torture->ev) != 0) {
192                         break;
193                 }
194         }
195
196         status = torture_setup_complex_file(tree, FNAME);
197         CHECK_STATUS(status, NT_STATUS_OK);
198
199         status = smb2_notify_recv(req, torture, &n);
200         CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);
201
202         /* if the buffer size is too large, we get invalid parameter */
203         n.in.recursive          = 0x0000;
204         n.in.buffer_size        = max_buffer_size + 1;
205         n.in.file.handle        = dh;
206         n.in.completion_filter  = FILE_NOTIFY_CHANGE_ALL;
207         n.in.unknown            = 0x00000000;
208         req = smb2_notify_send(tree, &n);
209         status = smb2_notify_recv(req, torture, &n);
210         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
211
212 done:
213         return ret;
214 }
215
216 /*
217    basic testing of change notify on directories
218 */
219 static bool torture_smb2_notify_dir(struct torture_context *torture,
220                               struct smb2_tree *tree1,
221                               struct smb2_tree *tree2)
222 {
223         bool ret = true;
224         NTSTATUS status;
225         union smb_notify notify;
226         union smb_open io;
227         union smb_close cl;
228         int i, count;
229         struct smb2_handle h1, h2;
230         struct smb2_request *req, *req2;
231         const char *fname = BASEDIR "\\subdir-name";
232         extern int torture_numops;
233
234         torture_comment(torture, "TESTING CHANGE NOTIFY ON DIRECTORIES\n");
235
236         smb2_deltree(tree1, BASEDIR);
237         smb2_util_rmdir(tree1, BASEDIR);
238         /*
239           get a handle on the directory
240         */
241         ZERO_STRUCT(io.smb2);
242         io.generic.level = RAW_OPEN_SMB2;
243         io.smb2.in.create_flags = 0;
244         io.smb2.in.desired_access = SEC_FILE_ALL;
245         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
246         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
247         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
248                                 NTCREATEX_SHARE_ACCESS_WRITE;
249         io.smb2.in.alloc_size = 0;
250         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
251         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
252         io.smb2.in.security_flags = 0;
253         io.smb2.in.fname = BASEDIR;
254
255         status = smb2_create(tree1, torture, &(io.smb2));
256         CHECK_STATUS(status, NT_STATUS_OK);
257         h1 = io.smb2.out.file.handle;
258
259         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
260         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ;
261         status = smb2_create(tree1, torture, &(io.smb2));
262         CHECK_STATUS(status, NT_STATUS_OK);
263         h2 = io.smb2.out.file.handle;
264
265         /* ask for a change notify,
266            on file or directory name changes */
267         ZERO_STRUCT(notify.smb2);
268         notify.smb2.level = RAW_NOTIFY_SMB2;
269         notify.smb2.in.buffer_size = 1000;
270         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
271         notify.smb2.in.file.handle = h1;
272         notify.smb2.in.recursive = true;
273
274         torture_comment(torture, "Testing notify cancel\n");
275
276         req = smb2_notify_send(tree1, &(notify.smb2));
277         smb2_cancel(req);
278         status = smb2_notify_recv(req, torture, &(notify.smb2));
279         CHECK_STATUS(status, NT_STATUS_CANCELLED);
280
281         torture_comment(torture, "Testing notify mkdir\n");
282
283         req = smb2_notify_send(tree1, &(notify.smb2));
284         smb2_util_mkdir(tree2, fname);
285
286         status = smb2_notify_recv(req, torture, &(notify.smb2));
287         CHECK_STATUS(status, NT_STATUS_OK);
288
289         CHECK_VAL(notify.smb2.out.num_changes, 1);
290         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
291         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
292
293         torture_comment(torture, "Testing notify rmdir\n");
294
295         req = smb2_notify_send(tree1, &(notify.smb2));
296         smb2_util_rmdir(tree2, fname);
297
298         status = smb2_notify_recv(req, torture, &(notify.smb2));
299         CHECK_STATUS(status, NT_STATUS_OK);
300         CHECK_VAL(notify.smb2.out.num_changes, 1);
301         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
302         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
303
304         torture_comment(torture,
305                 "Testing notify mkdir - rmdir - mkdir - rmdir\n");
306
307         smb2_util_mkdir(tree2, fname);
308         smb2_util_rmdir(tree2, fname);
309         smb2_util_mkdir(tree2, fname);
310         smb2_util_rmdir(tree2, fname);
311         smb_msleep(200);
312         req = smb2_notify_send(tree1, &(notify.smb2));
313         status = smb2_notify_recv(req, torture, &(notify.smb2));
314         CHECK_STATUS(status, NT_STATUS_OK);
315         CHECK_VAL(notify.smb2.out.num_changes, 4);
316         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
317         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
318         CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_REMOVED);
319         CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name");
320         CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_ADDED);
321         CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name");
322         CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_REMOVED);
323         CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name");
324
325         count = torture_numops;
326         torture_comment(torture,
327                 "Testing buffered notify on create of %d files\n", count);
328         for (i=0;i<count;i++) {
329                 struct smb2_handle h12;
330                 char *fname2 = talloc_asprintf(torture, BASEDIR "\\test%d.txt",
331                                               i);
332
333                 ZERO_STRUCT(io.smb2);
334                 io.generic.level = RAW_OPEN_SMB2;
335                 io.smb2.in.create_flags = 0;
336                 io.smb2.in.desired_access = SEC_FILE_ALL;
337                 io.smb2.in.create_options =
338                     NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
339                 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
340                 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
341                                         NTCREATEX_SHARE_ACCESS_WRITE;
342                 io.smb2.in.alloc_size = 0;
343                 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
344                 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
345                 io.smb2.in.security_flags = 0;
346                 io.smb2.in.fname = fname2;
347
348                 status = smb2_create(tree1, torture, &(io.smb2));
349                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
350                         torture_comment(torture, "Failed to create %s \n",
351                                fname);
352                         ret = false;
353                         goto done;
354                 }
355                 h12 = io.smb2.out.file.handle;
356                 talloc_free(fname2);
357                 smb2_util_close(tree1, h12);
358         }
359
360         /* (1st notify) setup a new notify on a different directory handle.
361            This new notify won't see the events above. */
362         notify.smb2.in.file.handle = h2;
363         req2 = smb2_notify_send(tree1, &(notify.smb2));
364
365         /* (2nd notify) whereas this notify will see the above buffered events,
366            and it directly returns the buffered events */
367         notify.smb2.in.file.handle = h1;
368         req = smb2_notify_send(tree1, &(notify.smb2));
369
370         status = smb2_util_unlink(tree1, BASEDIR "\\nonexistant.txt");
371         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
372
373         /* (1st unlink) as the 2nd notify directly returns,
374            this unlink is only seen by the 1st notify and
375            the 3rd notify (later) */
376         torture_comment(torture,
377                 "Testing notify on unlink for the first file\n");
378         status = smb2_util_unlink(tree2, BASEDIR "\\test0.txt");
379         CHECK_STATUS(status, NT_STATUS_OK);
380
381         /* receive the reply from the 2nd notify */
382         status = smb2_notify_recv(req, torture, &(notify.smb2));
383         CHECK_STATUS(status, NT_STATUS_OK);
384
385         CHECK_VAL(notify.smb2.out.num_changes, count);
386         for (i=1;i<count;i++) {
387                 CHECK_VAL(notify.smb2.out.changes[i].action,
388                           NOTIFY_ACTION_ADDED);
389         }
390         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
391
392         torture_comment(torture, "and now from the 1st notify\n");
393         status = smb2_notify_recv(req2, torture, &(notify.smb2));
394         CHECK_STATUS(status, NT_STATUS_OK);
395         CHECK_VAL(notify.smb2.out.num_changes, 1);
396         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
397         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
398
399         torture_comment(torture,
400                 "(3rd notify) this notify will only see the 1st unlink\n");
401         req = smb2_notify_send(tree1, &(notify.smb2));
402
403         status = smb2_util_unlink(tree1, BASEDIR "\\nonexistant.txt");
404         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
405
406         for (i=1;i<count;i++) {
407                 char *fname2 = talloc_asprintf(torture,
408                               BASEDIR "\\test%d.txt", i);
409                 status = smb2_util_unlink(tree2, fname2);
410                 CHECK_STATUS(status, NT_STATUS_OK);
411                 talloc_free(fname2);
412         }
413
414         /* receive the 3rd notify */
415         status = smb2_notify_recv(req, torture, &(notify.smb2));
416         CHECK_STATUS(status, NT_STATUS_OK);
417         CHECK_VAL(notify.smb2.out.num_changes, 1);
418         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
419         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "test0.txt");
420
421         /* and we now see the rest of the unlink calls on both
422          * directory handles */
423         notify.smb2.in.file.handle = h1;
424         sleep(3);
425         req = smb2_notify_send(tree1, &(notify.smb2));
426         status = smb2_notify_recv(req, torture, &(notify.smb2));
427         CHECK_STATUS(status, NT_STATUS_OK);
428         CHECK_VAL(notify.smb2.out.num_changes, count-1);
429         for (i=0;i<notify.smb2.out.num_changes;i++) {
430                 CHECK_VAL(notify.smb2.out.changes[i].action,
431                           NOTIFY_ACTION_REMOVED);
432         }
433         notify.smb2.in.file.handle = h2;
434         req = smb2_notify_send(tree1, &(notify.smb2));
435         status = smb2_notify_recv(req, torture, &(notify.smb2));
436         CHECK_STATUS(status, NT_STATUS_OK);
437         CHECK_VAL(notify.smb2.out.num_changes, count-1);
438         for (i=0;i<notify.smb2.out.num_changes;i++) {
439                 CHECK_VAL(notify.smb2.out.changes[i].action,
440                           NOTIFY_ACTION_REMOVED);
441         }
442
443         torture_comment(torture,
444         "Testing if a close() on the dir handle triggers the notify reply\n");
445
446         notify.smb2.in.file.handle = h1;
447         req = smb2_notify_send(tree1, &(notify.smb2));
448
449         ZERO_STRUCT(cl.smb2);
450         cl.smb2.level = RAW_CLOSE_SMB2;
451         cl.smb2.in.file.handle = h1;
452         status = smb2_close(tree1, &(cl.smb2));
453         CHECK_STATUS(status, NT_STATUS_OK);
454
455         status = smb2_notify_recv(req, torture, &(notify.smb2));
456         CHECK_STATUS(status, STATUS_NOTIFY_CLEANUP);
457         CHECK_VAL(notify.smb2.out.num_changes, 9);
458
459 done:
460         smb2_util_close(tree1, h1);
461         smb2_util_close(tree1, h2);
462         smb2_deltree(tree1, BASEDIR);
463         return ret;
464 }
465
466 static struct smb2_handle custom_smb2_create(struct smb2_tree *tree,
467                                                 struct torture_context *torture,
468                                                 struct smb2_create *smb2)
469 {
470         struct smb2_handle h1;
471         bool ret = true;
472         NTSTATUS status;
473         smb2_deltree(tree, smb2->in.fname);
474         status = smb2_create(tree, torture, smb2);
475         CHECK_STATUS(status, NT_STATUS_OK);
476         h1 = smb2->out.file.handle;
477 done:
478         return h1;
479 }
480
481 /*
482    testing of recursive change notify
483 */
484
485 static bool torture_smb2_notify_recursive(struct torture_context *torture,
486                                 struct smb2_tree *tree1,
487                                 struct smb2_tree *tree2)
488 {
489         bool ret = true;
490         NTSTATUS status;
491         union smb_notify notify;
492         union smb_open io, io1;
493         union smb_setfileinfo sinfo;
494         struct smb2_handle h1;
495         struct smb2_request *req1, *req2;
496
497         smb2_deltree(tree1, BASEDIR);
498         smb2_util_rmdir(tree1, BASEDIR);
499
500         torture_comment(torture, "TESTING CHANGE NOTIFY WITH RECURSION\n");
501
502         /*
503           get a handle on the directory
504         */
505         ZERO_STRUCT(io.smb2);
506         io.generic.level = RAW_OPEN_SMB2;
507         io.smb2.in.create_flags = 0;
508         io.smb2.in.desired_access = SEC_FILE_ALL;
509         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
510         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
511         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
512                                 NTCREATEX_SHARE_ACCESS_WRITE;
513         io.smb2.in.alloc_size = 0;
514         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
515         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
516         io.smb2.in.security_flags = 0;
517         io.smb2.in.fname = BASEDIR;
518
519         status = smb2_create(tree1, torture, &(io.smb2));
520         CHECK_STATUS(status, NT_STATUS_OK);
521         h1 = io.smb2.out.file.handle;
522
523         /* ask for a change notify, on file or directory name
524            changes. Setup both with and without recursion */
525         ZERO_STRUCT(notify.smb2);
526         notify.smb2.level = RAW_NOTIFY_SMB2;
527         notify.smb2.in.buffer_size = 1000;
528         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
529                                 FILE_NOTIFY_CHANGE_ATTRIBUTES |
530                                 FILE_NOTIFY_CHANGE_CREATION;
531         notify.smb2.in.file.handle = h1;
532
533         notify.smb2.in.recursive = true;
534         req1 = smb2_notify_send(tree1, &(notify.smb2));
535         smb2_cancel(req1);
536         status = smb2_notify_recv(req1, torture, &(notify.smb2));
537         CHECK_STATUS(status, NT_STATUS_CANCELLED);
538
539         notify.smb2.in.recursive = false;
540         req2 = smb2_notify_send(tree1, &(notify.smb2));
541         smb2_cancel(req2);
542         status = smb2_notify_recv(req2, torture, &(notify.smb2));
543         CHECK_STATUS(status, NT_STATUS_CANCELLED);
544
545         ZERO_STRUCT(io1.smb2);
546         io1.generic.level = RAW_OPEN_SMB2;
547         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
548         io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
549                                 SEC_RIGHTS_FILE_WRITE|
550                                 SEC_RIGHTS_FILE_ALL;
551         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
552         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
553         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
554                                 NTCREATEX_SHARE_ACCESS_WRITE |
555                                 NTCREATEX_SHARE_ACCESS_DELETE;
556         io1.smb2.in.alloc_size = 0;
557         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
558         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
559         io1.smb2.in.security_flags = 0;
560         io1.smb2.in.fname = BASEDIR "\\subdir-name";
561         status = smb2_create(tree2, torture, &(io1.smb2));
562         CHECK_STATUS(status, NT_STATUS_OK);
563         smb2_util_close(tree2, io1.smb2.out.file.handle);
564
565         io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname1";
566         status = smb2_create(tree2, torture, &(io1.smb2));
567         CHECK_STATUS(status, NT_STATUS_OK);
568         ZERO_STRUCT(sinfo);
569         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
570         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
571         sinfo.rename_information.in.overwrite = 0;
572         sinfo.rename_information.in.root_fid = 0;
573         sinfo.rename_information.in.new_name =
574                                 BASEDIR "\\subdir-name\\subname1-r";
575         status = smb2_setinfo_file(tree2, &sinfo);
576         CHECK_STATUS(status, NT_STATUS_OK);
577
578         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
579         io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname2";
580         status = smb2_create(tree2, torture, &(io1.smb2));
581         CHECK_STATUS(status, NT_STATUS_OK);
582         ZERO_STRUCT(sinfo);
583         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
584         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
585         sinfo.rename_information.in.overwrite = true;
586         sinfo.rename_information.in.root_fid = 0;
587         sinfo.rename_information.in.new_name = BASEDIR "\\subname2-r";
588         status = smb2_setinfo_file(tree2, &sinfo);
589         CHECK_STATUS(status, NT_STATUS_OK);
590
591         io1.smb2.in.fname = BASEDIR "\\subname2-r";
592         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
593         status = smb2_create(tree2, torture, &(io1.smb2));
594         CHECK_STATUS(status, NT_STATUS_OK);
595         ZERO_STRUCT(sinfo);
596         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
597         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
598         sinfo.rename_information.in.overwrite = true;
599         sinfo.rename_information.in.root_fid = 0;
600         sinfo.rename_information.in.new_name = BASEDIR "\\subname3-r";
601         status = smb2_setinfo_file(tree2, &sinfo);
602         CHECK_STATUS(status, NT_STATUS_OK);
603
604         notify.smb2.in.completion_filter = 0;
605         notify.smb2.in.recursive = true;
606         smb_msleep(200);
607         req1 = smb2_notify_send(tree1, &(notify.smb2));
608
609         status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name\\subname1-r");
610         CHECK_STATUS(status, NT_STATUS_OK);
611         status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name");
612         CHECK_STATUS(status, NT_STATUS_OK);
613         status = smb2_util_unlink(tree2, BASEDIR "\\subname3-r");
614         CHECK_STATUS(status, NT_STATUS_OK);
615
616         notify.smb2.in.recursive = false;
617         req2 = smb2_notify_send(tree1, &(notify.smb2));
618
619         status = smb2_notify_recv(req1, torture, &(notify.smb2));
620         CHECK_STATUS(status, NT_STATUS_OK);
621
622         CHECK_VAL(notify.smb2.out.num_changes, 9);
623         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
624         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
625         CHECK_VAL(notify.smb2.out.changes[1].action, NOTIFY_ACTION_ADDED);
626         CHECK_WIRE_STR(notify.smb2.out.changes[1].name, "subdir-name\\subname1");
627         CHECK_VAL(notify.smb2.out.changes[2].action, NOTIFY_ACTION_OLD_NAME);
628         CHECK_WIRE_STR(notify.smb2.out.changes[2].name, "subdir-name\\subname1");
629         CHECK_VAL(notify.smb2.out.changes[3].action, NOTIFY_ACTION_NEW_NAME);
630         CHECK_WIRE_STR(notify.smb2.out.changes[3].name, "subdir-name\\subname1-r");
631         CHECK_VAL(notify.smb2.out.changes[4].action, NOTIFY_ACTION_ADDED);
632         CHECK_WIRE_STR(notify.smb2.out.changes[4].name, "subdir-name\\subname2");
633         CHECK_VAL(notify.smb2.out.changes[5].action, NOTIFY_ACTION_REMOVED);
634         CHECK_WIRE_STR(notify.smb2.out.changes[5].name, "subdir-name\\subname2");
635         CHECK_VAL(notify.smb2.out.changes[6].action, NOTIFY_ACTION_ADDED);
636         CHECK_WIRE_STR(notify.smb2.out.changes[6].name, "subname2-r");
637         CHECK_VAL(notify.smb2.out.changes[7].action, NOTIFY_ACTION_OLD_NAME);
638         CHECK_WIRE_STR(notify.smb2.out.changes[7].name, "subname2-r");
639         CHECK_VAL(notify.smb2.out.changes[8].action, NOTIFY_ACTION_NEW_NAME);
640         CHECK_WIRE_STR(notify.smb2.out.changes[8].name, "subname3-r");
641
642 done:
643         smb2_deltree(tree1, BASEDIR);
644         return ret;
645 }
646
647 /*
648    testing of change notify mask change
649 */
650
651 static bool torture_smb2_notify_mask_change(struct torture_context *torture,
652                                             struct smb2_tree *tree1,
653                                             struct smb2_tree *tree2)
654 {
655         bool ret = true;
656         NTSTATUS status;
657         union smb_notify notify;
658         union smb_open io, io1;
659         struct smb2_handle h1;
660         struct smb2_request *req1, *req2;
661         union smb_setfileinfo sinfo;
662
663         smb2_deltree(tree1, BASEDIR);
664         smb2_util_rmdir(tree1, BASEDIR);
665
666         torture_comment(torture, "TESTING CHANGE NOTIFY WITH MASK CHANGE\n");
667
668         /*
669           get a handle on the directory
670         */
671         ZERO_STRUCT(io.smb2);
672         io.generic.level = RAW_OPEN_SMB2;
673         io.smb2.in.create_flags = 0;
674         io.smb2.in.desired_access = SEC_FILE_ALL;
675         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
676         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
677         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
678                                 NTCREATEX_SHARE_ACCESS_WRITE;
679         io.smb2.in.alloc_size = 0;
680         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
681         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
682         io.smb2.in.security_flags = 0;
683         io.smb2.in.fname = BASEDIR;
684
685         status = smb2_create(tree1, torture, &(io.smb2));
686         CHECK_STATUS(status, NT_STATUS_OK);
687         h1 = io.smb2.out.file.handle;
688
689         /* ask for a change notify, on file or directory name
690            changes. Setup both with and without recursion */
691         ZERO_STRUCT(notify.smb2);
692         notify.smb2.level = RAW_NOTIFY_SMB2;
693         notify.smb2.in.buffer_size = 1000;
694         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
695         notify.smb2.in.file.handle = h1;
696
697         notify.smb2.in.recursive = true;
698         req1 = smb2_notify_send(tree1, &(notify.smb2));
699
700         smb2_cancel(req1);
701         status = smb2_notify_recv(req1, torture, &(notify.smb2));
702         CHECK_STATUS(status, NT_STATUS_CANCELLED);
703
704
705         notify.smb2.in.recursive = false;
706         req2 = smb2_notify_send(tree1, &(notify.smb2));
707
708         smb2_cancel(req2);
709         status = smb2_notify_recv(req2, torture, &(notify.smb2));
710         CHECK_STATUS(status, NT_STATUS_CANCELLED);
711
712         notify.smb2.in.recursive = true;
713         req1 = smb2_notify_send(tree1, &(notify.smb2));
714
715         /* Set to hidden then back again. */
716         ZERO_STRUCT(io1.smb2);
717         io1.generic.level = RAW_OPEN_SMB2;
718         io1.smb2.in.create_flags = 0;
719         io1.smb2.in.desired_access = SEC_RIGHTS_FILE_READ |
720                                 SEC_RIGHTS_FILE_WRITE|
721                                 SEC_RIGHTS_FILE_ALL;
722         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
723         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
724                                 NTCREATEX_SHARE_ACCESS_WRITE |
725                                 NTCREATEX_SHARE_ACCESS_DELETE;
726         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
727         io1.smb2.in.security_flags = 0;
728         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
729         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
730         io1.smb2.in.fname = BASEDIR "\\tname1";
731
732         smb2_util_close(tree1,
733                 custom_smb2_create(tree1, torture, &(io1.smb2)));
734         status = smb2_util_setatr(tree1, BASEDIR "\\tname1",
735                                 FILE_ATTRIBUTE_HIDDEN);
736         CHECK_STATUS(status, NT_STATUS_OK);
737         smb2_util_unlink(tree1, BASEDIR "\\tname1");
738
739         status = smb2_notify_recv(req1, torture, &(notify.smb2));
740         CHECK_STATUS(status, NT_STATUS_OK);
741
742         CHECK_VAL(notify.smb2.out.num_changes, 1);
743         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
744         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
745
746         /* Now try and change the mask to include other events.
747          * This should not work - once the mask is set on a directory
748          * h1 it seems to be fixed until the fnum is closed. */
749
750         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME |
751                                         FILE_NOTIFY_CHANGE_ATTRIBUTES |
752                                         FILE_NOTIFY_CHANGE_CREATION;
753         notify.smb2.in.recursive = true;
754         req1 = smb2_notify_send(tree1, &(notify.smb2));
755
756         notify.smb2.in.recursive = false;
757         req2 = smb2_notify_send(tree1, &(notify.smb2));
758
759         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
760         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
761         io1.smb2.in.fname = BASEDIR "\\subdir-name";
762         status = smb2_create(tree2, torture, &(io1.smb2));
763         CHECK_STATUS(status, NT_STATUS_OK);
764         smb2_util_close(tree2, io1.smb2.out.file.handle);
765
766         ZERO_STRUCT(sinfo);
767         io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname1";
768         io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
769         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
770         status = smb2_create(tree2, torture, &(io1.smb2));
771         CHECK_STATUS(status, NT_STATUS_OK);
772         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
773         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
774         sinfo.rename_information.in.overwrite = true;
775         sinfo.rename_information.in.root_fid = 0;
776         sinfo.rename_information.in.new_name =
777                                 BASEDIR "\\subdir-name\\subname1-r";
778         status = smb2_setinfo_file(tree2, &sinfo);
779         CHECK_STATUS(status, NT_STATUS_OK);
780
781         io1.smb2.in.fname = BASEDIR "\\subdir-name\\subname2";
782         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
783         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
784         status = smb2_create(tree2, torture, &(io1.smb2));
785         CHECK_STATUS(status, NT_STATUS_OK);
786         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
787         sinfo.rename_information.in.new_name = BASEDIR "\\subname2-r";
788         status = smb2_setinfo_file(tree2, &sinfo);
789         CHECK_STATUS(status, NT_STATUS_OK);
790         smb2_util_close(tree2, io1.smb2.out.file.handle);
791
792         io1.smb2.in.fname = BASEDIR "\\subname2-r";
793         io1.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
794         status = smb2_create(tree2, torture, &(io1.smb2));
795         CHECK_STATUS(status, NT_STATUS_OK);
796         sinfo.rename_information.in.file.handle = io1.smb2.out.file.handle;
797         sinfo.rename_information.in.new_name = BASEDIR "\\subname3-r";
798         status = smb2_setinfo_file(tree2, &sinfo);
799         CHECK_STATUS(status, NT_STATUS_OK);
800         smb2_util_close(tree2, io1.smb2.out.file.handle);
801
802         status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name\\subname1-r");
803         CHECK_STATUS(status, NT_STATUS_OK);
804         status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name");
805         CHECK_STATUS(status, NT_STATUS_OK);
806         status = smb2_util_unlink(tree2, BASEDIR "\\subname3-r");
807         CHECK_STATUS(status, NT_STATUS_OK);
808
809         status = smb2_notify_recv(req1, torture, &(notify.smb2));
810         CHECK_STATUS(status, NT_STATUS_OK);
811
812         CHECK_VAL(notify.smb2.out.num_changes, 1);
813         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
814         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname2-r");
815
816         status = smb2_notify_recv(req2, torture, &(notify.smb2));
817         CHECK_STATUS(status, NT_STATUS_OK);
818
819         CHECK_VAL(notify.smb2.out.num_changes, 1);
820         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
821         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subname3-r");
822
823         if (!ret) {
824                 goto done;
825         }
826
827 done:
828         smb2_deltree(tree1, BASEDIR);
829         return ret;
830 }
831
832 /*
833    testing of mask bits for change notify
834 */
835
836 static bool torture_smb2_notify_mask(struct torture_context *torture,
837                                      struct smb2_tree *tree1,
838                                      struct smb2_tree *tree2)
839 {
840         bool ret = true;
841         NTSTATUS status;
842         union smb_notify notify;
843         union smb_open io, io1;
844         struct smb2_handle h1, h2;
845         uint32_t mask;
846         int i;
847         char c = 1;
848         union smb_setfileinfo sinfo;
849
850         smb2_deltree(tree1, BASEDIR);
851         smb2_util_rmdir(tree1, BASEDIR);
852
853         torture_comment(torture, "TESTING CHANGE NOTIFY COMPLETION FILTERS\n");
854
855
856         /*
857           get a handle on the directory
858         */
859         ZERO_STRUCT(io.smb2);
860         io.generic.level = RAW_OPEN_SMB2;
861         io.smb2.in.create_flags = 0;
862         io.smb2.in.desired_access = SEC_FILE_ALL;
863         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
864         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
865         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
866                                 NTCREATEX_SHARE_ACCESS_WRITE;
867         io.smb2.in.alloc_size = 0;
868         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
869         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
870         io.smb2.in.security_flags = 0;
871         io.smb2.in.fname = BASEDIR;
872
873         ZERO_STRUCT(notify.smb2);
874         notify.smb2.level = RAW_NOTIFY_SMB2;
875         notify.smb2.in.buffer_size = 1000;
876         notify.smb2.in.recursive = true;
877
878 #define NOTIFY_MASK_TEST(test_name, setup, op, cleanup, Action, \
879                          expected, nchanges) \
880         do { \
881         do { for (mask=i=0;i<32;i++) { \
882                 struct smb2_request *req; \
883                 status = smb2_create(tree1, torture, &(io.smb2)); \
884                 CHECK_STATUS(status, NT_STATUS_OK); \
885                 h1 = io.smb2.out.file.handle; \
886                 setup \
887                 notify.smb2.in.file.handle = h1;        \
888                 notify.smb2.in.completion_filter = (1<<i); \
889                 /* cancel initial requests so the buffer is setup */    \
890                 req = smb2_notify_send(tree1, &(notify.smb2)); \
891                 smb2_cancel(req); \
892                 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
893                 CHECK_STATUS(status, NT_STATUS_CANCELLED); \
894                 /* send the change notify request */ \
895                 req = smb2_notify_send(tree1, &(notify.smb2)); \
896                 op \
897                 smb_msleep(200); smb2_cancel(req); \
898                 status = smb2_notify_recv(req, torture, &(notify.smb2)); \
899                 cleanup \
900                 smb2_util_close(tree1, h1); \
901                 if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) continue; \
902                 CHECK_STATUS(status, NT_STATUS_OK); \
903                 /* special case to cope with file rename behaviour */ \
904                 if (nchanges == 2 && notify.smb2.out.num_changes == 1 && \
905                     notify.smb2.out.changes[0].action == \
906                         NOTIFY_ACTION_MODIFIED && \
907                     ((expected) & FILE_NOTIFY_CHANGE_ATTRIBUTES) && \
908                     Action == NOTIFY_ACTION_OLD_NAME) { \
909                         torture_comment(torture, \
910                                 "(rename file special handling OK)\n"); \
911                 } else if (nchanges != notify.smb2.out.num_changes) { \
912                         torture_result(torture, TORTURE_FAIL, \
913                                "ERROR: nchanges=%d expected=%d "\
914                                "action=%d filter=0x%08x\n", \
915                                notify.smb2.out.num_changes, \
916                                nchanges, \
917                                notify.smb2.out.changes[0].action, \
918                                notify.smb2.in.completion_filter); \
919                         ret = false; \
920                 } else if (notify.smb2.out.changes[0].action != Action) { \
921                         torture_result(torture, TORTURE_FAIL, \
922                                "ERROR: nchanges=%d action=%d " \
923                                "expectedAction=%d filter=0x%08x\n", \
924                                notify.smb2.out.num_changes, \
925                                notify.smb2.out.changes[0].action, \
926                                Action, \
927                                notify.smb2.in.completion_filter); \
928                         ret = false; \
929                 } else if (strcmp(notify.smb2.out.changes[0].name.s, \
930                            "tname1") != 0) { \
931                         torture_result(torture, TORTURE_FAIL, \
932                                "ERROR: nchanges=%d action=%d " \
933                                "filter=0x%08x name=%s\n", \
934                                notify.smb2.out.num_changes, \
935                                notify.smb2.out.changes[0].action, \
936                                notify.smb2.in.completion_filter, \
937                                notify.smb2.out.changes[0].name.s);      \
938                         ret = false; \
939                 } \
940                 mask |= (1<<i); \
941         } \
942         } while (0); \
943         } while (0);
944
945         torture_comment(torture, "Testing mkdir\n");
946         NOTIFY_MASK_TEST("Testing mkdir",;,
947                          smb2_util_mkdir(tree2, BASEDIR "\\tname1");,
948                          smb2_util_rmdir(tree2, BASEDIR "\\tname1");,
949                          NOTIFY_ACTION_ADDED,
950                          FILE_NOTIFY_CHANGE_DIR_NAME, 1);
951
952         torture_comment(torture, "Testing create file\n");
953         ZERO_STRUCT(io1.smb2);
954         io1.generic.level = RAW_OPEN_SMB2;
955         io1.smb2.in.create_flags = 0;
956         io1.smb2.in.desired_access = SEC_FILE_ALL;
957         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
958         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
959                                 NTCREATEX_SHARE_ACCESS_WRITE;
960         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
961         io1.smb2.in.security_flags = 0;
962         io1.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
963         io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
964         io1.smb2.in.fname = BASEDIR "\\tname1";
965
966         NOTIFY_MASK_TEST("Testing create file",;,
967                          smb2_util_close(tree2, custom_smb2_create(tree2,
968                                                 torture, &(io1.smb2)));,
969                          smb2_util_unlink(tree2, BASEDIR "\\tname1");,
970                          NOTIFY_ACTION_ADDED,
971                          FILE_NOTIFY_CHANGE_FILE_NAME, 1);
972
973         torture_comment(torture, "Testing unlink\n");
974         NOTIFY_MASK_TEST("Testing unlink",
975                          smb2_util_close(tree2, custom_smb2_create(tree2,
976                                                 torture, &(io1.smb2)));,
977                          smb2_util_unlink(tree2, BASEDIR "\\tname1");,
978                          ;,
979                          NOTIFY_ACTION_REMOVED,
980                          FILE_NOTIFY_CHANGE_FILE_NAME, 1);
981
982         torture_comment(torture, "Testing rmdir\n");
983         NOTIFY_MASK_TEST("Testing rmdir",
984                          smb2_util_mkdir(tree2, BASEDIR "\\tname1");,
985                          smb2_util_rmdir(tree2, BASEDIR "\\tname1");,
986                          ;,
987                          NOTIFY_ACTION_REMOVED,
988                          FILE_NOTIFY_CHANGE_DIR_NAME, 1);
989
990         torture_comment(torture, "Testing rename file\n");
991         ZERO_STRUCT(sinfo);
992         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
993         sinfo.rename_information.in.file.handle = h1;
994         sinfo.rename_information.in.overwrite = true;
995         sinfo.rename_information.in.root_fid = 0;
996         sinfo.rename_information.in.new_name = BASEDIR "\\tname2";
997         NOTIFY_MASK_TEST("Testing rename file",
998                          smb2_util_close(tree2, custom_smb2_create(tree2,
999                                                 torture, &(io1.smb2)));,
1000                          smb2_setinfo_file(tree2, &sinfo);,
1001                          smb2_util_unlink(tree2, BASEDIR "\\tname2");,
1002                          NOTIFY_ACTION_OLD_NAME,
1003                          FILE_NOTIFY_CHANGE_FILE_NAME, 2);
1004
1005         torture_comment(torture, "Testing rename dir\n");
1006         ZERO_STRUCT(sinfo);
1007         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1008         sinfo.rename_information.in.file.handle = h1;
1009         sinfo.rename_information.in.overwrite = true;
1010         sinfo.rename_information.in.root_fid = 0;
1011         sinfo.rename_information.in.new_name = BASEDIR "\\tname2";
1012         NOTIFY_MASK_TEST("Testing rename dir",
1013                 smb2_util_mkdir(tree2, BASEDIR "\\tname1");,
1014                 smb2_setinfo_file(tree2, &sinfo);,
1015                 smb2_util_rmdir(tree2, BASEDIR "\\tname2");,
1016                 NOTIFY_ACTION_OLD_NAME,
1017                 FILE_NOTIFY_CHANGE_DIR_NAME, 2);
1018
1019         torture_comment(torture, "Testing set path attribute\n");
1020         NOTIFY_MASK_TEST("Testing set path attribute",
1021                 smb2_util_close(tree2, custom_smb2_create(tree2,
1022                                        torture, &(io.smb2)));,
1023                 smb2_util_setatr(tree2, BASEDIR "\\tname1",
1024                                  FILE_ATTRIBUTE_HIDDEN);,
1025                 smb2_util_unlink(tree2, BASEDIR "\\tname1");,
1026                 NOTIFY_ACTION_MODIFIED,
1027                 FILE_NOTIFY_CHANGE_ATTRIBUTES, 1);
1028
1029         torture_comment(torture, "Testing set path write time\n");
1030         ZERO_STRUCT(sinfo);
1031         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1032         sinfo.generic.in.file.handle = h1;
1033         sinfo.basic_info.in.write_time = 1000;
1034         NOTIFY_MASK_TEST("Testing set path write time",
1035                 smb2_util_close(tree2, custom_smb2_create(tree2,
1036                                        torture, &(io1.smb2)));,
1037                 smb2_setinfo_file(tree2, &sinfo);,
1038                 smb2_util_unlink(tree2, BASEDIR "\\tname1");,
1039                 NOTIFY_ACTION_MODIFIED,
1040                 FILE_NOTIFY_CHANGE_LAST_WRITE, 1);
1041
1042         if (torture_setting_bool(torture, "samba3", false)) {
1043                 torture_comment(torture,
1044                        "Samba3 does not yet support create times "
1045                        "everywhere\n");
1046         }
1047         else {
1048                 ZERO_STRUCT(sinfo);
1049                 sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1050                 sinfo.generic.in.file.handle = h1;
1051                 sinfo.basic_info.in.create_time = 0;
1052                 torture_comment(torture, "Testing set file create time\n");
1053                 NOTIFY_MASK_TEST("Testing set file create time",
1054                         smb2_create_complex_file(tree2,
1055                         BASEDIR "\\tname1", &h2);,
1056                         smb2_setinfo_file(tree2, &sinfo);,
1057                         (smb2_util_close(tree2, h2),
1058                          smb2_util_unlink(tree2, BASEDIR "\\tname1"));,
1059                         NOTIFY_ACTION_MODIFIED,
1060                         FILE_NOTIFY_CHANGE_CREATION, 1);
1061         }
1062
1063         ZERO_STRUCT(sinfo);
1064         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1065         sinfo.generic.in.file.handle = h1;
1066         sinfo.basic_info.in.access_time = 0;
1067         torture_comment(torture, "Testing set file access time\n");
1068         NOTIFY_MASK_TEST("Testing set file access time",
1069                 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);,
1070                 smb2_setinfo_file(tree2, &sinfo);,
1071                 (smb2_util_close(tree2, h2),
1072                 smb2_util_unlink(tree2, BASEDIR "\\tname1"));,
1073                 NOTIFY_ACTION_MODIFIED,
1074                 FILE_NOTIFY_CHANGE_LAST_ACCESS, 1);
1075
1076         ZERO_STRUCT(sinfo);
1077         sinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
1078         sinfo.generic.in.file.handle = h1;
1079         sinfo.basic_info.in.change_time = 0;
1080         torture_comment(torture, "Testing set file change time\n");
1081         NOTIFY_MASK_TEST("Testing set file change time",
1082                 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);,
1083                 smb2_setinfo_file(tree2, &sinfo);,
1084                 (smb2_util_close(tree2, h2),
1085                 smb2_util_unlink(tree2, BASEDIR "\\tname1"));,
1086                 NOTIFY_ACTION_MODIFIED,
1087                 0, 1);
1088
1089
1090         torture_comment(torture, "Testing write\n");
1091         NOTIFY_MASK_TEST("Testing write",
1092                 smb2_create_complex_file(tree2, BASEDIR "\\tname1", &h2);,
1093                 smb2_util_write(tree2, h2, &c, 10000, 1);,
1094                 (smb2_util_close(tree2, h2),
1095                 smb2_util_unlink(tree2, BASEDIR "\\tname1"));,
1096                 NOTIFY_ACTION_MODIFIED,
1097                 0, 1);
1098
1099 done:
1100         smb2_deltree(tree1, BASEDIR);
1101         return ret;
1102 }
1103
1104 /*
1105   basic testing of change notify on files
1106 */
1107 static bool torture_smb2_notify_file(struct torture_context *torture,
1108                                 struct smb2_tree *tree)
1109 {
1110         NTSTATUS status;
1111         bool ret = true;
1112         union smb_open io;
1113         union smb_close cl;
1114         union smb_notify notify;
1115         struct smb2_request *req;
1116         struct smb2_handle h1;
1117         const char *fname = BASEDIR "\\file.txt";
1118
1119         smb2_deltree(tree, BASEDIR);
1120         smb2_util_rmdir(tree, BASEDIR);
1121
1122         torture_comment(torture, "TESTING CHANGE NOTIFY ON FILES\n");
1123         status = torture_smb2_testdir(tree, BASEDIR, &h1);
1124         CHECK_STATUS(status, NT_STATUS_OK);
1125
1126         ZERO_STRUCT(io.smb2);
1127         io.generic.level = RAW_OPEN_SMB2;
1128         io.smb2.in.create_flags = 0;
1129         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1130         io.smb2.in.create_options = 0;
1131         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1132         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1133                                 NTCREATEX_SHARE_ACCESS_WRITE;
1134         io.smb2.in.alloc_size = 0;
1135         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1136         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1137         io.smb2.in.security_flags = 0;
1138         io.smb2.in.fname = fname;
1139         status = smb2_create(tree, torture, &(io.smb2));
1140         CHECK_STATUS(status, NT_STATUS_OK);
1141         h1 = io.smb2.out.file.handle;
1142
1143         /* ask for a change notify,
1144            on file or directory name changes */
1145         ZERO_STRUCT(notify.smb2);
1146         notify.smb2.level = RAW_NOTIFY_SMB2;
1147         notify.smb2.in.file.handle = h1;
1148         notify.smb2.in.buffer_size = 1000;
1149         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_STREAM_NAME;
1150         notify.smb2.in.recursive = false;
1151
1152         torture_comment(torture,
1153         "Testing if notifies on file handles are invalid (should be)\n");
1154
1155         req = smb2_notify_send(tree, &(notify.smb2));
1156         status = smb2_notify_recv(req, torture, &(notify.smb2));
1157         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1158
1159         ZERO_STRUCT(cl.smb2);
1160         cl.close.level = RAW_CLOSE_SMB2;
1161         cl.close.in.file.handle = h1;
1162         status = smb2_close(tree, &(cl.smb2));
1163         CHECK_STATUS(status, NT_STATUS_OK);
1164
1165         status = smb2_util_unlink(tree, fname);
1166         CHECK_STATUS(status, NT_STATUS_OK);
1167
1168 done:
1169         smb2_deltree(tree, BASEDIR);
1170         return ret;
1171 }
1172 /*
1173   basic testing of change notifies followed by a tdis
1174 */
1175
1176 static bool torture_smb2_notify_tree_disconnect(
1177                 struct torture_context *torture,
1178                 struct smb2_tree *tree)
1179 {
1180         bool ret = true;
1181         NTSTATUS status;
1182         union smb_notify notify;
1183         union smb_open io;
1184         struct smb2_handle h1;
1185         struct smb2_request *req;
1186
1187         smb2_deltree(tree, BASEDIR);
1188         smb2_util_rmdir(tree, BASEDIR);
1189
1190         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY "
1191                         "TREE-DISCONNECT\n");
1192
1193         /*
1194           get a handle on the directory
1195         */
1196         ZERO_STRUCT(io.smb2);
1197         io.generic.level = RAW_OPEN_SMB2;
1198         io.smb2.in.create_flags = 0;
1199         io.smb2.in.desired_access = SEC_FILE_ALL;
1200         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1201         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1202         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1203                                 NTCREATEX_SHARE_ACCESS_WRITE;
1204         io.smb2.in.alloc_size = 0;
1205         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1206         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1207         io.smb2.in.security_flags = 0;
1208         io.smb2.in.fname = BASEDIR;
1209
1210         status = smb2_create(tree, torture, &(io.smb2));
1211         CHECK_STATUS(status, NT_STATUS_OK);
1212         h1 = io.smb2.out.file.handle;
1213
1214         /* ask for a change notify,
1215            on file or directory name changes */
1216         ZERO_STRUCT(notify.smb2);
1217         notify.smb2.level = RAW_NOTIFY_SMB2;
1218         notify.smb2.in.buffer_size = 1000;
1219         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1220         notify.smb2.in.file.handle = h1;
1221         notify.smb2.in.recursive = true;
1222
1223         req = smb2_notify_send(tree, &(notify.smb2));
1224         smb2_cancel(req);
1225         status = smb2_notify_recv(req, torture, &(notify.smb2));
1226
1227         status = smb2_tdis(tree);
1228         CHECK_STATUS(status, NT_STATUS_OK);
1229
1230         req = smb2_notify_send(tree, &(notify.smb2));
1231
1232         smb2_notify_recv(req, torture, &(notify.smb2));
1233         CHECK_STATUS(status, NT_STATUS_OK);
1234         CHECK_VAL(notify.smb2.out.num_changes, 0);
1235
1236 done:
1237         smb2_deltree(tree, BASEDIR);
1238         return ret;
1239 }
1240
1241 /*
1242   basic testing of change notifies followed by a ulogoff
1243 */
1244
1245 static bool torture_smb2_notify_ulogoff(struct torture_context *torture,
1246                                 struct smb2_tree *tree1,
1247                                 struct smb2_tree *tree2)
1248 {
1249         bool ret = true;
1250         NTSTATUS status;
1251         union smb_notify notify;
1252         union smb_open io;
1253         struct smb2_handle h1;
1254         struct smb2_request *req;
1255
1256         smb2_deltree(tree1, BASEDIR);
1257         smb2_util_rmdir(tree1, BASEDIR);
1258
1259         torture_comment(torture, "TESTING CHANGE NOTIFY FOLLOWED BY ULOGOFF\n");
1260
1261         /*
1262           get a handle on the directory
1263         */
1264         ZERO_STRUCT(io.smb2);
1265         io.generic.level = RAW_OPEN_SMB2;
1266         io.smb2.in.create_flags = 0;
1267         io.smb2.in.desired_access = SEC_FILE_ALL;
1268         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1269         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1270         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1271                                 NTCREATEX_SHARE_ACCESS_WRITE;
1272         io.smb2.in.alloc_size = 0;
1273         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1274         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1275         io.smb2.in.security_flags = 0;
1276         io.smb2.in.fname = BASEDIR;
1277
1278         status = smb2_create(tree2, torture, &(io.smb2));
1279         CHECK_STATUS(status, NT_STATUS_OK);
1280
1281         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1282         status = smb2_create(tree2, torture, &(io.smb2));
1283         CHECK_STATUS(status, NT_STATUS_OK);
1284         h1 = io.smb2.out.file.handle;
1285
1286         /* ask for a change notify,
1287            on file or directory name changes */
1288         ZERO_STRUCT(notify.smb2);
1289         notify.smb2.level = RAW_NOTIFY_SMB2;
1290         notify.smb2.in.buffer_size = 1000;
1291         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1292         notify.smb2.in.file.handle = h1;
1293         notify.smb2.in.recursive = true;
1294
1295         req = smb2_notify_send(tree1, &(notify.smb2));
1296
1297         status = smb2_logoff(tree2->session);
1298         CHECK_STATUS(status, NT_STATUS_OK);
1299
1300         status = smb2_notify_recv(req, torture, &(notify.smb2));
1301         CHECK_VAL(notify.smb2.out.num_changes, 0);
1302
1303 done:
1304         smb2_deltree(tree1, BASEDIR);
1305         return ret;
1306 }
1307
1308 static void tcp_dis_handler(struct smb2_transport *t, void *p)
1309 {
1310         struct smb2_tree *tree = (struct smb2_tree *)p;
1311         smb2_transport_dead(tree->session->transport,
1312                         NT_STATUS_LOCAL_DISCONNECT);
1313         t = NULL;
1314         tree = NULL;
1315 }
1316
1317 /*
1318   basic testing of change notifies followed by tcp disconnect
1319 */
1320
1321 static bool torture_smb2_notify_tcp_disconnect(
1322                 struct torture_context *torture,
1323                 struct smb2_tree *tree)
1324 {
1325         bool ret = true;
1326         NTSTATUS status;
1327         union smb_notify notify;
1328         union smb_open io;
1329         struct smb2_handle h1;
1330         struct smb2_request *req;
1331
1332         smb2_deltree(tree, BASEDIR);
1333         smb2_util_rmdir(tree, BASEDIR);
1334
1335         torture_comment(torture,
1336                 "TESTING CHANGE NOTIFY FOLLOWED BY TCP DISCONNECT\n");
1337
1338         /*
1339           get a handle on the directory
1340         */
1341         ZERO_STRUCT(io.smb2);
1342         io.generic.level = RAW_OPEN_SMB2;
1343         io.smb2.in.create_flags = 0;
1344         io.smb2.in.desired_access = SEC_FILE_ALL;
1345         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1346         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1347         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1348                                 NTCREATEX_SHARE_ACCESS_WRITE;
1349         io.smb2.in.alloc_size = 0;
1350         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1351         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1352         io.smb2.in.security_flags = 0;
1353         io.smb2.in.fname = BASEDIR;
1354
1355         status = smb2_create(tree, torture, &(io.smb2));
1356         CHECK_STATUS(status, NT_STATUS_OK);
1357         h1 = io.smb2.out.file.handle;
1358
1359         /* ask for a change notify,
1360            on file or directory name changes */
1361         ZERO_STRUCT(notify.smb2);
1362         notify.smb2.level = RAW_NOTIFY_SMB2;
1363         notify.smb2.in.buffer_size = 1000;
1364         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1365         notify.smb2.in.file.handle = h1;
1366         notify.smb2.in.recursive = true;
1367
1368         req = smb2_notify_send(tree, &(notify.smb2));
1369         smb2_cancel(req);
1370         status = smb2_notify_recv(req, torture, &(notify.smb2));
1371         CHECK_STATUS(status, NT_STATUS_CANCELLED);
1372
1373         notify.smb2.in.recursive = true;
1374         req = smb2_notify_send(tree, &(notify.smb2));
1375         smb2_transport_idle_handler(tree->session->transport,
1376                                 tcp_dis_handler, 250, tree);
1377         tree = NULL;
1378         status = smb2_notify_recv(req, torture, &(notify.smb2));
1379         CHECK_STATUS(status, NT_STATUS_LOCAL_DISCONNECT);
1380
1381 done:
1382         return ret;
1383 }
1384
1385 /*
1386    test setting up two change notify requests on one handle
1387 */
1388
1389 static bool torture_smb2_notify_double(struct torture_context *torture,
1390                         struct smb2_tree *tree1,
1391                         struct smb2_tree *tree2)
1392 {
1393         bool ret = true;
1394         NTSTATUS status;
1395         union smb_notify notify;
1396         union smb_open io;
1397         struct smb2_handle h1;
1398         struct smb2_request *req1, *req2;
1399
1400         smb2_deltree(tree1, BASEDIR);
1401         smb2_util_rmdir(tree1, BASEDIR);
1402
1403         torture_comment(torture,
1404                 "TESTING CHANGE NOTIFY TWICE ON ONE DIRECTORY\n");
1405
1406         /*
1407           get a handle on the directory
1408         */
1409         ZERO_STRUCT(io.smb2);
1410         io.generic.level = RAW_OPEN_SMB2;
1411         io.smb2.in.create_flags = 0;
1412         io.smb2.in.desired_access = SEC_RIGHTS_FILE_READ|
1413                                 SEC_RIGHTS_FILE_WRITE|
1414                                 SEC_RIGHTS_FILE_ALL;
1415         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1416         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1417         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1418                                 NTCREATEX_SHARE_ACCESS_WRITE;
1419         io.smb2.in.alloc_size = 0;
1420         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1421         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1422         io.smb2.in.security_flags = 0;
1423         io.smb2.in.fname = BASEDIR;
1424
1425         status = smb2_create(tree1, torture, &(io.smb2));
1426         CHECK_STATUS(status, NT_STATUS_OK);
1427         h1 = io.smb2.out.file.handle;
1428
1429         /* ask for a change notify,
1430            on file or directory name changes */
1431         ZERO_STRUCT(notify.smb2);
1432         notify.smb2.level = RAW_NOTIFY_SMB2;
1433         notify.smb2.in.buffer_size = 1000;
1434         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1435         notify.smb2.in.file.handle = h1;
1436         notify.smb2.in.recursive = true;
1437
1438         req1 = smb2_notify_send(tree1, &(notify.smb2));
1439         smb2_cancel(req1);
1440         status = smb2_notify_recv(req1, torture, &(notify.smb2));
1441         CHECK_STATUS(status, NT_STATUS_CANCELLED);
1442
1443         req2 = smb2_notify_send(tree1, &(notify.smb2));
1444         smb2_cancel(req2);
1445         status = smb2_notify_recv(req2, torture, &(notify.smb2));
1446         CHECK_STATUS(status, NT_STATUS_CANCELLED);
1447
1448         smb2_util_mkdir(tree2, BASEDIR "\\subdir-name");
1449         req1 = smb2_notify_send(tree1, &(notify.smb2));
1450         req2 = smb2_notify_send(tree1, &(notify.smb2));
1451
1452         status = smb2_notify_recv(req1, torture, &(notify.smb2));
1453         CHECK_STATUS(status, NT_STATUS_OK);
1454         CHECK_VAL(notify.smb2.out.num_changes, 1);
1455         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1456
1457         smb2_util_mkdir(tree2, BASEDIR "\\subdir-name2");
1458
1459         status = smb2_notify_recv(req2, torture, &(notify.smb2));
1460         CHECK_STATUS(status, NT_STATUS_OK);
1461         CHECK_VAL(notify.smb2.out.num_changes, 1);
1462         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name2");
1463
1464 done:
1465         smb2_deltree(tree1, BASEDIR);
1466         return ret;
1467 }
1468
1469
1470 /*
1471    test multiple change notifies at different depths and with/without recursion
1472 */
1473
1474 static bool torture_smb2_notify_tree(struct torture_context *torture,
1475                              struct smb2_tree *tree)
1476 {
1477         bool ret = true;
1478         union smb_notify notify;
1479         union smb_open io;
1480         struct smb2_request *req;
1481         struct timeval tv;
1482         struct {
1483                 const char *path;
1484                 bool recursive;
1485                 uint32_t filter;
1486                 int expected;
1487                 struct smb2_handle h1;
1488                 int counted;
1489         } dirs[] = {
1490                 {BASEDIR "\\abc",               true, FILE_NOTIFY_CHANGE_NAME, 30 },
1491                 {BASEDIR "\\zqy",               true, FILE_NOTIFY_CHANGE_NAME, 8 },
1492                 {BASEDIR "\\atsy",              true, FILE_NOTIFY_CHANGE_NAME, 4 },
1493                 {BASEDIR "\\abc\\foo",          true,  FILE_NOTIFY_CHANGE_NAME, 2 },
1494                 {BASEDIR "\\abc\\blah",         true,  FILE_NOTIFY_CHANGE_NAME, 13 },
1495                 {BASEDIR "\\abc\\blah",         false, FILE_NOTIFY_CHANGE_NAME, 7 },
1496                 {BASEDIR "\\abc\\blah\\a",      true, FILE_NOTIFY_CHANGE_NAME, 2 },
1497                 {BASEDIR "\\abc\\blah\\b",      true, FILE_NOTIFY_CHANGE_NAME, 2 },
1498                 {BASEDIR "\\abc\\blah\\c",      true, FILE_NOTIFY_CHANGE_NAME, 2 },
1499                 {BASEDIR "\\abc\\fooblah",      true, FILE_NOTIFY_CHANGE_NAME, 2 },
1500                 {BASEDIR "\\zqy\\xx",           true, FILE_NOTIFY_CHANGE_NAME, 2 },
1501                 {BASEDIR "\\zqy\\yyy",          true, FILE_NOTIFY_CHANGE_NAME, 2 },
1502                 {BASEDIR "\\zqy\\..",           true, FILE_NOTIFY_CHANGE_NAME, 40 },
1503                 {BASEDIR,                       true, FILE_NOTIFY_CHANGE_NAME, 40 },
1504                 {BASEDIR,                       false,FILE_NOTIFY_CHANGE_NAME, 6 },
1505                 {BASEDIR "\\atsy",              false,FILE_NOTIFY_CHANGE_NAME, 4 },
1506                 {BASEDIR "\\abc",               true, FILE_NOTIFY_CHANGE_NAME, 24 },
1507                 {BASEDIR "\\abc",               false,FILE_NOTIFY_CHANGE_FILE_NAME, 0 },
1508                 {BASEDIR "\\abc",               true, FILE_NOTIFY_CHANGE_FILE_NAME, 0 },
1509                 {BASEDIR "\\abc",               true, FILE_NOTIFY_CHANGE_NAME, 24 },
1510         };
1511         int i;
1512         NTSTATUS status;
1513         bool all_done = false;
1514
1515         smb2_deltree(tree, BASEDIR);
1516         smb2_util_rmdir(tree, BASEDIR);
1517
1518         torture_comment(torture, "TESTING NOTIFY FOR DIFFERENT DEPTHS\n");
1519
1520         ZERO_STRUCT(io.smb2);
1521         io.generic.level = RAW_OPEN_SMB2;
1522         io.smb2.in.create_flags = 0;
1523         io.smb2.in.desired_access = SEC_FILE_ALL;
1524         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1525         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1526         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1527                                 NTCREATEX_SHARE_ACCESS_WRITE;
1528         io.smb2.in.alloc_size = 0;
1529         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1530         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1531         io.smb2.in.security_flags = 0;
1532         io.smb2.in.fname = BASEDIR;
1533         status = smb2_create(tree, torture, &(io.smb2));
1534         CHECK_STATUS(status, NT_STATUS_OK);
1535
1536         ZERO_STRUCT(notify.smb2);
1537         notify.smb2.level = RAW_NOTIFY_SMB2;
1538         notify.smb2.in.buffer_size = 20000;
1539
1540         /*
1541           setup the directory tree, and the notify buffer on each directory
1542         */
1543         for (i=0;i<ARRAY_SIZE(dirs);i++) {
1544                 io.smb2.in.fname = dirs[i].path;
1545                 status = smb2_create(tree, torture, &(io.smb2));
1546                 CHECK_STATUS(status, NT_STATUS_OK);
1547                 dirs[i].h1 = io.smb2.out.file.handle;
1548
1549                 notify.smb2.in.completion_filter = dirs[i].filter;
1550                 notify.smb2.in.file.handle = dirs[i].h1;
1551                 notify.smb2.in.recursive = dirs[i].recursive;
1552                 req = smb2_notify_send(tree, &(notify.smb2));
1553                 smb2_cancel(req);
1554                 status = smb2_notify_recv(req, torture, &(notify.smb2));
1555                 CHECK_STATUS(status, NT_STATUS_CANCELLED);
1556         }
1557
1558         /* trigger 2 events in each dir */
1559         for (i=0;i<ARRAY_SIZE(dirs);i++) {
1560                 char *path = talloc_asprintf(torture, "%s\\test.dir",
1561                                              dirs[i].path);
1562                 smb2_util_mkdir(tree, path);
1563                 smb2_util_rmdir(tree, path);
1564                 talloc_free(path);
1565         }
1566
1567         /* give a bit of time for the events to propogate */
1568         tv = timeval_current();
1569
1570         do {
1571                 /* count events that have happened in each dir */
1572                 for (i=0;i<ARRAY_SIZE(dirs);i++) {
1573                         notify.smb2.in.file.handle = dirs[i].h1;
1574                         req = smb2_notify_send(tree, &(notify.smb2));
1575                         smb2_cancel(req);
1576                         notify.smb2.out.num_changes = 0;
1577                         status = smb2_notify_recv(req, torture,
1578                                  &(notify.smb2));
1579                         dirs[i].counted += notify.smb2.out.num_changes;
1580                 }
1581
1582                 all_done = true;
1583
1584                 for (i=0;i<ARRAY_SIZE(dirs);i++) {
1585                         if (dirs[i].counted != dirs[i].expected) {
1586                                 all_done = false;
1587                         }
1588                 }
1589         } while (!all_done && timeval_elapsed(&tv) < 20);
1590
1591         torture_comment(torture, "took %.4f seconds to propogate all events\n",
1592                         timeval_elapsed(&tv));
1593
1594         for (i=0;i<ARRAY_SIZE(dirs);i++) {
1595                 if (dirs[i].counted != dirs[i].expected) {
1596                         torture_comment(torture,
1597                                 "ERROR: i=%d expected %d got %d for '%s'\n",
1598                                 i, dirs[i].expected, dirs[i].counted,
1599                                 dirs[i].path);
1600                         ret = false;
1601                 }
1602         }
1603
1604         /*
1605           run from the back, closing and deleting
1606         */
1607         for (i=ARRAY_SIZE(dirs)-1;i>=0;i--) {
1608                 smb2_util_close(tree, dirs[i].h1);
1609                 smb2_util_rmdir(tree, dirs[i].path);
1610         }
1611
1612 done:
1613         smb2_deltree(tree, BASEDIR);
1614         smb2_util_rmdir(tree, BASEDIR);
1615         return ret;
1616 }
1617
1618 /*
1619    Test response when cached server events exceed single NT NOTFIY response
1620    packet size.
1621 */
1622
1623 static bool torture_smb2_notify_overflow(struct torture_context *torture,
1624                                 struct smb2_tree *tree)
1625 {
1626         bool ret = true;
1627         NTSTATUS status;
1628         union smb_notify notify;
1629         union smb_open io;
1630         struct smb2_handle h1, h2;
1631         int count = 100;
1632         struct smb2_request *req1;
1633         int i;
1634
1635         smb2_deltree(tree, BASEDIR);
1636         smb2_util_rmdir(tree, BASEDIR);
1637
1638         torture_comment(torture, "TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
1639
1640         /* get a handle on the directory */
1641         ZERO_STRUCT(io.smb2);
1642         io.generic.level = RAW_OPEN_SMB2;
1643         io.smb2.in.create_flags = 0;
1644         io.smb2.in.desired_access = SEC_FILE_ALL;
1645         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1646         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1647         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1648                             NTCREATEX_SHARE_ACCESS_WRITE;
1649         io.smb2.in.alloc_size = 0;
1650         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1651         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1652         io.smb2.in.security_flags = 0;
1653         io.smb2.in.fname = BASEDIR;
1654
1655         status = smb2_create(tree, torture, &(io.smb2));
1656         CHECK_STATUS(status, NT_STATUS_OK);
1657         h1 = io.smb2.out.file.handle;
1658
1659         /* ask for a change notify, on name changes. */
1660         ZERO_STRUCT(notify.smb2);
1661         notify.smb2.level = RAW_NOTIFY_NTTRANS;
1662         notify.smb2.in.buffer_size = 1000;
1663         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1664         notify.smb2.in.file.handle = h1;
1665
1666         notify.smb2.in.recursive = true;
1667         req1 = smb2_notify_send(tree, &(notify.smb2));
1668
1669         /* cancel initial requests so the buffer is setup */
1670         smb2_cancel(req1);
1671         status = smb2_notify_recv(req1, torture, &(notify.smb2));
1672         CHECK_STATUS(status, NT_STATUS_CANCELLED);
1673
1674         /* open a lot of files, filling up the server side notify buffer */
1675         torture_comment(torture,
1676                 "Testing overflowed buffer notify on create of %d files\n",
1677                 count);
1678
1679         for (i=0;i<count;i++) {
1680                 char *fname = talloc_asprintf(torture,
1681                               BASEDIR "\\test%d.txt", i);
1682                 union smb_open io1;
1683                 ZERO_STRUCT(io1.smb2);
1684                 io1.generic.level = RAW_OPEN_SMB2;
1685                 io1.smb2.in.create_flags = 0;
1686                 io1.smb2.in.desired_access = SEC_FILE_ALL;
1687                 io1.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1688                 io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1689                 io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1690                                     NTCREATEX_SHARE_ACCESS_WRITE;
1691                 io1.smb2.in.alloc_size = 0;
1692                 io1.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1693                 io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1694                 io1.smb2.in.security_flags = 0;
1695                 io1.smb2.in.fname = fname;
1696
1697                 h2 = custom_smb2_create(tree, torture, &(io1.smb2));
1698                 talloc_free(fname);
1699                 smb2_util_close(tree, h2);
1700         }
1701
1702         req1 = smb2_notify_send(tree, &(notify.smb2));
1703         status = smb2_notify_recv(req1, torture, &(notify.smb2));
1704         CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);
1705         CHECK_VAL(notify.smb2.out.num_changes, 0);
1706
1707 done:
1708         smb2_deltree(tree, BASEDIR);
1709         return ret;
1710 }
1711
1712 /*
1713    Test if notifications are returned for changes to the base directory.
1714    They shouldn't be.
1715 */
1716
1717 static bool torture_smb2_notify_basedir(struct torture_context *torture,
1718                                 struct smb2_tree *tree1,
1719                                 struct smb2_tree *tree2)
1720 {
1721         bool ret = true;
1722         NTSTATUS status;
1723         union smb_notify notify;
1724         union smb_open io;
1725         struct smb2_handle h1;
1726         struct smb2_request *req1;
1727
1728         smb2_deltree(tree1, BASEDIR);
1729         smb2_util_rmdir(tree1, BASEDIR);
1730
1731         torture_comment(torture, "TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
1732
1733         /* get a handle on the directory */
1734         ZERO_STRUCT(io.smb2);
1735         io.generic.level = RAW_OPEN_SMB2;
1736         io.smb2.in.create_flags = 0;
1737         io.smb2.in.desired_access = SEC_FILE_ALL;
1738         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1739         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1740         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1741             NTCREATEX_SHARE_ACCESS_WRITE;
1742         io.smb2.in.alloc_size = 0;
1743         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1744         io.smb2.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1745         io.smb2.in.security_flags = 0;
1746         io.smb2.in.fname = BASEDIR;
1747
1748         status = smb2_create(tree1, torture, &(io.smb2));
1749         CHECK_STATUS(status, NT_STATUS_OK);
1750         h1 = io.smb2.out.file.handle;
1751
1752         /* create a test file that will also be modified */
1753         io.smb2.in.fname = BASEDIR "\\tname1";
1754         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1755         status =  smb2_create(tree2, torture, &(io.smb2));
1756         CHECK_STATUS(status,NT_STATUS_OK);
1757         smb2_util_close(tree2, io.smb2.out.file.handle);
1758
1759         /* ask for a change notify, on attribute changes. */
1760         ZERO_STRUCT(notify.smb2);
1761         notify.smb2.level = RAW_NOTIFY_SMB2;
1762         notify.smb2.in.buffer_size = 1000;
1763         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
1764         notify.smb2.in.file.handle = h1;
1765         notify.smb2.in.recursive = true;
1766
1767         req1 = smb2_notify_send(tree1, &(notify.smb2));
1768
1769         /* set attribute on the base dir */
1770         smb2_util_setatr(tree2, BASEDIR, FILE_ATTRIBUTE_HIDDEN);
1771
1772         /* set attribute on a file to assure we receive a notification */
1773         smb2_util_setatr(tree2, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN);
1774         smb_msleep(200);
1775
1776         /* check how many responses were given, expect only 1 for the file */
1777         status = smb2_notify_recv(req1, torture, &(notify.smb2));
1778         CHECK_STATUS(status, NT_STATUS_OK);
1779         CHECK_VAL(notify.smb2.out.num_changes, 1);
1780         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
1781         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "tname1");
1782
1783 done:
1784         smb2_deltree(tree1, BASEDIR);
1785         return ret;
1786 }
1787
1788
1789 /*
1790   create a secondary tree connect - used to test for a bug in Samba3 messaging
1791   with change notify
1792 */
1793 static struct smb2_tree *secondary_tcon(struct smb2_tree *tree,
1794                                         struct torture_context *tctx)
1795 {
1796         NTSTATUS status;
1797         const char *share, *host;
1798         struct smb2_tree *tree1;
1799         union smb_tcon tcon;
1800
1801         share = torture_setting_string(tctx, "share", NULL);
1802         host  = torture_setting_string(tctx, "host", NULL);
1803
1804         torture_comment(tctx,
1805                 "create a second tree context on the same session\n");
1806         tree1 = smb2_tree_init(tree->session, tctx, false);
1807         if (tree1 == NULL) {
1808                 torture_comment(tctx, "Out of memory\n");
1809                 return NULL;
1810         }
1811
1812         ZERO_STRUCT(tcon.smb2);
1813         tcon.generic.level = RAW_TCON_SMB2;
1814         tcon.smb2.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
1815         status = smb2_tree_connect(tree, &(tcon.smb2));
1816         if (!NT_STATUS_IS_OK(status)) {
1817                 talloc_free(tree);
1818                 torture_comment(tctx,"Failed to create secondary tree\n");
1819                 return NULL;
1820         }
1821
1822         tree1->tid = tcon.smb2.out.tid;
1823         torture_comment(tctx,"tid1=%d tid2=%d\n", tree->tid, tree1->tid);
1824
1825         return tree1;
1826 }
1827
1828
1829 /*
1830    very simple change notify test
1831 */
1832 static bool torture_smb2_notify_tcon(struct torture_context *torture,
1833                                   struct smb2_tree *tree)
1834 {
1835         bool ret = true;
1836         NTSTATUS status;
1837         union smb_notify notify;
1838         union smb_open io;
1839         struct smb2_handle h1;
1840         struct smb2_request *req = NULL;
1841         struct smb2_tree *tree1 = NULL;
1842         const char *fname = BASEDIR "\\subdir-name";
1843
1844         smb2_deltree(tree, BASEDIR);
1845         smb2_util_rmdir(tree, BASEDIR);
1846
1847         torture_comment(torture, "TESTING SIMPLE CHANGE NOTIFY\n");
1848
1849         /*
1850           get a handle on the directory
1851         */
1852
1853         ZERO_STRUCT(io.smb2);
1854         io.generic.level = RAW_OPEN_SMB2;
1855         io.smb2.in.create_flags = 0;
1856         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1857         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1858         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL |
1859                                 FILE_ATTRIBUTE_DIRECTORY;
1860         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1861                                 NTCREATEX_SHARE_ACCESS_WRITE;
1862         io.smb2.in.alloc_size = 0;
1863         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1864         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1865         io.smb2.in.security_flags = 0;
1866         io.smb2.in.fname = BASEDIR;
1867
1868         status = smb2_create(tree, torture, &(io.smb2));
1869         CHECK_STATUS(status, NT_STATUS_OK);
1870         h1 = io.smb2.out.file.handle;
1871
1872         /* ask for a change notify,
1873            on file or directory name changes */
1874         ZERO_STRUCT(notify.smb2);
1875         notify.smb2.level = RAW_NOTIFY_SMB2;
1876         notify.smb2.in.buffer_size = 1000;
1877         notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
1878         notify.smb2.in.file.handle = h1;
1879         notify.smb2.in.recursive = true;
1880
1881         torture_comment(torture, "Testing notify mkdir\n");
1882         req = smb2_notify_send(tree, &(notify.smb2));
1883         smb2_cancel(req);
1884         status = smb2_notify_recv(req, torture, &(notify.smb2));
1885         CHECK_STATUS(status, NT_STATUS_CANCELLED);
1886
1887         notify.smb2.in.recursive = true;
1888         req = smb2_notify_send(tree, &(notify.smb2));
1889         status = smb2_util_mkdir(tree, fname);
1890         CHECK_STATUS(status, NT_STATUS_OK);
1891
1892         status = smb2_notify_recv(req, torture, &(notify.smb2));
1893         CHECK_STATUS(status, NT_STATUS_OK);
1894
1895         CHECK_VAL(notify.smb2.out.num_changes, 1);
1896         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
1897         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1898
1899         torture_comment(torture, "Testing notify rmdir\n");
1900         req = smb2_notify_send(tree, &(notify.smb2));
1901         status = smb2_util_rmdir(tree, fname);
1902         CHECK_STATUS(status, NT_STATUS_OK);
1903
1904         status = smb2_notify_recv(req, torture, &(notify.smb2));
1905         CHECK_STATUS(status, NT_STATUS_OK);
1906         CHECK_VAL(notify.smb2.out.num_changes, 1);
1907         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_REMOVED);
1908         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1909
1910         torture_comment(torture, "SIMPLE CHANGE NOTIFY OK\n");
1911
1912         torture_comment(torture, "TESTING WITH SECONDARY TCON\n");
1913         tree1 = secondary_tcon(tree, torture);
1914
1915         torture_comment(torture, "Testing notify mkdir\n");
1916         req = smb2_notify_send(tree, &(notify.smb2));
1917         smb2_util_mkdir(tree1, fname);
1918
1919         status = smb2_notify_recv(req, torture, &(notify.smb2));
1920         CHECK_STATUS(status, NT_STATUS_OK);
1921
1922         CHECK_VAL(notify.smb2.out.num_changes, 1);
1923         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
1924         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1925
1926         torture_comment(torture, "Testing notify rmdir\n");
1927         req = smb2_notify_send(tree, &(notify.smb2));
1928         smb2_util_rmdir(tree, fname);
1929
1930         status = smb2_notify_recv(req, torture, &(notify.smb2));
1931         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_REMOVED);
1934         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1935
1936         torture_comment(torture, "CHANGE NOTIFY WITH TCON OK\n");
1937
1938         torture_comment(torture, "Disconnecting secondary tree\n");
1939         status = smb2_tdis(tree1);
1940         CHECK_STATUS(status, NT_STATUS_OK);
1941         talloc_free(tree1);
1942
1943         torture_comment(torture, "Testing notify mkdir\n");
1944         req = smb2_notify_send(tree, &(notify.smb2));
1945         smb2_util_mkdir(tree, fname);
1946
1947         status = smb2_notify_recv(req, torture, &(notify.smb2));
1948         CHECK_STATUS(status, NT_STATUS_OK);
1949
1950         CHECK_VAL(notify.smb2.out.num_changes, 1);
1951         CHECK_VAL(notify.smb2.out.changes[0].action, NOTIFY_ACTION_ADDED);
1952         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1953
1954         torture_comment(torture, "Testing notify rmdir\n");
1955         req = smb2_notify_send(tree, &(notify.smb2));
1956         smb2_util_rmdir(tree, fname);
1957
1958         status = smb2_notify_recv(req, torture, &(notify.smb2));
1959         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_REMOVED);
1962         CHECK_WIRE_STR(notify.smb2.out.changes[0].name, "subdir-name");
1963
1964         torture_comment(torture, "CHANGE NOTIFY WITH TDIS OK\n");
1965 done:
1966         smb2_util_close(tree, h1);
1967         smb2_deltree(tree, BASEDIR);
1968
1969         return ret;
1970 }
1971
1972 /*
1973    basic testing of SMB2 change notify
1974 */
1975 struct torture_suite *torture_smb2_notify_init(void)
1976 {
1977         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "notify");
1978
1979         torture_suite_add_1smb2_test(suite, "valid-req", test_valid_request);
1980         torture_suite_add_1smb2_test(suite, "tcon", torture_smb2_notify_tcon);
1981         torture_suite_add_2smb2_test(suite, "dir", torture_smb2_notify_dir);
1982         torture_suite_add_2smb2_test(suite, "mask", torture_smb2_notify_mask);
1983         torture_suite_add_1smb2_test(suite, "tdis", torture_smb2_notify_tree_disconnect);
1984         torture_suite_add_2smb2_test(suite, "mask-change", torture_smb2_notify_mask_change);
1985         torture_suite_add_2smb2_test(suite, "logoff", torture_smb2_notify_ulogoff);
1986         torture_suite_add_1smb2_test(suite, "tree", torture_smb2_notify_tree);
1987         torture_suite_add_2smb2_test(suite, "basedir", torture_smb2_notify_basedir);
1988         torture_suite_add_2smb2_test(suite, "double", torture_smb2_notify_double);
1989         torture_suite_add_1smb2_test(suite, "file", torture_smb2_notify_file);
1990         torture_suite_add_1smb2_test(suite, "tcp", torture_smb2_notify_tcp_disconnect);
1991         torture_suite_add_2smb2_test(suite, "rec", torture_smb2_notify_recursive);
1992         torture_suite_add_1smb2_test(suite, "overflow", torture_smb2_notify_overflow);
1993
1994         suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests");
1995
1996         return suite;
1997 }
1998