s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[samba.git] / source3 / modules / vfs_delay_inject.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Samba VFS module for delay injection in VFS calls
4  *  Copyright (C) Ralph Boehme 2018
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "locking/share_mode_lock.h"
22 #include "smbd/smbd.h"
23 #include "lib/util/tevent_unix.h"
24 #include "lib/global_contexts.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_VFS
28
29 static void inject_delay(const char *vfs_func, vfs_handle_struct *handle)
30 {
31         int delay;
32
33         delay = lp_parm_int(SNUM(handle->conn), "delay_inject", vfs_func, 0);
34         if (delay == 0) {
35                 return;
36         }
37
38         DBG_DEBUG("Injected delay for [%s] of [%d] ms\n", vfs_func, delay);
39
40         smb_msleep(delay);
41 }
42
43 static int vfs_delay_inject_fntimes(vfs_handle_struct *handle,
44                                     files_struct *fsp,
45                                     struct smb_file_time *ft)
46 {
47         inject_delay("fntimes", handle);
48
49         return SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
50 }
51
52 struct vfs_delay_inject_pread_state {
53         struct tevent_context *ev;
54         struct vfs_handle_struct *handle;
55         struct files_struct *fsp;
56         void *data;
57         size_t n;
58         off_t offset;
59         ssize_t ret;
60         struct vfs_aio_state vfs_aio_state;
61 };
62
63 static void vfs_delay_inject_pread_wait_done(struct tevent_req *subreq);
64 static void vfs_delay_inject_pread_done(struct tevent_req *subreq);
65
66 static struct tevent_req *vfs_delay_inject_pread_send(
67                                 struct vfs_handle_struct *handle,
68                                 TALLOC_CTX *mem_ctx,
69                                 struct tevent_context *ev,
70                                 struct files_struct *fsp,
71                                 void *data,
72                                 size_t n,
73                                 off_t offset)
74 {
75         struct tevent_req *req = NULL, *subreq = NULL;
76         struct vfs_delay_inject_pread_state *state = NULL;
77         int delay;
78         struct timeval delay_tv;
79
80         delay = lp_parm_int(
81                 SNUM(handle->conn), "delay_inject", "pread_send", 0);
82         delay_tv = tevent_timeval_current_ofs(delay / 1000,
83                                               (delay * 1000) % 1000000);
84
85         req = tevent_req_create(mem_ctx, &state,
86                                 struct vfs_delay_inject_pread_state);
87         if (req == NULL) {
88                 return NULL;
89         }
90         *state = (struct vfs_delay_inject_pread_state) {
91                 .ev = ev,
92                 .handle = handle,
93                 .fsp = fsp,
94                 .data = data,
95                 .n = n,
96                 .offset = offset,
97         };
98
99         if (delay == 0) {
100                 subreq = SMB_VFS_NEXT_PREAD_SEND(state,
101                                                  state->ev,
102                                                  state->handle,
103                                                  state->fsp,
104                                                  state->data,
105                                                  state->n,
106                                                  state->offset);
107                 if (tevent_req_nomem(subreq, req)) {
108                         return tevent_req_post(req, ev);
109                 }
110                 tevent_req_set_callback(subreq,
111                                         vfs_delay_inject_pread_done,
112                                         req);
113                 return req;
114         }
115
116         subreq = tevent_wakeup_send(state, ev, delay_tv);
117         if (tevent_req_nomem(subreq, req)) {
118                 return tevent_req_post(req, ev);
119         }
120         tevent_req_set_callback(subreq, vfs_delay_inject_pread_wait_done, req);
121         return req;
122 }
123
124
125 static void vfs_delay_inject_pread_wait_done(struct tevent_req *subreq)
126 {
127         struct tevent_req *req = tevent_req_callback_data(
128                 subreq, struct tevent_req);
129         struct vfs_delay_inject_pread_state *state = tevent_req_data(
130                 req, struct vfs_delay_inject_pread_state);
131         bool ok;
132
133         ok = tevent_wakeup_recv(subreq);
134         TALLOC_FREE(subreq);
135         if (!ok) {
136                 tevent_req_error(req, EIO);
137                 return;
138         }
139
140         subreq = SMB_VFS_NEXT_PREAD_SEND(state,
141                                          state->ev,
142                                          state->handle,
143                                          state->fsp,
144                                          state->data,
145                                          state->n,
146                                          state->offset);
147         if (tevent_req_nomem(subreq, req)) {
148                 return;
149         }
150         tevent_req_set_callback(subreq, vfs_delay_inject_pread_done, req);
151 }
152
153 static void vfs_delay_inject_pread_done(struct tevent_req *subreq)
154 {
155         struct tevent_req *req = tevent_req_callback_data(
156                 subreq, struct tevent_req);
157         struct vfs_delay_inject_pread_state *state = tevent_req_data(
158                 req, struct vfs_delay_inject_pread_state);
159
160         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
161         TALLOC_FREE(subreq);
162
163         tevent_req_done(req);
164 }
165
166 static ssize_t vfs_delay_inject_pread_recv(struct tevent_req *req,
167                                 struct vfs_aio_state *vfs_aio_state)
168 {
169         struct vfs_delay_inject_pread_state *state = tevent_req_data(
170                 req, struct vfs_delay_inject_pread_state);
171
172         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
173                 return -1;
174         }
175
176         *vfs_aio_state = state->vfs_aio_state;
177         return state->ret;
178 }
179
180 struct vfs_delay_inject_pwrite_state {
181         struct tevent_context *ev;
182         struct vfs_handle_struct *handle;
183         struct files_struct *fsp;
184         const void *data;
185         size_t n;
186         off_t offset;
187         ssize_t ret;
188         struct vfs_aio_state vfs_aio_state;
189 };
190
191 static void vfs_delay_inject_pwrite_wait_done(struct tevent_req *subreq);
192 static void vfs_delay_inject_pwrite_done(struct tevent_req *subreq);
193
194 static struct tevent_req *vfs_delay_inject_pwrite_send(
195                                 struct vfs_handle_struct *handle,
196                                 TALLOC_CTX *mem_ctx,
197                                 struct tevent_context *ev,
198                                 struct files_struct *fsp,
199                                 const void *data,
200                                 size_t n,
201                                 off_t offset)
202 {
203         struct tevent_req *req = NULL, *subreq = NULL;
204         struct vfs_delay_inject_pwrite_state *state = NULL;
205         int delay;
206         struct timeval delay_tv;
207
208         delay = lp_parm_int(
209                 SNUM(handle->conn), "delay_inject", "pwrite_send", 0);
210         delay_tv = tevent_timeval_current_ofs(delay / 1000,
211                                               (delay * 1000) % 1000000);
212
213         req = tevent_req_create(mem_ctx, &state,
214                                 struct vfs_delay_inject_pwrite_state);
215         if (req == NULL) {
216                 return NULL;
217         }
218         *state = (struct vfs_delay_inject_pwrite_state) {
219                 .ev = ev,
220                 .handle = handle,
221                 .fsp = fsp,
222                 .data = data,
223                 .n = n,
224                 .offset = offset,
225         };
226
227         if (delay == 0) {
228                 subreq = SMB_VFS_NEXT_PWRITE_SEND(state,
229                                                  state->ev,
230                                                  state->handle,
231                                                  state->fsp,
232                                                  state->data,
233                                                  state->n,
234                                                  state->offset);
235                 if (tevent_req_nomem(subreq, req)) {
236                         return tevent_req_post(req, ev);
237                 }
238                 tevent_req_set_callback(subreq,
239                                         vfs_delay_inject_pwrite_done,
240                                         req);
241                 return req;
242         }
243
244         subreq = tevent_wakeup_send(state, ev, delay_tv);
245         if (tevent_req_nomem(subreq, req)) {
246                 return tevent_req_post(req, ev);
247         }
248         tevent_req_set_callback(
249                 subreq, vfs_delay_inject_pwrite_wait_done, req);
250         return req;
251 }
252
253
254 static void vfs_delay_inject_pwrite_wait_done(struct tevent_req *subreq)
255 {
256         struct tevent_req *req = tevent_req_callback_data(
257                 subreq, struct tevent_req);
258         struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
259                 req, struct vfs_delay_inject_pwrite_state);
260         bool ok;
261
262         ok = tevent_wakeup_recv(subreq);
263         TALLOC_FREE(subreq);
264         if (!ok) {
265                 tevent_req_error(req, EIO);
266                 return;
267         }
268
269         subreq = SMB_VFS_NEXT_PWRITE_SEND(state,
270                                          state->ev,
271                                          state->handle,
272                                          state->fsp,
273                                          state->data,
274                                          state->n,
275                                          state->offset);
276         if (tevent_req_nomem(subreq, req)) {
277                 return;
278         }
279         tevent_req_set_callback(subreq, vfs_delay_inject_pwrite_done, req);
280 }
281
282 static void vfs_delay_inject_pwrite_done(struct tevent_req *subreq)
283 {
284         struct tevent_req *req = tevent_req_callback_data(
285                 subreq, struct tevent_req);
286         struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
287                 req, struct vfs_delay_inject_pwrite_state);
288
289         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
290         TALLOC_FREE(subreq);
291
292         tevent_req_done(req);
293 }
294
295 static ssize_t vfs_delay_inject_pwrite_recv(struct tevent_req *req,
296                                 struct vfs_aio_state *vfs_aio_state)
297 {
298         struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
299                 req, struct vfs_delay_inject_pwrite_state);
300
301         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
302                 return -1;
303         }
304
305         *vfs_aio_state = state->vfs_aio_state;
306         return state->ret;
307 }
308
309 struct vfs_delay_inject_brl_lock_state {
310         struct vfs_delay_inject_brl_lock_state *prev, *next;
311         struct files_struct *fsp;
312         struct GUID req_guid;
313         struct timeval delay_tv;
314         struct tevent_timer *delay_te;
315 };
316
317 static struct vfs_delay_inject_brl_lock_state *brl_lock_states;
318
319 static int vfs_delay_inject_brl_lock_state_destructor(struct vfs_delay_inject_brl_lock_state *state)
320 {
321         DLIST_REMOVE(brl_lock_states, state);
322         return 0;
323 }
324
325 static void vfs_delay_inject_brl_lock_timer(struct tevent_context *ev,
326                                             struct tevent_timer *te,
327                                             struct timeval current_time,
328                                             void *private_data)
329 {
330         struct vfs_delay_inject_brl_lock_state *state =
331                 talloc_get_type_abort(private_data,
332                 struct vfs_delay_inject_brl_lock_state);
333         NTSTATUS status;
334
335         TALLOC_FREE(state->delay_te);
336
337         status = share_mode_wakeup_waiters(state->fsp->file_id);
338         if (!NT_STATUS_IS_OK(status)) {
339                 struct file_id_buf idbuf;
340                 DBG_ERR("share_mode_wakeup_waiters(%s) %s\n",
341                         file_id_str_buf(state->fsp->file_id, &idbuf),
342                         nt_errstr(status));
343         }
344 }
345
346 static NTSTATUS vfs_delay_inject_brl_lock_windows(struct vfs_handle_struct *handle,
347                                                   struct byte_range_lock *br_lck,
348                                                   struct lock_struct *plock)
349 {
350         struct files_struct *fsp = brl_fsp(br_lck);
351         TALLOC_CTX *req_mem_ctx = brl_req_mem_ctx(br_lck);
352         const struct GUID *req_guid = brl_req_guid(br_lck);
353         struct vfs_delay_inject_brl_lock_state *state = NULL;
354         bool expired;
355
356         for (state = brl_lock_states; state != NULL; state = state->next) {
357                 bool match;
358
359                 match = GUID_equal(&state->req_guid, req_guid);
360                 if (match) {
361                         break;
362                 }
363         }
364
365         if (state == NULL) {
366                 int delay;
367                 bool use_timer;
368
369                 state = talloc_zero(req_mem_ctx,
370                                     struct vfs_delay_inject_brl_lock_state);
371                 if (state == NULL) {
372                         return NT_STATUS_NO_MEMORY;
373                 }
374                 state->fsp = fsp;
375                 state->req_guid = *req_guid;
376
377                 delay = lp_parm_int(SNUM(handle->conn),
378                                     "delay_inject", "brl_lock_windows", 0);
379                 state->delay_tv = timeval_current_ofs_msec(delay);
380
381                 use_timer = lp_parm_bool(SNUM(handle->conn),
382                                     "delay_inject", "brl_lock_windows_use_timer", true);
383
384                 if (use_timer) {
385                         state->delay_te = tevent_add_timer(
386                                         global_event_context(),
387                                         state,
388                                         state->delay_tv,
389                                         vfs_delay_inject_brl_lock_timer,
390                                         state);
391                         if (state->delay_te == NULL) {
392                                 return NT_STATUS_NO_MEMORY;
393                         }
394                 }
395
396                 talloc_set_destructor(state,
397                         vfs_delay_inject_brl_lock_state_destructor);
398                 DLIST_ADD_END(brl_lock_states, state);
399         }
400
401         if (state->delay_te != NULL) {
402                 plock->context.smblctx = 0;
403                 return NT_STATUS_RETRY;
404         }
405
406         expired = timeval_expired(&state->delay_tv);
407         if (!expired) {
408                 plock->context.smblctx = UINT64_MAX;
409                 return NT_STATUS_RETRY;
410         }
411
412         TALLOC_FREE(state);
413
414         return SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock);
415 }
416
417 static bool vfs_delay_inject_brl_unlock_windows(struct vfs_handle_struct *handle,
418                                                 struct byte_range_lock *br_lck,
419                                                 const struct lock_struct *plock)
420 {
421         return SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, br_lck, plock);
422 }
423
424 static struct vfs_fn_pointers vfs_delay_inject_fns = {
425         .fntimes_fn = vfs_delay_inject_fntimes,
426         .pread_send_fn = vfs_delay_inject_pread_send,
427         .pread_recv_fn = vfs_delay_inject_pread_recv,
428         .pwrite_send_fn = vfs_delay_inject_pwrite_send,
429         .pwrite_recv_fn = vfs_delay_inject_pwrite_recv,
430
431         .brl_lock_windows_fn = vfs_delay_inject_brl_lock_windows,
432         .brl_unlock_windows_fn = vfs_delay_inject_brl_unlock_windows,
433 };
434
435 static_decl_vfs;
436 NTSTATUS vfs_delay_inject_init(TALLOC_CTX *ctx)
437 {
438         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "delay_inject",
439                                 &vfs_delay_inject_fns);
440 }