s4:torture/smb2/ioctl.c - quiet format specifier warnings on 32 bit
[obnox/samba/samba-obnox.git] / source4 / torture / smb2 / ioctl.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 ioctl operations
5
6    Copyright (C) David Disseldorp 2011
7
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.
12
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.
17
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/>.
20 */
21
22 #include "includes.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/gen_ndr/ndr_ioctl.h"
29
30 #define FNAME   "testfsctl.dat"
31 #define FNAME2  "testfsctl2.dat"
32
33 /*
34    basic testing of SMB2 shadow copy calls
35 */
36 static bool test_ioctl_get_shadow_copy(struct torture_context *torture,
37                                        struct smb2_tree *tree)
38 {
39         struct smb2_handle h;
40         uint8_t buf[100];
41         NTSTATUS status;
42         union smb_ioctl ioctl;
43         TALLOC_CTX *tmp_ctx = talloc_new(tree);
44
45         smb2_util_unlink(tree, FNAME);
46
47         status = torture_smb2_testfile(tree, FNAME, &h);
48         if (!NT_STATUS_IS_OK(status)) {
49                 printf("create write\n");
50                 return false;
51         }
52
53         ZERO_ARRAY(buf);
54         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
55         if (!NT_STATUS_IS_OK(status)) {
56                 printf("failed write\n");
57                 return false;
58         }
59
60         ZERO_STRUCT(ioctl);
61         ioctl.smb2.level = RAW_IOCTL_SMB2;
62         ioctl.smb2.in.file.handle = h;
63         ioctl.smb2.in.function = FSCTL_SRV_ENUM_SNAPS;
64         ioctl.smb2.in.max_response_size = 16;
65         ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
66
67         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
68         if (!NT_STATUS_IS_OK(status)) {
69                 printf("FSCTL_SRV_ENUM_SNAPS failed\n");
70                 return false;
71         }
72
73         return true;
74 }
75
76 /*
77    basic testing of the SMB2 server side copy ioctls
78 */
79 static bool test_ioctl_req_resume_key(struct torture_context *torture,
80                                       struct smb2_tree *tree)
81 {
82         struct smb2_handle h;
83         uint8_t buf[100];
84         NTSTATUS status;
85         union smb_ioctl ioctl;
86         TALLOC_CTX *tmp_ctx = talloc_new(tree);
87         struct req_resume_key_rsp res_key;
88         enum ndr_err_code ndr_ret;
89
90         smb2_util_unlink(tree, FNAME);
91
92         status = torture_smb2_testfile(tree, FNAME, &h);
93         if (!NT_STATUS_IS_OK(status)) {
94                 printf("create write\n");
95                 return false;
96         }
97
98         ZERO_ARRAY(buf);
99         status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
100         if (!NT_STATUS_IS_OK(status)) {
101                 printf("failed write\n");
102                 return false;
103         }
104
105         ZERO_STRUCT(ioctl);
106         ioctl.smb2.level = RAW_IOCTL_SMB2;
107         ioctl.smb2.in.file.handle = h;
108         ioctl.smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
109         ioctl.smb2.in.max_response_size = 32;
110         ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
111
112         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
113         if (!NT_STATUS_IS_OK(status)) {
114                 printf("FSCTL_SRV_REQUEST_RESUME_KEY failed\n");
115                 return false;
116         }
117
118         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx, &res_key,
119                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
120         if (ndr_ret != NDR_ERR_SUCCESS) {
121                 return false;
122         }
123
124         ndr_print_debug((ndr_print_fn_t)ndr_print_req_resume_key_rsp, "yo", &res_key);
125
126         talloc_free(tmp_ctx);
127         return true;
128 }
129
130 static uint64_t patt_hash(uint64_t off)
131 {
132         return off;
133 }
134
135 static bool check_pattern(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
136                           struct smb2_handle h, uint64_t off, uint64_t len,
137                           uint64_t patt_off)
138 {
139         uint64_t i;
140         struct smb2_read r;
141         NTSTATUS status;
142
143         ZERO_STRUCT(r);
144         r.in.file.handle = h;
145         r.in.length      = len;
146         r.in.offset      = off;
147         status = smb2_read(tree, mem_ctx, &r);
148         if (!NT_STATUS_IS_OK(status)) {
149                 printf("read failed - %s\n", nt_errstr(status));
150                 return false;
151         } else if (len != r.out.data.length) {
152                 printf("read data len mismatch got %zu, expected %llu\n",
153                        r.out.data.length, (unsigned long long)len);
154                 return false;
155         }
156
157         for (i = 0; i <= len - 8; i += 8, patt_off += 8) {
158                 if (BVAL(r.out.data.data, i) != patt_hash(patt_off)) {
159                         printf("pattern bad at %llu, got %llx, expected %llx\n",
160                                (unsigned long long)i,
161                                (unsigned long long)BVAL(r.out.data.data, i),
162                                (unsigned long long)patt_hash(patt_off));
163                         return false;
164                 }
165         }
166
167         talloc_free(r.out.data.data);
168         return true;
169 }
170
171 static bool test_setup_copy_chunk(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
172                                   uint32_t nchunks,
173                                   struct smb2_handle *src_h,
174                                   uint64_t src_size,
175                                   struct smb2_handle *dest_h,
176                                   uint64_t dest_size,
177                                   struct srv_copychunk_copy *cc_copy,
178                                   union smb_ioctl *ioctl)
179 {
180         struct req_resume_key_rsp res_key;
181         NTSTATUS status;
182         enum ndr_err_code ndr_ret;
183         uint64_t i;
184         uint8_t *buf = talloc_zero_size(mem_ctx, MAX(src_size, dest_size));
185         if (buf == NULL) {
186                 printf("no mem for file data buffer\n");
187                 return false;
188         }
189
190         smb2_util_unlink(tree, FNAME);
191         smb2_util_unlink(tree, FNAME2);
192
193         status = torture_smb2_testfile(tree, FNAME, src_h);
194         if (!NT_STATUS_IS_OK(status)) {
195                 printf("create write\n");
196                 return false;
197         }
198
199         if (src_size > 0) {
200                 for (i = 0; i <= src_size - 8; i += 8) {
201                         SBVAL(buf, i, patt_hash(i));
202                 }
203                 status = smb2_util_write(tree, *src_h, buf, 0, src_size);
204                 if (!NT_STATUS_IS_OK(status)) {
205                         printf("failed src write\n");
206                         return false;
207                 }
208         }
209
210         status = torture_smb2_testfile(tree, FNAME2, dest_h);
211         if (!NT_STATUS_IS_OK(status)) {
212                 printf("create write\n");
213                 return false;
214         }
215
216         if (dest_size > 0) {
217                 for (i = 0; i <= src_size - 8; i += 8) {
218                         SBVAL(buf, i, patt_hash(i));
219                 }
220                 status = smb2_util_write(tree, *dest_h, buf, 0, dest_size);
221                 if (!NT_STATUS_IS_OK(status)) {
222                         printf("failed dest write\n");
223                         return false;
224                 }
225         }
226
227         ZERO_STRUCTPN(ioctl);
228         ioctl->smb2.level = RAW_IOCTL_SMB2;
229         ioctl->smb2.in.file.handle = *src_h;
230         ioctl->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
231         /* Allow for Key + ContextLength + Context */
232         ioctl->smb2.in.max_response_size = 32;
233         ioctl->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
234
235         status = smb2_ioctl(tree, mem_ctx, &ioctl->smb2);
236         if (!NT_STATUS_IS_OK(status)) {
237                 printf("FSCTL_SRV_REQUEST_RESUME_KEY failed\n");
238                 return false;
239         }
240
241         ndr_ret = ndr_pull_struct_blob(&ioctl->smb2.out.out, mem_ctx, &res_key,
242                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
243         if (ndr_ret != NDR_ERR_SUCCESS) {
244                 return false;
245         }
246
247         ZERO_STRUCTPN(ioctl);
248         ioctl->smb2.level = RAW_IOCTL_SMB2;
249         ioctl->smb2.in.file.handle = *dest_h;
250         ioctl->smb2.in.function = FSCTL_SRV_COPYCHUNK;
251         ioctl->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
252         ioctl->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
253
254         ZERO_STRUCTPN(cc_copy);
255         memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
256         cc_copy->chunk_count = nchunks;
257         cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
258         if (cc_copy->chunks == NULL) {
259                 printf("not enough memory to allocate %u chunks\n", nchunks);
260                 return false;
261         }
262
263         return true;
264 }
265
266
267 static bool check_copy_chunk_rsp(struct srv_copychunk_rsp *cc_rsp,
268                                  uint32_t ex_chunks_written,
269                                  uint32_t ex_chunk_bytes_written,
270                                  uint32_t ex_total_bytes_written)
271 {
272         if (cc_rsp->chunks_written != ex_chunks_written) {
273                 printf("expected %u chunks, got %u\n",
274                        ex_chunks_written, cc_rsp->chunks_written);
275                 return false;
276         }
277         if (cc_rsp->chunk_bytes_written != ex_chunk_bytes_written) {
278                 printf("expected %u chunk bytes remaining, got %u\n",
279                        ex_chunk_bytes_written, cc_rsp->chunk_bytes_written);
280                 return false;
281         }
282         if (cc_rsp->total_bytes_written != ex_total_bytes_written) {
283                 printf("expected %u total bytes, got %u\n",
284                        ex_total_bytes_written, cc_rsp->total_bytes_written);
285                 return false;
286         }
287         return true;
288 }
289
290 static bool test_ioctl_copy_chunk_simple(struct torture_context *torture,
291                                          struct smb2_tree *tree)
292 {
293         struct smb2_handle src_h;
294         struct smb2_handle dest_h;
295         NTSTATUS status;
296         union smb_ioctl ioctl;
297         TALLOC_CTX *tmp_ctx = talloc_new(tree);
298         struct srv_copychunk_copy cc_copy;
299         struct srv_copychunk_rsp cc_rsp;
300         enum ndr_err_code ndr_ret;
301         bool ok;
302
303         ok = test_setup_copy_chunk(tree, tmp_ctx,
304                                    1, /* 1 chunk */
305                                    &src_h, 4096, /* fill 4096 byte src file */
306                                    &dest_h, 0,  /* 0 byte dest file */
307                                    &cc_copy,
308                                    &ioctl);
309         if (!ok) {
310                 return false;
311         }
312
313         /* copy all src file data (via a single chunk desc) */
314         cc_copy.chunks[0].source_off = 0;
315         cc_copy.chunks[0].target_off = 0;
316         cc_copy.chunks[0].length = 4096;
317
318         ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
319                                        &cc_copy,
320                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
321         if (ndr_ret != NDR_ERR_SUCCESS) {
322                 return false;
323         }
324
325         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
326         if (!NT_STATUS_IS_OK(status)) {
327                 printf("FSCTL_SRV_COPYCHUNK failed\n");
328                 return false;
329         }
330
331         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
332                                        &cc_rsp,
333                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
334         if (ndr_ret != NDR_ERR_SUCCESS) {
335                 return false;
336         }
337
338         ok = check_copy_chunk_rsp(&cc_rsp,
339                                   1,    /* chunks written */
340                                   0,    /* chunk bytes unsuccessfully written */
341                                   4096); /* total bytes written */
342         if (!ok) {
343                 return false;
344         }
345
346         ok = check_pattern(tree, tmp_ctx, dest_h, 0, 4096, 0);
347         if (!ok) {
348                 return false;
349         }
350
351         smb2_util_close(tree, src_h);
352         smb2_util_close(tree, dest_h);
353         talloc_free(tmp_ctx);
354         return true;
355 }
356
357 static bool test_ioctl_copy_chunk_multi(struct torture_context *torture,
358                                         struct smb2_tree *tree)
359 {
360         struct smb2_handle src_h;
361         struct smb2_handle dest_h;
362         NTSTATUS status;
363         union smb_ioctl ioctl;
364         TALLOC_CTX *tmp_ctx = talloc_new(tree);
365         struct srv_copychunk_copy cc_copy;
366         struct srv_copychunk_rsp cc_rsp;
367         enum ndr_err_code ndr_ret;
368         bool ok;
369
370         ok = test_setup_copy_chunk(tree, tmp_ctx,
371                                    2, /* chunks */
372                                    &src_h, 8192, /* src file */
373                                    &dest_h, 0,  /* dest file */
374                                    &cc_copy,
375                                    &ioctl);
376         if (!ok) {
377                 return false;
378         }
379
380         /* copy all src file data via two chunks */
381         cc_copy.chunks[0].source_off = 0;
382         cc_copy.chunks[0].target_off = 0;
383         cc_copy.chunks[0].length = 4096;
384
385         cc_copy.chunks[1].source_off = 4096;
386         cc_copy.chunks[1].target_off = 4096;
387         cc_copy.chunks[1].length = 4096;
388
389         ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
390                                        &cc_copy,
391                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
392         if (ndr_ret != NDR_ERR_SUCCESS) {
393                 return false;
394         }
395
396         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
397         if (!NT_STATUS_IS_OK(status)) {
398                 printf("FSCTL_SRV_COPYCHUNK failed\n");
399                 return false;
400         }
401
402         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
403                                        &cc_rsp,
404                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
405         if (ndr_ret != NDR_ERR_SUCCESS) {
406                 return false;
407         }
408
409         ok = check_copy_chunk_rsp(&cc_rsp,
410                                   2,    /* chunks written */
411                                   0,    /* chunk bytes unsuccessfully written */
412                                   8192);        /* total bytes written */
413         if (!ok) {
414                 return false;
415         }
416
417         smb2_util_close(tree, src_h);
418         smb2_util_close(tree, dest_h);
419         talloc_free(tmp_ctx);
420         return true;
421 }
422
423 static bool test_ioctl_copy_chunk_tiny(struct torture_context *torture,
424                                        struct smb2_tree *tree)
425 {
426         struct smb2_handle src_h;
427         struct smb2_handle dest_h;
428         NTSTATUS status;
429         union smb_ioctl ioctl;
430         TALLOC_CTX *tmp_ctx = talloc_new(tree);
431         struct srv_copychunk_copy cc_copy;
432         struct srv_copychunk_rsp cc_rsp;
433         enum ndr_err_code ndr_ret;
434         bool ok;
435
436         ok = test_setup_copy_chunk(tree, tmp_ctx,
437                                    2, /* chunks */
438                                    &src_h, 100, /* src file */
439                                    &dest_h, 0,  /* dest file */
440                                    &cc_copy,
441                                    &ioctl);
442         if (!ok) {
443                 return false;
444         }
445
446         /* copy all src file data via two chunks, sub block size chunks */
447         cc_copy.chunks[0].source_off = 0;
448         cc_copy.chunks[0].target_off = 0;
449         cc_copy.chunks[0].length = 50;
450
451         cc_copy.chunks[1].source_off = 50;
452         cc_copy.chunks[1].target_off = 50;
453         cc_copy.chunks[1].length = 50;
454
455         ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
456                                        &cc_copy,
457                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
458         if (ndr_ret != NDR_ERR_SUCCESS) {
459                 return false;
460         }
461
462         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
463         if (!NT_STATUS_IS_OK(status)) {
464                 printf("FSCTL_SRV_COPYCHUNK failed\n");
465                 return false;
466         }
467
468         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
469                                        &cc_rsp,
470                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
471         if (ndr_ret != NDR_ERR_SUCCESS) {
472                 return false;
473         }
474
475         ok = check_copy_chunk_rsp(&cc_rsp,
476                                   2,    /* chunks written */
477                                   0,    /* chunk bytes unsuccessfully written */
478                                   100); /* total bytes written */
479         if (!ok) {
480                 return false;
481         }
482
483         ok = check_pattern(tree, tmp_ctx, dest_h, 0, 100, 0);
484         if (!ok) {
485                 return false;
486         }
487
488         smb2_util_close(tree, src_h);
489         smb2_util_close(tree, dest_h);
490         talloc_free(tmp_ctx);
491         return true;
492 }
493
494 static bool test_ioctl_copy_chunk_over(struct torture_context *torture,
495                                        struct smb2_tree *tree)
496 {
497         struct smb2_handle src_h;
498         struct smb2_handle dest_h;
499         NTSTATUS status;
500         union smb_ioctl ioctl;
501         TALLOC_CTX *tmp_ctx = talloc_new(tree);
502         struct srv_copychunk_copy cc_copy;
503         struct srv_copychunk_rsp cc_rsp;
504         enum ndr_err_code ndr_ret;
505         bool ok;
506
507         ok = test_setup_copy_chunk(tree, tmp_ctx,
508                                    2, /* chunks */
509                                    &src_h, 8192, /* src file */
510                                    &dest_h, 4096, /* dest file */
511                                    &cc_copy,
512                                    &ioctl);
513         if (!ok) {
514                 return false;
515         }
516
517         /* first chunk overwrites existing dest data */
518         cc_copy.chunks[0].source_off = 0;
519         cc_copy.chunks[0].target_off = 0;
520         cc_copy.chunks[0].length = 4096;
521
522         /* second chunk overwrites the first */
523         cc_copy.chunks[1].source_off = 4096;
524         cc_copy.chunks[1].target_off = 0;
525         cc_copy.chunks[1].length = 4096;
526
527         ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
528                                        &cc_copy,
529                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
530         if (ndr_ret != NDR_ERR_SUCCESS) {
531                 return false;
532         }
533
534         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
535         if (!NT_STATUS_IS_OK(status)) {
536                 printf("FSCTL_SRV_COPYCHUNK failed\n");
537                 return false;
538         }
539
540         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
541                                        &cc_rsp,
542                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
543         if (ndr_ret != NDR_ERR_SUCCESS) {
544                 return false;
545         }
546
547         ok = check_copy_chunk_rsp(&cc_rsp,
548                                   2,    /* chunks written */
549                                   0,    /* chunk bytes unsuccessfully written */
550                                   8192); /* total bytes written */
551         if (!ok) {
552                 return false;
553         }
554
555         ok = check_pattern(tree, tmp_ctx, dest_h, 0, 4096, 4096);
556         if (!ok) {
557                 return false;
558         }
559
560         smb2_util_close(tree, src_h);
561         smb2_util_close(tree, dest_h);
562         talloc_free(tmp_ctx);
563         return true;
564 }
565
566 static bool test_ioctl_copy_chunk_append(struct torture_context *torture,
567                                        struct smb2_tree *tree)
568 {
569         struct smb2_handle src_h;
570         struct smb2_handle dest_h;
571         NTSTATUS status;
572         union smb_ioctl ioctl;
573         TALLOC_CTX *tmp_ctx = talloc_new(tree);
574         struct srv_copychunk_copy cc_copy;
575         struct srv_copychunk_rsp cc_rsp;
576         enum ndr_err_code ndr_ret;
577         bool ok;
578
579         ok = test_setup_copy_chunk(tree, tmp_ctx,
580                                    2, /* chunks */
581                                    &src_h, 4096, /* src file */
582                                    &dest_h, 0,  /* dest file */
583                                    &cc_copy,
584                                    &ioctl);
585         if (!ok) {
586                 return false;
587         }
588
589         cc_copy.chunks[0].source_off = 0;
590         cc_copy.chunks[0].target_off = 0;
591         cc_copy.chunks[0].length = 4096;
592
593         /* second chunk appends the same data to the first */
594         cc_copy.chunks[1].source_off = 0;
595         cc_copy.chunks[1].target_off = 4096;
596         cc_copy.chunks[1].length = 4096;
597
598         ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
599                                        &cc_copy,
600                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
601         if (ndr_ret != NDR_ERR_SUCCESS) {
602                 return false;
603         }
604
605         status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
606         if (!NT_STATUS_IS_OK(status)) {
607                 printf("FSCTL_SRV_COPYCHUNK failed\n");
608                 return false;
609         }
610
611         ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
612                                        &cc_rsp,
613                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
614         if (ndr_ret != NDR_ERR_SUCCESS) {
615                 return false;
616         }
617
618         ok = check_copy_chunk_rsp(&cc_rsp,
619                                   2,    /* chunks written */
620                                   0,    /* chunk bytes unsuccessfully written */
621                                   8192); /* total bytes written */
622         if (!ok) {
623                 return false;
624         }
625
626         ok = check_pattern(tree, tmp_ctx, dest_h, 0, 4096, 0);
627         if (!ok) {
628                 return false;
629         }
630
631         ok = check_pattern(tree, tmp_ctx, dest_h, 4096, 4096, 0);
632         if (!ok) {
633                 return false;
634         }
635
636         smb2_util_close(tree, src_h);
637         smb2_util_close(tree, dest_h);
638         talloc_free(tmp_ctx);
639         return true;
640 }
641
642 /*
643    basic testing of SMB2 ioctls
644 */
645 struct torture_suite *torture_smb2_ioctl_init(void)
646 {
647         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "ioctl");
648
649         torture_suite_add_1smb2_test(suite, "shadow_copy",
650                                      test_ioctl_get_shadow_copy);
651         torture_suite_add_1smb2_test(suite, "req_resume_key",
652                                      test_ioctl_req_resume_key);
653         torture_suite_add_1smb2_test(suite, "copy_chunk_simple",
654                                      test_ioctl_copy_chunk_simple);
655         torture_suite_add_1smb2_test(suite, "copy_chunk_multi",
656                                      test_ioctl_copy_chunk_multi);
657         torture_suite_add_1smb2_test(suite, "copy_chunk_tiny",
658                                      test_ioctl_copy_chunk_tiny);
659         torture_suite_add_1smb2_test(suite, "copy_chunk_overwrite",
660                                      test_ioctl_copy_chunk_over);
661         torture_suite_add_1smb2_test(suite, "copy_chunk_append",
662                                      test_ioctl_copy_chunk_append);
663
664         suite->description = talloc_strdup(suite, "SMB2-IOCTL tests");
665
666         return suite;
667 }
668