2 * Unix SMB/CIFS implementation.
4 * test suite for SMB2 replay
6 * Copyright (C) Anubhav Rakshit 2014
7 * Copyright (C) Stefan Metzmacher 2014
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "../libcli/smb/smbXcli_base.h"
29 #include "oplock_break_handler.h"
30 #include "lib/events/events.h"
32 struct break_info break_info;
34 static void torture_oplock_ack_callback(struct smb2_request *req)
38 status = smb2_break_recv(req, &break_info.br);
39 if (!NT_STATUS_IS_OK(status)) {
40 break_info.failures++;
41 break_info.failure_status = status;
46 * A general oplock break notification handler. This should be used when a
47 * test expects to break from batch or exclusive to a lower level.
50 bool torture_oplock_ack_handler(struct smb2_transport *transport,
51 const struct smb2_handle *handle,
55 struct smb2_tree *tree = private_data;
57 struct smb2_request *req;
59 ZERO_STRUCT(break_info.br);
61 break_info.handle = *handle;
62 break_info.level = level;
66 case SMB2_OPLOCK_LEVEL_II:
69 case SMB2_OPLOCK_LEVEL_NONE:
74 break_info.failures++;
76 torture_comment(break_info.tctx,
77 "transport[%p] Acking to %s [0x%02X] in oplock handler\n",
78 transport, name, level);
80 break_info.br.in.file.handle = *handle;
81 break_info.br.in.oplock_level = level;
82 break_info.br.in.reserved = 0;
83 break_info.br.in.reserved2 = 0;
84 break_info.received_transport = tree->session->transport;
85 SMB_ASSERT(tree->session->transport == transport);
87 req = smb2_break_send(tree, &break_info.br);
88 req->async.fn = torture_oplock_ack_callback;
89 req->async.private_data = NULL;
95 * A oplock break handler designed to ignore incoming break requests.
96 * This is used when incoming oplock break requests need to be ignored
98 bool torture_oplock_ignore_handler(struct smb2_transport *transport,
99 const struct smb2_handle *handle,
100 uint8_t level, void *private_data)
106 * Timer handler function notifies the registering function that time is up
108 static void timeout_cb(struct tevent_context *ev,
109 struct tevent_timer *te,
110 struct timeval current_time,
113 bool *timesup = (bool *)private_data;
118 * Wait a short period of time to receive a single oplock break request
120 void torture_wait_for_oplock_break(struct torture_context *tctx)
122 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
123 struct tevent_timer *te = NULL;
125 bool timesup = false;
126 int old_count = break_info.count;
128 /* Wait 1 second for an oplock break */
129 ne = tevent_timeval_current_ofs(0, 1000000);
131 te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up);
133 torture_comment(tctx, "Failed to wait for an oplock break. "
134 "test results may not be accurate.");
138 while (!timesup && break_info.count < old_count + 1) {
139 if (tevent_loop_once(tctx->ev) != 0) {
140 torture_comment(tctx, "Failed to wait for an oplock "
141 "break. test results may not be "
148 /* We don't know if the timed event fired and was freed, we received
149 * our oplock break, or some other event triggered the loop. Thus,
150 * we create a tmp_ctx to be able to safely free/remove the timed
151 * event in all 3 cases.
153 talloc_free(tmp_ctx);