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 98 : void torture_lease_break_callback(struct smb2_request *req) 35 : { 36 0 : NTSTATUS status; 37 : 38 98 : status = smb2_lease_break_ack_recv(req, &lease_break_info.lease_break_ack); 39 98 : if (!NT_STATUS_IS_OK(status)) 40 2 : lease_break_info.failures++; 41 : 42 98 : return; 43 : } 44 : 45 : /* a lease break request handler */ 46 258 : bool torture_lease_handler(struct smb2_transport *transport, 47 : const struct smb2_lease_break *lb, 48 : void *private_data) 49 : { 50 258 : struct smb2_tree *tree = private_data; 51 0 : struct smb2_lease_break_ack io; 52 0 : struct smb2_request *req; 53 258 : const char *action = NULL; 54 258 : char *ls = smb2_util_lease_state_string(lease_break_info.tctx, 55 258 : lb->new_lease_state); 56 : 57 258 : if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { 58 232 : action = "acking"; 59 : } else { 60 26 : action = "received"; 61 : } 62 : 63 258 : lease_break_info.lease_transport = transport; 64 258 : lease_break_info.lease_break = *lb; 65 258 : lease_break_info.count++; 66 : 67 258 : if (lease_break_info.lease_skip_ack) { 68 136 : torture_comment(lease_break_info.tctx, 69 : "transport[%p] Skip %s to %s in lease handler\n", 70 : transport, action, ls); 71 136 : return true; 72 : } 73 : 74 122 : torture_comment(lease_break_info.tctx, 75 : "transport[%p] %s to %s in lease handler\n", 76 : transport, action, ls); 77 : 78 122 : if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { 79 98 : ZERO_STRUCT(io); 80 98 : io.in.lease.lease_key = lb->current_lease.lease_key; 81 98 : io.in.lease.lease_state = lb->new_lease_state; 82 : 83 98 : req = smb2_lease_break_ack_send(tree, &io); 84 98 : req->async.fn = torture_lease_break_callback; 85 98 : req->async.private_data = NULL; 86 : } 87 : 88 122 : 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 512 : static void timeout_cb(struct tevent_context *ev, 107 : struct tevent_timer *te, 108 : struct timeval current_time, 109 : void *private_data) 110 : { 111 512 : bool *timesup = (bool *)private_data; 112 512 : *timesup = true; 113 512 : return; 114 : } 115 : 116 : /* 117 : Wait a short period of time to receive a single oplock break request 118 : */ 119 596 : void torture_wait_for_lease_break(struct torture_context *tctx) 120 : { 121 596 : TALLOC_CTX *tmp_ctx = talloc_new(NULL); 122 596 : struct tevent_timer *te = NULL; 123 0 : struct timeval ne; 124 596 : bool timesup = false; 125 596 : int old_count = lease_break_info.count; 126 : 127 : /* Wait 1 second for an lease break */ 128 596 : ne = tevent_timeval_current_ofs(0, 1000000); 129 : 130 596 : te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up); 131 596 : 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 596 : torture_comment(tctx, "Waiting for a potential lease break...\n"); 138 1539 : while (!timesup && lease_break_info.count < old_count + 1) { 139 943 : 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 596 : if (timesup) { 147 512 : torture_comment(tctx, "... waiting for a lease break timed out\n"); 148 : } else { 149 84 : torture_comment(tctx, "Got %u lease breaks\n", 150 84 : lease_break_info.count - old_count); 151 : } 152 : 153 596 : 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 596 : talloc_free(tmp_ctx); 159 : 160 596 : return; 161 : }