Backport FSCTL codes from master
[Samba.git] / source4 / torture / smb2 / compound.c
blob59ed9b1e613bd191f1c7dd2214a5bc1ada1702db
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 compounded requests
6 Copyright (C) Stefan Metzmacher 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
28 #define CHECK_STATUS(status, correct) do { \
29 if (!NT_STATUS_EQUAL(status, correct)) { \
30 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
31 nt_errstr(status), nt_errstr(correct)); \
32 ret = false; \
33 goto done; \
34 }} while (0)
36 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
37 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
39 static bool test_compound_related1(struct torture_context *tctx,
40 struct smb2_tree *tree)
42 struct smb2_handle hd;
43 struct smb2_create cr;
44 NTSTATUS status;
45 const char *fname = "compound_related1.dat";
46 struct smb2_close cl;
47 bool ret = true;
48 struct smb2_request *req[2];
49 uint32_t saved_tid = tree->tid;
50 uint64_t saved_uid = tree->session->uid;
52 smb2_transport_credits_ask_num(tree->session->transport, 2);
54 smb2_util_unlink(tree, fname);
56 smb2_transport_credits_ask_num(tree->session->transport, 1);
58 ZERO_STRUCT(cr);
59 cr.in.security_flags = 0x00;
60 cr.in.oplock_level = 0;
61 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
62 cr.in.create_flags = 0x00000000;
63 cr.in.reserved = 0x00000000;
64 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
65 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
66 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
67 NTCREATEX_SHARE_ACCESS_WRITE |
68 NTCREATEX_SHARE_ACCESS_DELETE;
69 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
70 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
71 NTCREATEX_OPTIONS_ASYNC_ALERT |
72 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
73 0x00200000;
74 cr.in.fname = fname;
76 smb2_transport_compound_start(tree->session->transport, 2);
78 req[0] = smb2_create_send(tree, &cr);
80 smb2_transport_compound_set_related(tree->session->transport, true);
82 hd.data[0] = UINT64_MAX;
83 hd.data[1] = UINT64_MAX;
85 ZERO_STRUCT(cl);
86 cl.in.file.handle = hd;
88 tree->tid = 0xFFFFFFFF;
89 tree->session->uid = UINT64_MAX;
91 req[1] = smb2_close_send(tree, &cl);
93 status = smb2_create_recv(req[0], tree, &cr);
94 CHECK_STATUS(status, NT_STATUS_OK);
95 status = smb2_close_recv(req[1], &cl);
96 CHECK_STATUS(status, NT_STATUS_OK);
98 tree->tid = saved_tid;
99 tree->session->uid = saved_uid;
101 smb2_util_unlink(tree, fname);
102 done:
103 return ret;
106 static bool test_compound_related2(struct torture_context *tctx,
107 struct smb2_tree *tree)
109 struct smb2_handle hd;
110 struct smb2_create cr;
111 NTSTATUS status;
112 const char *fname = "compound_related2.dat";
113 struct smb2_close cl;
114 bool ret = true;
115 struct smb2_request *req[5];
116 uint32_t saved_tid = tree->tid;
117 uint64_t saved_uid = tree->session->uid;
119 smb2_transport_credits_ask_num(tree->session->transport, 5);
121 smb2_util_unlink(tree, fname);
123 smb2_transport_credits_ask_num(tree->session->transport, 1);
125 ZERO_STRUCT(cr);
126 cr.in.security_flags = 0x00;
127 cr.in.oplock_level = 0;
128 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
129 cr.in.create_flags = 0x00000000;
130 cr.in.reserved = 0x00000000;
131 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
132 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
133 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
134 NTCREATEX_SHARE_ACCESS_WRITE |
135 NTCREATEX_SHARE_ACCESS_DELETE;
136 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
137 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
138 NTCREATEX_OPTIONS_ASYNC_ALERT |
139 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
140 0x00200000;
141 cr.in.fname = fname;
143 smb2_transport_compound_start(tree->session->transport, 5);
145 req[0] = smb2_create_send(tree, &cr);
147 hd.data[0] = UINT64_MAX;
148 hd.data[1] = UINT64_MAX;
150 smb2_transport_compound_set_related(tree->session->transport, true);
152 ZERO_STRUCT(cl);
153 cl.in.file.handle = hd;
154 tree->tid = 0xFFFFFFFF;
155 tree->session->uid = UINT64_MAX;
157 req[1] = smb2_close_send(tree, &cl);
158 req[2] = smb2_close_send(tree, &cl);
159 req[3] = smb2_close_send(tree, &cl);
160 req[4] = smb2_close_send(tree, &cl);
162 status = smb2_create_recv(req[0], tree, &cr);
163 CHECK_STATUS(status, NT_STATUS_OK);
164 status = smb2_close_recv(req[1], &cl);
165 CHECK_STATUS(status, NT_STATUS_OK);
166 status = smb2_close_recv(req[2], &cl);
167 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
168 status = smb2_close_recv(req[3], &cl);
169 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
170 status = smb2_close_recv(req[4], &cl);
171 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
173 tree->tid = saved_tid;
174 tree->session->uid = saved_uid;
176 smb2_util_unlink(tree, fname);
177 done:
178 return ret;
181 static bool test_compound_unrelated1(struct torture_context *tctx,
182 struct smb2_tree *tree)
184 struct smb2_handle hd;
185 struct smb2_create cr;
186 NTSTATUS status;
187 const char *fname = "compound_unrelated1.dat";
188 struct smb2_close cl;
189 bool ret = true;
190 struct smb2_request *req[5];
192 smb2_transport_credits_ask_num(tree->session->transport, 5);
194 smb2_util_unlink(tree, fname);
196 smb2_transport_credits_ask_num(tree->session->transport, 1);
198 ZERO_STRUCT(cr);
199 cr.in.security_flags = 0x00;
200 cr.in.oplock_level = 0;
201 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
202 cr.in.create_flags = 0x00000000;
203 cr.in.reserved = 0x00000000;
204 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
205 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
206 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
207 NTCREATEX_SHARE_ACCESS_WRITE |
208 NTCREATEX_SHARE_ACCESS_DELETE;
209 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
210 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
211 NTCREATEX_OPTIONS_ASYNC_ALERT |
212 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
213 0x00200000;
214 cr.in.fname = fname;
216 smb2_transport_compound_start(tree->session->transport, 5);
218 req[0] = smb2_create_send(tree, &cr);
220 hd.data[0] = UINT64_MAX;
221 hd.data[1] = UINT64_MAX;
223 ZERO_STRUCT(cl);
224 cl.in.file.handle = hd;
225 req[1] = smb2_close_send(tree, &cl);
226 req[2] = smb2_close_send(tree, &cl);
227 req[3] = smb2_close_send(tree, &cl);
228 req[4] = smb2_close_send(tree, &cl);
230 status = smb2_create_recv(req[0], tree, &cr);
231 CHECK_STATUS(status, NT_STATUS_OK);
232 status = smb2_close_recv(req[1], &cl);
233 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
234 status = smb2_close_recv(req[2], &cl);
235 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
236 status = smb2_close_recv(req[3], &cl);
237 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
238 status = smb2_close_recv(req[4], &cl);
239 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
241 smb2_util_unlink(tree, fname);
242 done:
243 return ret;
246 static bool test_compound_invalid1(struct torture_context *tctx,
247 struct smb2_tree *tree)
249 struct smb2_handle hd;
250 struct smb2_create cr;
251 NTSTATUS status;
252 const char *fname = "compound_invalid1.dat";
253 struct smb2_close cl;
254 bool ret = true;
255 struct smb2_request *req[2];
257 smb2_transport_credits_ask_num(tree->session->transport, 2);
259 smb2_util_unlink(tree, fname);
261 smb2_transport_credits_ask_num(tree->session->transport, 1);
263 ZERO_STRUCT(cr);
264 cr.in.security_flags = 0x00;
265 cr.in.oplock_level = 0;
266 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
267 cr.in.create_flags = 0x00000000;
268 cr.in.reserved = 0x00000000;
269 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
270 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
271 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
272 NTCREATEX_SHARE_ACCESS_WRITE |
273 NTCREATEX_SHARE_ACCESS_DELETE;
274 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
275 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
276 NTCREATEX_OPTIONS_ASYNC_ALERT |
277 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
278 0x00200000;
279 cr.in.fname = fname;
281 smb2_transport_compound_start(tree->session->transport, 2);
283 /* passing the first request with the related flag is invalid */
284 smb2_transport_compound_set_related(tree->session->transport, true);
286 req[0] = smb2_create_send(tree, &cr);
288 hd.data[0] = UINT64_MAX;
289 hd.data[1] = UINT64_MAX;
291 ZERO_STRUCT(cl);
292 cl.in.file.handle = hd;
293 req[1] = smb2_close_send(tree, &cl);
295 status = smb2_create_recv(req[0], tree, &cr);
296 /* TODO: check why this fails with --signing=required */
297 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
298 status = smb2_close_recv(req[1], &cl);
299 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
301 smb2_util_unlink(tree, fname);
302 done:
303 return ret;
306 static bool test_compound_invalid2(struct torture_context *tctx,
307 struct smb2_tree *tree)
309 struct smb2_handle hd;
310 struct smb2_create cr;
311 NTSTATUS status;
312 const char *fname = "compound_invalid2.dat";
313 struct smb2_close cl;
314 bool ret = true;
315 struct smb2_request *req[5];
316 uint32_t saved_tid = tree->tid;
317 uint64_t saved_uid = tree->session->uid;
319 smb2_transport_credits_ask_num(tree->session->transport, 5);
321 smb2_util_unlink(tree, fname);
323 smb2_transport_credits_ask_num(tree->session->transport, 1);
325 ZERO_STRUCT(cr);
326 cr.in.security_flags = 0x00;
327 cr.in.oplock_level = 0;
328 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
329 cr.in.create_flags = 0x00000000;
330 cr.in.reserved = 0x00000000;
331 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
332 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
333 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
334 NTCREATEX_SHARE_ACCESS_WRITE |
335 NTCREATEX_SHARE_ACCESS_DELETE;
336 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
337 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
338 NTCREATEX_OPTIONS_ASYNC_ALERT |
339 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
340 0x00200000;
341 cr.in.fname = fname;
343 smb2_transport_compound_start(tree->session->transport, 5);
345 req[0] = smb2_create_send(tree, &cr);
347 hd.data[0] = UINT64_MAX;
348 hd.data[1] = UINT64_MAX;
350 smb2_transport_compound_set_related(tree->session->transport, true);
352 ZERO_STRUCT(cl);
353 cl.in.file.handle = hd;
354 tree->tid = 0xFFFFFFFF;
355 tree->session->uid = UINT64_MAX;
357 req[1] = smb2_close_send(tree, &cl);
358 /* strange that this is not generating invalid parameter */
359 smb2_transport_compound_set_related(tree->session->transport, false);
360 req[2] = smb2_close_send(tree, &cl);
361 req[3] = smb2_close_send(tree, &cl);
362 smb2_transport_compound_set_related(tree->session->transport, true);
363 req[4] = smb2_close_send(tree, &cl);
365 status = smb2_create_recv(req[0], tree, &cr);
366 CHECK_STATUS(status, NT_STATUS_OK);
367 status = smb2_close_recv(req[1], &cl);
368 CHECK_STATUS(status, NT_STATUS_OK);
369 status = smb2_close_recv(req[2], &cl);
370 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
371 status = smb2_close_recv(req[3], &cl);
372 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
373 status = smb2_close_recv(req[4], &cl);
374 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
376 tree->tid = saved_tid;
377 tree->session->uid = saved_uid;
379 smb2_util_unlink(tree, fname);
380 done:
381 return ret;
384 static bool test_compound_invalid3(struct torture_context *tctx,
385 struct smb2_tree *tree)
387 struct smb2_handle hd;
388 struct smb2_create cr;
389 NTSTATUS status;
390 const char *fname = "compound_invalid3.dat";
391 struct smb2_close cl;
392 bool ret = true;
393 struct smb2_request *req[5];
395 smb2_transport_credits_ask_num(tree->session->transport, 5);
397 smb2_util_unlink(tree, fname);
399 smb2_transport_credits_ask_num(tree->session->transport, 1);
401 ZERO_STRUCT(cr);
402 cr.in.security_flags = 0x00;
403 cr.in.oplock_level = 0;
404 cr.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
405 cr.in.create_flags = 0x00000000;
406 cr.in.reserved = 0x00000000;
407 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
408 cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
409 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
410 NTCREATEX_SHARE_ACCESS_WRITE |
411 NTCREATEX_SHARE_ACCESS_DELETE;
412 cr.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
413 cr.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
414 NTCREATEX_OPTIONS_ASYNC_ALERT |
415 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
416 0x00200000;
417 cr.in.fname = fname;
419 smb2_transport_compound_start(tree->session->transport, 5);
421 req[0] = smb2_create_send(tree, &cr);
423 hd.data[0] = UINT64_MAX;
424 hd.data[1] = UINT64_MAX;
426 ZERO_STRUCT(cl);
427 cl.in.file.handle = hd;
428 req[1] = smb2_close_send(tree, &cl);
429 req[2] = smb2_close_send(tree, &cl);
430 /* flipping the related flag is invalid */
431 smb2_transport_compound_set_related(tree->session->transport, true);
432 req[3] = smb2_close_send(tree, &cl);
433 req[4] = smb2_close_send(tree, &cl);
435 status = smb2_create_recv(req[0], tree, &cr);
436 CHECK_STATUS(status, NT_STATUS_OK);
437 status = smb2_close_recv(req[1], &cl);
438 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
439 status = smb2_close_recv(req[2], &cl);
440 CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
441 status = smb2_close_recv(req[3], &cl);
442 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
443 status = smb2_close_recv(req[4], &cl);
444 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
446 smb2_util_unlink(tree, fname);
447 done:
448 return ret;
451 /* Send a compound request where we expect the last request (Create, Notify)
452 * to go asynchronous. This works against a Win7 server and the reply is
453 * sent in two different packets. */
454 static bool test_compound_interim1(struct torture_context *tctx,
455 struct smb2_tree *tree)
457 struct smb2_handle hd;
458 struct smb2_create cr;
459 NTSTATUS status = NT_STATUS_OK;
460 const char *dname = "compound_interim_dir";
461 struct smb2_notify nt;
462 bool ret = true;
463 struct smb2_request *req[2];
465 /* Win7 compound request implementation deviates substantially from the
466 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
467 * verifies the Windows behavior, not the general spec behavior. */
468 if (!TARGET_IS_WIN7(tctx) && !TARGET_IS_W2K8(tctx)) {
469 torture_skip(tctx, "Interim test is specific to Windows server "
470 "behavior.\n");
473 smb2_transport_credits_ask_num(tree->session->transport, 5);
475 smb2_deltree(tree, dname);
477 smb2_transport_credits_ask_num(tree->session->transport, 1);
479 ZERO_STRUCT(cr);
480 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
481 cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
482 cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
483 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
484 NTCREATEX_SHARE_ACCESS_WRITE |
485 NTCREATEX_SHARE_ACCESS_DELETE;
486 cr.in.create_disposition = NTCREATEX_DISP_CREATE;
487 cr.in.fname = dname;
489 smb2_transport_compound_start(tree->session->transport, 2);
491 req[0] = smb2_create_send(tree, &cr);
493 smb2_transport_compound_set_related(tree->session->transport, true);
495 hd.data[0] = UINT64_MAX;
496 hd.data[1] = UINT64_MAX;
498 ZERO_STRUCT(nt);
499 nt.in.recursive = true;
500 nt.in.buffer_size = 0x1000;
501 nt.in.file.handle = hd;
502 nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
503 nt.in.unknown = 0x00000000;
505 req[1] = smb2_notify_send(tree, &nt);
507 status = smb2_create_recv(req[0], tree, &cr);
508 CHECK_STATUS(status, NT_STATUS_OK);
510 smb2_cancel(req[1]);
511 status = smb2_notify_recv(req[1], tree, &nt);
512 CHECK_STATUS(status, NT_STATUS_CANCELLED);
514 smb2_util_close(tree, cr.out.file.handle);
516 smb2_deltree(tree, dname);
517 done:
518 return ret;
521 /* Send a compound request where we expect the middle request (Create, Notify,
522 * GetInfo) to go asynchronous. Against Win7 the sync request succeed while
523 * the async fails. All are returned in the same compound response. */
524 static bool test_compound_interim2(struct torture_context *tctx,
525 struct smb2_tree *tree)
527 struct smb2_handle hd;
528 struct smb2_create cr;
529 NTSTATUS status = NT_STATUS_OK;
530 const char *dname = "compound_interim_dir";
531 struct smb2_getinfo gf;
532 struct smb2_notify nt;
533 bool ret = true;
534 struct smb2_request *req[3];
536 /* Win7 compound request implementation deviates substantially from the
537 * SMB2 spec as noted in MS-SMB2 <159>, <162>. This, test currently
538 * verifies the Windows behavior, not the general spec behavior. */
539 if (!TARGET_IS_WIN7(tctx) && !TARGET_IS_W2K8(tctx)) {
540 torture_skip(tctx, "Interim test is specific to Windows server "
541 "behavior.\n");
544 smb2_transport_credits_ask_num(tree->session->transport, 5);
546 smb2_deltree(tree, dname);
548 smb2_transport_credits_ask_num(tree->session->transport, 1);
550 ZERO_STRUCT(cr);
551 cr.in.desired_access = SEC_RIGHTS_FILE_ALL;
552 cr.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
553 cr.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
554 cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
555 NTCREATEX_SHARE_ACCESS_WRITE |
556 NTCREATEX_SHARE_ACCESS_DELETE;
557 cr.in.create_disposition = NTCREATEX_DISP_CREATE;
558 cr.in.fname = dname;
560 smb2_transport_compound_start(tree->session->transport, 3);
562 req[0] = smb2_create_send(tree, &cr);
564 smb2_transport_compound_set_related(tree->session->transport, true);
566 hd.data[0] = UINT64_MAX;
567 hd.data[1] = UINT64_MAX;
569 ZERO_STRUCT(nt);
570 nt.in.recursive = true;
571 nt.in.buffer_size = 0x1000;
572 nt.in.file.handle = hd;
573 nt.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
574 nt.in.unknown = 0x00000000;
576 req[1] = smb2_notify_send(tree, &nt);
578 ZERO_STRUCT(gf);
579 gf.in.file.handle = hd;
580 gf.in.info_type = SMB2_GETINFO_FILE;
581 gf.in.info_class = 0x04; // FILE_BASIC_INFORMATION
582 gf.in.output_buffer_length = 0x1000;
583 gf.in.input_buffer_length = 0;
585 req[2] = smb2_getinfo_send(tree, &gf);
587 status = smb2_create_recv(req[0], tree, &cr);
588 CHECK_STATUS(status, NT_STATUS_OK);
590 status = smb2_notify_recv(req[1], tree, &nt);
591 CHECK_STATUS(status, NT_STATUS_INTERNAL_ERROR);
593 status = smb2_getinfo_recv(req[2], tree, &gf);
594 CHECK_STATUS(status, NT_STATUS_OK);
596 smb2_util_close(tree, cr.out.file.handle);
598 smb2_deltree(tree, dname);
599 done:
600 return ret;
603 struct torture_suite *torture_smb2_compound_init(void)
605 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "compound");
607 torture_suite_add_1smb2_test(suite, "related1", test_compound_related1);
608 torture_suite_add_1smb2_test(suite, "related2", test_compound_related2);
609 torture_suite_add_1smb2_test(suite, "unrelated1", test_compound_unrelated1);
610 torture_suite_add_1smb2_test(suite, "invalid1", test_compound_invalid1);
611 torture_suite_add_1smb2_test(suite, "invalid2", test_compound_invalid2);
612 torture_suite_add_1smb2_test(suite, "invalid3", test_compound_invalid3);
613 torture_suite_add_1smb2_test(suite, "interim1", test_compound_interim1);
614 torture_suite_add_1smb2_test(suite, "interim2", test_compound_interim2);
616 suite->description = talloc_strdup(suite, "SMB2-COMPOUND tests");
618 return suite;