Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : test suite for SMB2 leases
5 :
6 : Copyright (C) Zachary Loafman 2009
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 <tevent.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 "torture/util.h"
29 : #include "libcli/smb/smbXcli_base.h"
30 : #include "lease_break_handler.h"
31 :
32 : struct lease_break_info lease_break_info;
33 :
34 0 : void torture_lease_break_callback(struct smb2_request *req)
35 : {
36 : NTSTATUS status;
37 :
38 0 : status = smb2_lease_break_ack_recv(req, &lease_break_info.lease_break_ack);
39 0 : if (!NT_STATUS_IS_OK(status))
40 0 : lease_break_info.failures++;
41 :
42 0 : return;
43 : }
44 :
45 : /* a lease break request handler */
46 0 : bool torture_lease_handler(struct smb2_transport *transport,
47 : const struct smb2_lease_break *lb,
48 : void *private_data)
49 : {
50 0 : struct smb2_tree *tree = private_data;
51 : struct smb2_lease_break_ack io;
52 : struct smb2_request *req;
53 0 : const char *action = NULL;
54 0 : char *ls = smb2_util_lease_state_string(lease_break_info.tctx,
55 0 : lb->new_lease_state);
56 :
57 0 : if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
58 0 : action = "acking";
59 : } else {
60 0 : action = "received";
61 : }
62 :
63 0 : lease_break_info.lease_transport = transport;
64 0 : lease_break_info.lease_break = *lb;
65 0 : lease_break_info.count++;
66 :
67 0 : if (lease_break_info.lease_skip_ack) {
68 0 : torture_comment(lease_break_info.tctx,
69 : "transport[%p] Skip %s to %s in lease handler\n",
70 : transport, action, ls);
71 0 : return true;
72 : }
73 :
74 0 : torture_comment(lease_break_info.tctx,
75 : "transport[%p] %s to %s in lease handler\n",
76 : transport, action, ls);
77 :
78 0 : if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) {
79 0 : ZERO_STRUCT(io);
80 0 : io.in.lease.lease_key = lb->current_lease.lease_key;
81 0 : io.in.lease.lease_state = lb->new_lease_state;
82 :
83 0 : req = smb2_lease_break_ack_send(tree, &io);
84 0 : req->async.fn = torture_lease_break_callback;
85 0 : req->async.private_data = NULL;
86 : }
87 :
88 0 : return true;
89 : }
90 :
91 : /*
92 : * A lease break handler which ignores incoming lease break requests
93 : * To be used in cases where the client is expected to ignore incoming
94 : * lease break requests
95 : */
96 0 : bool torture_lease_ignore_handler(struct smb2_transport *transport,
97 : const struct smb2_lease_break *lb,
98 : void *private_data)
99 : {
100 0 : return true;
101 : }
102 :
103 : /*
104 : Timer handler function notifies the registering function that time is up
105 : */
106 0 : static void timeout_cb(struct tevent_context *ev,
107 : struct tevent_timer *te,
108 : struct timeval current_time,
109 : void *private_data)
110 : {
111 0 : bool *timesup = (bool *)private_data;
112 0 : *timesup = true;
113 0 : return;
114 : }
115 :
116 : /*
117 : Wait a short period of time to receive a single oplock break request
118 : */
119 0 : void torture_wait_for_lease_break(struct torture_context *tctx)
120 : {
121 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
122 0 : struct tevent_timer *te = NULL;
123 : struct timeval ne;
124 0 : bool timesup = false;
125 0 : int old_count = lease_break_info.count;
126 :
127 : /* Wait 1 second for an lease break */
128 0 : ne = tevent_timeval_current_ofs(0, 1000000);
129 :
130 0 : te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up);
131 0 : if (te == NULL) {
132 0 : torture_comment(tctx, "Failed to wait for an lease break. "
133 : "test results may not be accurate.\n");
134 0 : goto done;
135 : }
136 :
137 0 : torture_comment(tctx, "Waiting for a potential lease break...\n");
138 0 : while (!timesup && lease_break_info.count < old_count + 1) {
139 0 : if (tevent_loop_once(tctx->ev) != 0) {
140 0 : torture_comment(tctx, "Failed to wait for a lease "
141 : "break. test results may not be "
142 : "accurate.\n");
143 0 : goto done;
144 : }
145 : }
146 0 : if (timesup) {
147 0 : torture_comment(tctx, "... waiting for a lease break timed out\n");
148 : } else {
149 0 : torture_comment(tctx, "Got %u lease breaks\n",
150 0 : lease_break_info.count - old_count);
151 : }
152 :
153 0 : done:
154 : /* We don't know if the timed event fired and was freed, we received
155 : * our oplock break, or some other event triggered the loop. Thus,
156 : * we create a tmp_ctx to be able to safely free/remove the timed
157 : * event in all 3 cases. */
158 0 : talloc_free(tmp_ctx);
159 :
160 0 : return;
161 : }
|