s3: VFS: vfs_time_audit. Remove mkdir_fn(). No longer used.
[samba.git] / source3 / modules / vfs_time_audit.c
1 /*
2  * Time auditing VFS module for samba.  Log time taken for VFS call to syslog
3  * facility.
4  *
5  * Copyright (C) Abhidnya Chirmule <achirmul@in.ibm.com> 2009
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * This module implements logging for time taken for all Samba VFS operations.
23  *
24  * vfs objects = time_audit
25  */
26
27
28 #include "includes.h"
29 #include "smbd/smbd.h"
30 #include "ntioctl.h"
31 #include "lib/util/tevent_unix.h"
32 #include "lib/util/tevent_ntstatus.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_VFS
36
37 static double audit_timeout;
38
39 static void smb_time_audit_log_msg(const char *syscallname, double elapsed,
40                                     const char *msg)
41 {
42         DEBUG(0, ("WARNING: VFS call \"%s\" took unexpectedly long "
43                   "(%.2f seconds) %s%s-- Validate that file and storage "
44                   "subsystems are operating normally\n", syscallname,
45                   elapsed, (msg != NULL) ? msg : "",
46                   (msg != NULL) ? " " : ""));
47 }
48
49 static void smb_time_audit_log(const char *syscallname, double elapsed)
50 {
51         smb_time_audit_log_msg(syscallname, elapsed, NULL);
52 }
53
54 static void smb_time_audit_log_fsp(const char *syscallname, double elapsed,
55                                    const struct files_struct *fsp)
56 {
57         char *base_name = NULL;
58         char *connectpath = NULL;
59         char *msg = NULL;
60
61         if (fsp == NULL) {
62                 smb_time_audit_log(syscallname, elapsed);
63                 return;
64         }
65         if (fsp->conn)
66                 connectpath = fsp->conn->connectpath;
67         if (fsp->fsp_name)
68                 base_name = fsp->fsp_name->base_name;
69
70         if (connectpath != NULL && base_name != NULL) {
71                 msg = talloc_asprintf(talloc_tos(), "filename = \"%s/%s\"",
72                                       connectpath, base_name);
73         } else if (connectpath != NULL && base_name == NULL) {
74                 msg = talloc_asprintf(talloc_tos(), "connectpath = \"%s\", "
75                                       "base_name = <NULL>",
76                                       connectpath);
77         } else if (connectpath == NULL && base_name != NULL) {
78                 msg = talloc_asprintf(talloc_tos(), "connectpath = <NULL>, "
79                                       "base_name = \"%s\"",
80                                       base_name);
81         } else { /* connectpath == NULL && base_name == NULL */
82                 msg = talloc_asprintf(talloc_tos(), "connectpath = <NULL>, "
83                                       "base_name = <NULL>");
84         }
85         smb_time_audit_log_msg(syscallname, elapsed, msg);
86         TALLOC_FREE(msg);
87 }
88
89 static void smb_time_audit_log_at(const char *syscallname,
90                                   double elapsed,
91                                   const struct files_struct *dir_fsp,
92                                   const struct smb_filename *smb_fname)
93 {
94         char *msg = NULL;
95
96         msg = talloc_asprintf(talloc_tos(),
97                               "filename = \"%s/%s/%s\"",
98                               dir_fsp->conn->connectpath,
99                               dir_fsp->fsp_name->base_name,
100                               smb_fname->base_name);
101
102         smb_time_audit_log_msg(syscallname, elapsed, msg);
103         TALLOC_FREE(msg);
104 }
105
106 static void smb_time_audit_log_fname(const char *syscallname, double elapsed,
107                                     const char *fname)
108 {
109         char cwd[PATH_MAX];
110         char *msg = NULL;
111
112         if (getcwd(cwd, sizeof(cwd)) == NULL) {
113                 snprintf(cwd, sizeof(cwd), "<getcwd() error %d>", errno);
114         }
115         if (fname != NULL) {
116                 msg = talloc_asprintf(talloc_tos(),
117                                       "cwd = \"%s\", filename = \"%s\"",
118                                       cwd, fname);
119         } else {
120                 msg = talloc_asprintf(talloc_tos(),
121                                       "cwd = \"%s\", filename = <NULL>",
122                                       cwd);
123         }
124         smb_time_audit_log_msg(syscallname, elapsed, msg);
125         TALLOC_FREE(msg);
126 }
127
128 static void smb_time_audit_log_smb_fname(const char *syscallname, double elapsed,
129                                        const struct smb_filename *smb_fname)
130 {
131         if (smb_fname != NULL) {
132                 smb_time_audit_log_fname(syscallname, elapsed,
133                                          smb_fname->base_name);
134         } else {
135                 smb_time_audit_log_fname(syscallname, elapsed,
136                                          "smb_fname = <NULL>");
137         }
138 }
139
140 static int smb_time_audit_connect(vfs_handle_struct *handle,
141                                   const char *svc, const char *user)
142 {
143         int result;
144         struct timespec ts1,ts2;
145         double timediff;
146
147         if (!handle) {
148                 return -1;
149         }
150
151         clock_gettime_mono(&ts1);
152         result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
153         clock_gettime_mono(&ts2);
154         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
155         if (timediff > audit_timeout) {
156                 smb_time_audit_log_msg("connect", timediff, user);
157         }
158         return result;
159 }
160
161 static void smb_time_audit_disconnect(vfs_handle_struct *handle)
162 {
163         struct timespec ts1,ts2;
164         double timediff;
165
166         clock_gettime_mono(&ts1);
167         SMB_VFS_NEXT_DISCONNECT(handle);
168         clock_gettime_mono(&ts2);
169         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
170
171         if (timediff > audit_timeout) {
172                 smb_time_audit_log("disconnect", timediff);
173         }
174 }
175
176 static uint64_t smb_time_audit_disk_free(vfs_handle_struct *handle,
177                                         const struct smb_filename *smb_fname,
178                                         uint64_t *bsize,
179                                         uint64_t *dfree,
180                                         uint64_t *dsize)
181 {
182         uint64_t result;
183         struct timespec ts1,ts2;
184         double timediff;
185
186         clock_gettime_mono(&ts1);
187         result = SMB_VFS_NEXT_DISK_FREE(handle, smb_fname, bsize, dfree, dsize);
188         clock_gettime_mono(&ts2);
189         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
190
191         /* Don't have a reasonable notion of failure here */
192         if (timediff > audit_timeout) {
193                 smb_time_audit_log_fname("disk_free",
194                                 timediff,
195                                 smb_fname->base_name);
196         }
197
198         return result;
199 }
200
201 static int smb_time_audit_get_quota(struct vfs_handle_struct *handle,
202                                         const struct smb_filename *smb_fname,
203                                         enum SMB_QUOTA_TYPE qtype,
204                                         unid_t id,
205                                         SMB_DISK_QUOTA *qt)
206 {
207         int result;
208         struct timespec ts1,ts2;
209         double timediff;
210
211         clock_gettime_mono(&ts1);
212         result = SMB_VFS_NEXT_GET_QUOTA(handle, smb_fname, qtype, id, qt);
213         clock_gettime_mono(&ts2);
214         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
215
216         if (timediff > audit_timeout) {
217                 smb_time_audit_log_fname("get_quota",
218                                 timediff,
219                                 smb_fname->base_name);
220         }
221         return result;
222 }
223
224 static int smb_time_audit_set_quota(struct vfs_handle_struct *handle,
225                                     enum SMB_QUOTA_TYPE qtype, unid_t id,
226                                     SMB_DISK_QUOTA *qt)
227 {
228         int result;
229         struct timespec ts1,ts2;
230         double timediff;
231
232         clock_gettime_mono(&ts1);
233         result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt);
234         clock_gettime_mono(&ts2);
235         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
236
237         if (timediff > audit_timeout) {
238                 smb_time_audit_log("set_quota", timediff);
239         }
240
241         return result;
242 }
243
244 static int smb_time_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
245                                                struct files_struct *fsp,
246                                                struct shadow_copy_data *shadow_copy_data,
247                                                bool labels)
248 {
249         int result;
250         struct timespec ts1,ts2;
251         double timediff;
252
253         clock_gettime_mono(&ts1);
254         result = SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp,
255                                                    shadow_copy_data, labels);
256         clock_gettime_mono(&ts2);
257         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
258
259         if (timediff > audit_timeout) {
260                 smb_time_audit_log_fsp("get_shadow_copy_data", timediff, fsp);
261         }
262
263         return result;
264 }
265
266 static int smb_time_audit_statvfs(struct vfs_handle_struct *handle,
267                                   const struct smb_filename *smb_fname,
268                                   struct vfs_statvfs_struct *statbuf)
269 {
270         int result;
271         struct timespec ts1,ts2;
272         double timediff;
273
274         clock_gettime_mono(&ts1);
275         result = SMB_VFS_NEXT_STATVFS(handle, smb_fname, statbuf);
276         clock_gettime_mono(&ts2);
277         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
278
279         if (timediff > audit_timeout) {
280                 smb_time_audit_log_fname("statvfs", timediff,
281                         smb_fname->base_name);
282         }
283
284         return result;
285 }
286
287 static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle,
288                                                enum timestamp_set_resolution *p_ts_res)
289 {
290         uint32_t result;
291         struct timespec ts1,ts2;
292         double timediff;
293
294         clock_gettime_mono(&ts1);
295         result = SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
296         clock_gettime_mono(&ts2);
297         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
298
299         if (timediff > audit_timeout) {
300                 smb_time_audit_log("fs_capabilities", timediff);
301         }
302
303         return result;
304 }
305
306 static NTSTATUS smb_time_audit_get_dfs_referrals(
307                         struct vfs_handle_struct *handle,
308                         struct dfs_GetDFSReferral *r)
309 {
310         NTSTATUS result;
311         struct timespec ts1,ts2;
312         double timediff;
313
314         clock_gettime_mono(&ts1);
315         result = SMB_VFS_NEXT_GET_DFS_REFERRALS(handle, r);
316         clock_gettime_mono(&ts2);
317         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
318
319         if (timediff > audit_timeout) {
320                 smb_time_audit_log("get_dfs_referrals", timediff);
321         }
322
323         return result;
324 }
325
326 static NTSTATUS smb_time_audit_snap_check_path(struct vfs_handle_struct *handle,
327                                                TALLOC_CTX *mem_ctx,
328                                                const char *service_path,
329                                                char **base_volume)
330 {
331         NTSTATUS status;
332         struct timespec ts1,ts2;
333         double timediff;
334
335         clock_gettime_mono(&ts1);
336         status = SMB_VFS_NEXT_SNAP_CHECK_PATH(handle, mem_ctx, service_path,
337                                               base_volume);
338         clock_gettime_mono(&ts2);
339         timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
340
341         if (timediff > audit_timeout) {
342                 smb_time_audit_log("snap_check_path", timediff);
343         }
344
345         return status;
346 }
347
348 static NTSTATUS smb_time_audit_snap_create(struct vfs_handle_struct *handle,
349                                            TALLOC_CTX *mem_ctx,
350                                            const char *base_volume,
351                                            time_t *tstamp,
352                                            bool rw,
353                                            char **base_path,
354                                            char **snap_path)
355 {
356         NTSTATUS status;
357         struct timespec ts1,ts2;
358         double timediff;
359
360         clock_gettime_mono(&ts1);
361         status = SMB_VFS_NEXT_SNAP_CREATE(handle, mem_ctx, base_volume, tstamp,
362                                           rw, base_path, snap_path);
363         clock_gettime_mono(&ts2);
364         timediff = nsec_time_diff(&ts2 ,&ts1) * 1.0e-9;
365
366         if (timediff > audit_timeout) {
367                 smb_time_audit_log("snap_create", timediff);
368         }
369
370         return status;
371 }
372
373 static NTSTATUS smb_time_audit_snap_delete(struct vfs_handle_struct *handle,
374                                            TALLOC_CTX *mem_ctx,
375                                            char *base_path,
376                                            char *snap_path)
377 {
378         NTSTATUS status;
379         struct timespec ts1,ts2;
380         double timediff;
381
382         clock_gettime_mono(&ts1);
383         status = SMB_VFS_NEXT_SNAP_DELETE(handle, mem_ctx, base_path,
384                                           snap_path);
385         clock_gettime_mono(&ts2);
386         timediff = nsec_time_diff(&ts2, &ts1) * 1.0e-9;
387
388         if (timediff > audit_timeout) {
389                 smb_time_audit_log("snap_delete", timediff);
390         }
391
392         return status;
393 }
394
395 static DIR *smb_time_audit_opendir(vfs_handle_struct *handle,
396                                    const struct smb_filename *smb_fname,
397                                    const char *mask, uint32_t attr)
398 {
399         DIR *result;
400         struct timespec ts1,ts2;
401         double timediff;
402
403         clock_gettime_mono(&ts1);
404         result = SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr);
405         clock_gettime_mono(&ts2);
406         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
407
408         if (timediff > audit_timeout) {
409                 smb_time_audit_log_smb_fname("opendir", timediff, smb_fname);
410         }
411
412         return result;
413 }
414
415 static DIR *smb_time_audit_fdopendir(vfs_handle_struct *handle,
416                                               files_struct *fsp,
417                                               const char *mask, uint32_t attr)
418 {
419         DIR *result;
420         struct timespec ts1,ts2;
421         double timediff;
422
423         clock_gettime_mono(&ts1);
424         result = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr);
425         clock_gettime_mono(&ts2);
426         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
427
428         if (timediff > audit_timeout) {
429                 smb_time_audit_log_fsp("fdopendir", timediff, fsp);
430         }
431
432         return result;
433 }
434
435 static struct dirent *smb_time_audit_readdir(vfs_handle_struct *handle,
436                                                  DIR *dirp,
437                                                  SMB_STRUCT_STAT *sbuf)
438 {
439         struct dirent *result;
440         struct timespec ts1,ts2;
441         double timediff;
442
443         clock_gettime_mono(&ts1);
444         result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf);
445         clock_gettime_mono(&ts2);
446         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
447
448         if (timediff > audit_timeout) {
449                 smb_time_audit_log("readdir", timediff);
450         }
451
452         return result;
453 }
454
455 static void smb_time_audit_seekdir(vfs_handle_struct *handle,
456                                    DIR *dirp, long offset)
457 {
458         struct timespec ts1,ts2;
459         double timediff;
460
461         clock_gettime_mono(&ts1);
462         SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset);
463         clock_gettime_mono(&ts2);
464         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
465
466         if (timediff > audit_timeout) {
467                 smb_time_audit_log("seekdir", timediff);
468         }
469
470 }
471
472 static long smb_time_audit_telldir(vfs_handle_struct *handle,
473                                    DIR *dirp)
474 {
475         long result;
476         struct timespec ts1,ts2;
477         double timediff;
478
479         clock_gettime_mono(&ts1);
480         result = SMB_VFS_NEXT_TELLDIR(handle, dirp);
481         clock_gettime_mono(&ts2);
482         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
483
484         if (timediff > audit_timeout) {
485                 smb_time_audit_log("telldir", timediff);
486         }
487
488         return result;
489 }
490
491 static void smb_time_audit_rewinddir(vfs_handle_struct *handle,
492                                      DIR *dirp)
493 {
494         struct timespec ts1,ts2;
495         double timediff;
496
497         clock_gettime_mono(&ts1);
498         SMB_VFS_NEXT_REWINDDIR(handle, dirp);
499         clock_gettime_mono(&ts2);
500         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
501
502         if (timediff > audit_timeout) {
503                 smb_time_audit_log("rewinddir", timediff);
504         }
505
506 }
507
508 static int smb_time_audit_mkdirat(vfs_handle_struct *handle,
509                                 struct files_struct *dirfsp,
510                                 const struct smb_filename *smb_fname,
511                                 mode_t mode)
512 {
513         int result;
514         struct timespec ts1,ts2;
515         double timediff;
516
517         clock_gettime_mono(&ts1);
518         result = SMB_VFS_NEXT_MKDIRAT(handle,
519                                 dirfsp,
520                                 smb_fname,
521                                 mode);
522         clock_gettime_mono(&ts2);
523         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
524
525         if (timediff > audit_timeout) {
526                 smb_time_audit_log_smb_fname("mkdirat",
527                         timediff,
528                         smb_fname);
529         }
530
531         return result;
532 }
533
534 static int smb_time_audit_rmdir(vfs_handle_struct *handle,
535                                 const struct smb_filename *smb_fname)
536 {
537         int result;
538         struct timespec ts1,ts2;
539         double timediff;
540
541         clock_gettime_mono(&ts1);
542         result = SMB_VFS_NEXT_RMDIR(handle, smb_fname);
543         clock_gettime_mono(&ts2);
544         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
545
546         if (timediff > audit_timeout) {
547                 smb_time_audit_log_smb_fname("rmdir",
548                         timediff,
549                         smb_fname);
550         }
551
552         return result;
553 }
554
555 static int smb_time_audit_closedir(vfs_handle_struct *handle,
556                                    DIR *dirp)
557 {
558         int result;
559         struct timespec ts1,ts2;
560         double timediff;
561
562         clock_gettime_mono(&ts1);
563         result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
564         clock_gettime_mono(&ts2);
565         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
566
567         if (timediff > audit_timeout) {
568                 smb_time_audit_log("closedir", timediff);
569         }
570
571         return result;
572 }
573
574 static int smb_time_audit_open(vfs_handle_struct *handle,
575                                struct smb_filename *fname,
576                                files_struct *fsp,
577                                int flags, mode_t mode)
578 {
579         int result;
580         struct timespec ts1,ts2;
581         double timediff;
582
583         clock_gettime_mono(&ts1);
584         result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
585         clock_gettime_mono(&ts2);
586         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
587
588         if (timediff > audit_timeout) {
589                 smb_time_audit_log_fsp("open", timediff, fsp);
590         }
591
592         return result;
593 }
594
595 static NTSTATUS smb_time_audit_create_file(vfs_handle_struct *handle,
596                                            struct smb_request *req,
597                                            uint16_t root_dir_fid,
598                                            struct smb_filename *fname,
599                                            uint32_t access_mask,
600                                            uint32_t share_access,
601                                            uint32_t create_disposition,
602                                            uint32_t create_options,
603                                            uint32_t file_attributes,
604                                            uint32_t oplock_request,
605                                            const struct smb2_lease *lease,
606                                            uint64_t allocation_size,
607                                            uint32_t private_flags,
608                                            struct security_descriptor *sd,
609                                            struct ea_list *ea_list,
610                                            files_struct **result_fsp,
611                                            int *pinfo,
612                                            const struct smb2_create_blobs *in_context_blobs,
613                                            struct smb2_create_blobs *out_context_blobs)
614 {
615         NTSTATUS result;
616         struct timespec ts1,ts2;
617         double timediff;
618
619         clock_gettime_mono(&ts1);
620         result = SMB_VFS_NEXT_CREATE_FILE(
621                 handle,                                 /* handle */
622                 req,                                    /* req */
623                 root_dir_fid,                           /* root_dir_fid */
624                 fname,                                  /* fname */
625                 access_mask,                            /* access_mask */
626                 share_access,                           /* share_access */
627                 create_disposition,                     /* create_disposition*/
628                 create_options,                         /* create_options */
629                 file_attributes,                        /* file_attributes */
630                 oplock_request,                         /* oplock_request */
631                 lease,                                  /* lease */
632                 allocation_size,                        /* allocation_size */
633                 private_flags,
634                 sd,                                     /* sd */
635                 ea_list,                                /* ea_list */
636                 result_fsp,                             /* result */
637                 pinfo,
638                 in_context_blobs, out_context_blobs);   /* create context */
639         clock_gettime_mono(&ts2);
640         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
641
642         if (timediff > audit_timeout) {
643                 /*
644                  * can't use result_fsp this time, may have
645                  * invalid content causing smbd crash
646                  */
647                 smb_time_audit_log_smb_fname("create_file", timediff,
648                                            fname);
649         }
650
651         return result;
652 }
653
654 static int smb_time_audit_close(vfs_handle_struct *handle, files_struct *fsp)
655 {
656         int result;
657         struct timespec ts1,ts2;
658         double timediff;
659
660         clock_gettime_mono(&ts1);
661         result = SMB_VFS_NEXT_CLOSE(handle, fsp);
662         clock_gettime_mono(&ts2);
663         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
664
665         if (timediff > audit_timeout) {
666                 smb_time_audit_log_fsp("close", timediff, fsp);
667         }
668
669         return result;
670 }
671
672 static ssize_t smb_time_audit_pread(vfs_handle_struct *handle,
673                                     files_struct *fsp,
674                                     void *data, size_t n, off_t offset)
675 {
676         ssize_t result;
677         struct timespec ts1,ts2;
678         double timediff;
679
680         clock_gettime_mono(&ts1);
681         result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
682         clock_gettime_mono(&ts2);
683         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
684
685         if (timediff > audit_timeout) {
686                 smb_time_audit_log_fsp("pread", timediff, fsp);
687         }
688
689         return result;
690 }
691
692 struct smb_time_audit_pread_state {
693         struct files_struct *fsp;
694         ssize_t ret;
695         struct vfs_aio_state vfs_aio_state;
696 };
697
698 static void smb_time_audit_pread_done(struct tevent_req *subreq);
699
700 static struct tevent_req *smb_time_audit_pread_send(
701         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
702         struct tevent_context *ev, struct files_struct *fsp,
703         void *data, size_t n, off_t offset)
704 {
705         struct tevent_req *req, *subreq;
706         struct smb_time_audit_pread_state *state;
707
708         req = tevent_req_create(mem_ctx, &state,
709                                 struct smb_time_audit_pread_state);
710         if (req == NULL) {
711                 return NULL;
712         }
713         state->fsp = fsp;
714
715         subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
716                                          n, offset);
717         if (tevent_req_nomem(subreq, req)) {
718                 return tevent_req_post(req, ev);
719         }
720         tevent_req_set_callback(subreq, smb_time_audit_pread_done, req);
721         return req;
722 }
723
724 static void smb_time_audit_pread_done(struct tevent_req *subreq)
725 {
726         struct tevent_req *req = tevent_req_callback_data(
727                 subreq, struct tevent_req);
728         struct smb_time_audit_pread_state *state = tevent_req_data(
729                 req, struct smb_time_audit_pread_state);
730
731         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
732         TALLOC_FREE(subreq);
733         tevent_req_done(req);
734 }
735
736 static ssize_t smb_time_audit_pread_recv(struct tevent_req *req,
737                                          struct vfs_aio_state *vfs_aio_state)
738 {
739         struct smb_time_audit_pread_state *state = tevent_req_data(
740                 req, struct smb_time_audit_pread_state);
741         double timediff;
742
743         timediff = state->vfs_aio_state.duration * 1.0e-9;
744
745         if (timediff > audit_timeout) {
746                 smb_time_audit_log_fsp("async pread", timediff, state->fsp);
747         }
748
749         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
750                 return -1;
751         }
752         *vfs_aio_state = state->vfs_aio_state;
753         return state->ret;
754 }
755
756 static ssize_t smb_time_audit_pwrite(vfs_handle_struct *handle,
757                                      files_struct *fsp,
758                                      const void *data, size_t n,
759                                      off_t offset)
760 {
761         ssize_t result;
762         struct timespec ts1,ts2;
763         double timediff;
764
765         clock_gettime_mono(&ts1);
766         result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
767         clock_gettime_mono(&ts2);
768         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
769
770         if (timediff > audit_timeout) {
771                 smb_time_audit_log_fsp("pwrite", timediff, fsp);
772         }
773
774         return result;
775 }
776
777 struct smb_time_audit_pwrite_state {
778         struct files_struct *fsp;
779         ssize_t ret;
780         struct vfs_aio_state vfs_aio_state;
781 };
782
783 static void smb_time_audit_pwrite_done(struct tevent_req *subreq);
784
785 static struct tevent_req *smb_time_audit_pwrite_send(
786         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
787         struct tevent_context *ev, struct files_struct *fsp,
788         const void *data, size_t n, off_t offset)
789 {
790         struct tevent_req *req, *subreq;
791         struct smb_time_audit_pwrite_state *state;
792
793         req = tevent_req_create(mem_ctx, &state,
794                                 struct smb_time_audit_pwrite_state);
795         if (req == NULL) {
796                 return NULL;
797         }
798         state->fsp = fsp;
799
800         subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
801                                          n, offset);
802         if (tevent_req_nomem(subreq, req)) {
803                 return tevent_req_post(req, ev);
804         }
805         tevent_req_set_callback(subreq, smb_time_audit_pwrite_done, req);
806         return req;
807 }
808
809 static void smb_time_audit_pwrite_done(struct tevent_req *subreq)
810 {
811         struct tevent_req *req = tevent_req_callback_data(
812                 subreq, struct tevent_req);
813         struct smb_time_audit_pwrite_state *state = tevent_req_data(
814                 req, struct smb_time_audit_pwrite_state);
815
816         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
817         TALLOC_FREE(subreq);
818         tevent_req_done(req);
819 }
820
821 static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req,
822                                           struct vfs_aio_state *vfs_aio_state)
823 {
824         struct smb_time_audit_pwrite_state *state = tevent_req_data(
825                 req, struct smb_time_audit_pwrite_state);
826         double timediff;
827
828         timediff = state->vfs_aio_state.duration * 1.0e-9;
829
830         if (timediff > audit_timeout) {
831                 smb_time_audit_log_fsp("async pwrite", timediff, state->fsp);
832         }
833
834         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
835                 return -1;
836         }
837         *vfs_aio_state = state->vfs_aio_state;
838         return state->ret;
839 }
840
841 static off_t smb_time_audit_lseek(vfs_handle_struct *handle,
842                                       files_struct *fsp,
843                                       off_t offset, int whence)
844 {
845         off_t result;
846         struct timespec ts1,ts2;
847         double timediff;
848
849         clock_gettime_mono(&ts1);
850         result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
851         clock_gettime_mono(&ts2);
852         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
853
854         if (timediff > audit_timeout) {
855                 smb_time_audit_log_fsp("lseek", timediff, fsp);
856         }
857
858         return result;
859 }
860
861 static ssize_t smb_time_audit_sendfile(vfs_handle_struct *handle, int tofd,
862                                        files_struct *fromfsp,
863                                        const DATA_BLOB *hdr, off_t offset,
864                                        size_t n)
865 {
866         ssize_t result;
867         struct timespec ts1,ts2;
868         double timediff;
869
870         clock_gettime_mono(&ts1);
871         result = SMB_VFS_NEXT_SENDFILE(handle, tofd, fromfsp, hdr, offset, n);
872         clock_gettime_mono(&ts2);
873         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
874
875         if (timediff > audit_timeout) {
876                 smb_time_audit_log_fsp("sendfile", timediff, fromfsp);
877         }
878
879         return result;
880 }
881
882 static ssize_t smb_time_audit_recvfile(vfs_handle_struct *handle, int fromfd,
883                                        files_struct *tofsp,
884                                        off_t offset,
885                                        size_t n)
886 {
887         ssize_t result;
888         struct timespec ts1,ts2;
889         double timediff;
890
891         clock_gettime_mono(&ts1);
892         result = SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, n);
893         clock_gettime_mono(&ts2);
894         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
895
896         if (timediff > audit_timeout) {
897                 smb_time_audit_log_fsp("recvfile", timediff, tofsp);
898         }
899
900         return result;
901 }
902
903 static int smb_time_audit_renameat(vfs_handle_struct *handle,
904                                 files_struct *srcfsp,
905                                 const struct smb_filename *oldname,
906                                 files_struct *dstfsp,
907                                 const struct smb_filename *newname)
908 {
909         int result;
910         struct timespec ts1,ts2;
911         double timediff;
912
913         clock_gettime_mono(&ts1);
914         result = SMB_VFS_NEXT_RENAMEAT(handle,
915                         srcfsp,
916                         oldname,
917                         dstfsp,
918                         newname);
919         clock_gettime_mono(&ts2);
920         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
921
922         if (timediff > audit_timeout) {
923                 smb_time_audit_log_smb_fname("renameat", timediff, newname);
924         }
925
926         return result;
927 }
928
929 struct smb_time_audit_fsync_state {
930         struct files_struct *fsp;
931         int ret;
932         struct vfs_aio_state vfs_aio_state;
933 };
934
935 static void smb_time_audit_fsync_done(struct tevent_req *subreq);
936
937 static struct tevent_req *smb_time_audit_fsync_send(
938         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
939         struct tevent_context *ev, struct files_struct *fsp)
940 {
941         struct tevent_req *req, *subreq;
942         struct smb_time_audit_fsync_state *state;
943
944         req = tevent_req_create(mem_ctx, &state,
945                                 struct smb_time_audit_fsync_state);
946         if (req == NULL) {
947                 return NULL;
948         }
949         state->fsp = fsp;
950
951         subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
952         if (tevent_req_nomem(subreq, req)) {
953                 return tevent_req_post(req, ev);
954         }
955         tevent_req_set_callback(subreq, smb_time_audit_fsync_done, req);
956         return req;
957 }
958
959 static void smb_time_audit_fsync_done(struct tevent_req *subreq)
960 {
961         struct tevent_req *req = tevent_req_callback_data(
962                 subreq, struct tevent_req);
963         struct smb_time_audit_fsync_state *state = tevent_req_data(
964                 req, struct smb_time_audit_fsync_state);
965
966         state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
967         TALLOC_FREE(subreq);
968         tevent_req_done(req);
969 }
970
971 static int smb_time_audit_fsync_recv(struct tevent_req *req,
972                                      struct vfs_aio_state *vfs_aio_state)
973 {
974         struct smb_time_audit_fsync_state *state = tevent_req_data(
975                 req, struct smb_time_audit_fsync_state);
976         double timediff;
977
978         timediff = state->vfs_aio_state.duration * 1.0e-9;
979
980         if (timediff > audit_timeout) {
981                 smb_time_audit_log_fsp("async fsync", timediff, state->fsp);
982         }
983
984         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
985                 return -1;
986         }
987         *vfs_aio_state = state->vfs_aio_state;
988         return state->ret;
989 }
990
991 static int smb_time_audit_stat(vfs_handle_struct *handle,
992                                struct smb_filename *fname)
993 {
994         int result;
995         struct timespec ts1,ts2;
996         double timediff;
997
998         clock_gettime_mono(&ts1);
999         result = SMB_VFS_NEXT_STAT(handle, fname);
1000         clock_gettime_mono(&ts2);
1001         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1002
1003         if (timediff > audit_timeout) {
1004                 smb_time_audit_log_smb_fname("stat", timediff, fname);
1005         }
1006
1007         return result;
1008 }
1009
1010 static int smb_time_audit_fstat(vfs_handle_struct *handle, files_struct *fsp,
1011                                 SMB_STRUCT_STAT *sbuf)
1012 {
1013         int result;
1014         struct timespec ts1,ts2;
1015         double timediff;
1016
1017         clock_gettime_mono(&ts1);
1018         result = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1019         clock_gettime_mono(&ts2);
1020         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1021
1022         if (timediff > audit_timeout) {
1023                 smb_time_audit_log_fsp("fstat", timediff, fsp);
1024         }
1025
1026         return result;
1027 }
1028
1029 static int smb_time_audit_lstat(vfs_handle_struct *handle,
1030                                 struct smb_filename *path)
1031 {
1032         int result;
1033         struct timespec ts1,ts2;
1034         double timediff;
1035
1036         clock_gettime_mono(&ts1);
1037         result = SMB_VFS_NEXT_LSTAT(handle, path);
1038         clock_gettime_mono(&ts2);
1039         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1040
1041         if (timediff > audit_timeout) {
1042                 smb_time_audit_log_smb_fname("lstat", timediff, path);
1043         }
1044
1045         return result;
1046 }
1047
1048 static uint64_t smb_time_audit_get_alloc_size(vfs_handle_struct *handle,
1049                                               files_struct *fsp,
1050                                               const SMB_STRUCT_STAT *sbuf)
1051 {
1052         uint64_t result;
1053         struct timespec ts1,ts2;
1054         double timediff;
1055
1056         clock_gettime_mono(&ts1);
1057         result = SMB_VFS_NEXT_GET_ALLOC_SIZE(handle, fsp, sbuf);
1058         clock_gettime_mono(&ts2);
1059         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1060
1061         if (timediff > audit_timeout) {
1062                 smb_time_audit_log_fsp("get_alloc_size", timediff, fsp);
1063         }
1064
1065         return result;
1066 }
1067
1068 static int smb_time_audit_unlink(vfs_handle_struct *handle,
1069                                  const struct smb_filename *path)
1070 {
1071         int result;
1072         struct timespec ts1,ts2;
1073         double timediff;
1074
1075         clock_gettime_mono(&ts1);
1076         result = SMB_VFS_NEXT_UNLINK(handle, path);
1077         clock_gettime_mono(&ts2);
1078         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1079
1080         if (timediff > audit_timeout) {
1081                 smb_time_audit_log_smb_fname("unlink", timediff, path);
1082         }
1083
1084         return result;
1085 }
1086
1087 static int smb_time_audit_chmod(vfs_handle_struct *handle,
1088                         const struct smb_filename *smb_fname,
1089                         mode_t mode)
1090 {
1091         int result;
1092         struct timespec ts1,ts2;
1093         double timediff;
1094
1095         clock_gettime_mono(&ts1);
1096         result = SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1097         clock_gettime_mono(&ts2);
1098         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1099
1100         if (timediff > audit_timeout) {
1101                 smb_time_audit_log_fname("chmod",
1102                         timediff,
1103                         smb_fname->base_name);
1104         }
1105
1106         return result;
1107 }
1108
1109 static int smb_time_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp,
1110                                  mode_t mode)
1111 {
1112         int result;
1113         struct timespec ts1,ts2;
1114         double timediff;
1115
1116         clock_gettime_mono(&ts1);
1117         result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1118         clock_gettime_mono(&ts2);
1119         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1120
1121         if (timediff > audit_timeout) {
1122                 smb_time_audit_log_fsp("fchmod", timediff, fsp);
1123         }
1124
1125         return result;
1126 }
1127
1128 static int smb_time_audit_chown(vfs_handle_struct *handle,
1129                         const struct smb_filename *smb_fname,
1130                         uid_t uid,
1131                         gid_t gid)
1132 {
1133         int result;
1134         struct timespec ts1,ts2;
1135         double timediff;
1136
1137         clock_gettime_mono(&ts1);
1138         result = SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
1139         clock_gettime_mono(&ts2);
1140         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1141
1142         if (timediff > audit_timeout) {
1143                 smb_time_audit_log_fname("chown",
1144                         timediff,
1145                         smb_fname->base_name);
1146         }
1147
1148         return result;
1149 }
1150
1151 static int smb_time_audit_fchown(vfs_handle_struct *handle, files_struct *fsp,
1152                                  uid_t uid, gid_t gid)
1153 {
1154         int result;
1155         struct timespec ts1,ts2;
1156         double timediff;
1157
1158         clock_gettime_mono(&ts1);
1159         result = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1160         clock_gettime_mono(&ts2);
1161         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1162
1163         if (timediff > audit_timeout) {
1164                 smb_time_audit_log_fsp("fchown", timediff, fsp);
1165         }
1166
1167         return result;
1168 }
1169
1170 static int smb_time_audit_lchown(vfs_handle_struct *handle,
1171                         const struct smb_filename *smb_fname,
1172                         uid_t uid,
1173                         gid_t gid)
1174 {
1175         int result;
1176         struct timespec ts1,ts2;
1177         double timediff;
1178
1179         clock_gettime_mono(&ts1);
1180         result = SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
1181         clock_gettime_mono(&ts2);
1182         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1183
1184         if (timediff > audit_timeout) {
1185                 smb_time_audit_log_fname("lchown",
1186                         timediff,
1187                         smb_fname->base_name);
1188         }
1189
1190         return result;
1191 }
1192
1193 static int smb_time_audit_chdir(vfs_handle_struct *handle,
1194                         const struct smb_filename *smb_fname)
1195 {
1196         int result;
1197         struct timespec ts1,ts2;
1198         double timediff;
1199
1200         clock_gettime_mono(&ts1);
1201         result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
1202         clock_gettime_mono(&ts2);
1203         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1204
1205         if (timediff > audit_timeout) {
1206                 smb_time_audit_log_fname("chdir",
1207                         timediff,
1208                         smb_fname->base_name);
1209         }
1210
1211         return result;
1212 }
1213
1214 static struct smb_filename *smb_time_audit_getwd(vfs_handle_struct *handle,
1215                                         TALLOC_CTX *mem_ctx)
1216 {
1217         struct smb_filename *result;
1218         struct timespec ts1,ts2;
1219         double timediff;
1220
1221         clock_gettime_mono(&ts1);
1222         result = SMB_VFS_NEXT_GETWD(handle, mem_ctx);
1223         clock_gettime_mono(&ts2);
1224         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1225
1226         if (timediff > audit_timeout) {
1227                 smb_time_audit_log("getwd", timediff);
1228         }
1229
1230         return result;
1231 }
1232
1233 static int smb_time_audit_ntimes(vfs_handle_struct *handle,
1234                                  const struct smb_filename *path,
1235                                  struct smb_file_time *ft)
1236 {
1237         int result;
1238         struct timespec ts1,ts2;
1239         double timediff;
1240
1241         clock_gettime_mono(&ts1);
1242         result = SMB_VFS_NEXT_NTIMES(handle, path, ft);
1243         clock_gettime_mono(&ts2);
1244         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1245
1246         if (timediff > audit_timeout) {
1247                 smb_time_audit_log_smb_fname("ntimes", timediff, path);
1248         }
1249
1250         return result;
1251 }
1252
1253 static int smb_time_audit_ftruncate(vfs_handle_struct *handle,
1254                                     files_struct *fsp,
1255                                     off_t len)
1256 {
1257         int result;
1258         struct timespec ts1,ts2;
1259         double timediff;
1260
1261         clock_gettime_mono(&ts1);
1262         result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
1263         clock_gettime_mono(&ts2);
1264         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1265
1266         if (timediff > audit_timeout) {
1267                 smb_time_audit_log_fsp("ftruncate", timediff, fsp);
1268         }
1269
1270         return result;
1271 }
1272
1273 static int smb_time_audit_fallocate(vfs_handle_struct *handle,
1274                                     files_struct *fsp,
1275                                     uint32_t mode,
1276                                     off_t offset,
1277                                     off_t len)
1278 {
1279         int result;
1280         int saved_errno = 0;
1281         struct timespec ts1,ts2;
1282         double timediff;
1283
1284         clock_gettime_mono(&ts1);
1285         result = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1286         if (result == -1) {
1287                 saved_errno = errno;
1288         }
1289         clock_gettime_mono(&ts2);
1290         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1291
1292         if (timediff > audit_timeout) {
1293                 smb_time_audit_log_fsp("fallocate", timediff, fsp);
1294         }
1295         if (result == -1) {
1296                 errno = saved_errno;
1297         }
1298         return result;
1299 }
1300
1301 static bool smb_time_audit_lock(vfs_handle_struct *handle, files_struct *fsp,
1302                                 int op, off_t offset, off_t count,
1303                                 int type)
1304 {
1305         bool result;
1306         struct timespec ts1,ts2;
1307         double timediff;
1308
1309         clock_gettime_mono(&ts1);
1310         result = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
1311         clock_gettime_mono(&ts2);
1312         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1313
1314         if (timediff > audit_timeout) {
1315                 smb_time_audit_log_fsp("lock", timediff, fsp);
1316         }
1317
1318         return result;
1319 }
1320
1321 static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
1322                                        struct files_struct *fsp,
1323                                        uint32_t share_mode, uint32_t access_mask)
1324 {
1325         int result;
1326         struct timespec ts1,ts2;
1327         double timediff;
1328
1329         clock_gettime_mono(&ts1);
1330         result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode,
1331                                            access_mask);
1332         clock_gettime_mono(&ts2);
1333         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1334
1335         if (timediff > audit_timeout) {
1336                 smb_time_audit_log_fsp("kernel_flock", timediff, fsp);
1337         }
1338
1339         return result;
1340 }
1341
1342 static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
1343                                          files_struct *fsp,
1344                                          int leasetype)
1345 {
1346         int result;
1347         struct timespec ts1,ts2;
1348         double timediff;
1349
1350         clock_gettime_mono(&ts1);
1351         result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
1352         clock_gettime_mono(&ts2);
1353         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1354
1355         if (timediff > audit_timeout) {
1356                 smb_time_audit_log_fsp("linux_setlease", timediff, fsp);
1357         }
1358
1359         return result;
1360 }
1361
1362 static bool smb_time_audit_getlock(vfs_handle_struct *handle,
1363                                    files_struct *fsp,
1364                                    off_t *poffset, off_t *pcount,
1365                                    int *ptype, pid_t *ppid)
1366 {
1367         bool result;
1368         struct timespec ts1,ts2;
1369         double timediff;
1370
1371         clock_gettime_mono(&ts1);
1372         result = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype,
1373                                       ppid);
1374         clock_gettime_mono(&ts2);
1375         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1376
1377         if (timediff > audit_timeout) {
1378                 smb_time_audit_log_fsp("getlock", timediff, fsp);
1379         }
1380
1381         return result;
1382 }
1383
1384 static int smb_time_audit_symlinkat(vfs_handle_struct *handle,
1385                                 const char *link_contents,
1386                                 struct files_struct *dirfsp,
1387                                 const struct smb_filename *new_smb_fname)
1388 {
1389         int result;
1390         struct timespec ts1,ts2;
1391         double timediff;
1392
1393         clock_gettime_mono(&ts1);
1394         result = SMB_VFS_NEXT_SYMLINKAT(handle,
1395                                 link_contents,
1396                                 dirfsp,
1397                                 new_smb_fname);
1398         clock_gettime_mono(&ts2);
1399         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1400
1401         if (timediff > audit_timeout) {
1402                 smb_time_audit_log_fname("symlinkat", timediff,
1403                         new_smb_fname->base_name);
1404         }
1405
1406         return result;
1407 }
1408
1409 static int smb_time_audit_readlinkat(vfs_handle_struct *handle,
1410                                 files_struct *dirfsp,
1411                                 const struct smb_filename *smb_fname,
1412                                 char *buf,
1413                                 size_t bufsiz)
1414 {
1415         int result;
1416         struct timespec ts1,ts2;
1417         double timediff;
1418
1419         clock_gettime_mono(&ts1);
1420         result = SMB_VFS_NEXT_READLINKAT(handle,
1421                                 dirfsp,
1422                                 smb_fname,
1423                                 buf,
1424                                 bufsiz);
1425         clock_gettime_mono(&ts2);
1426         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1427
1428         if (timediff > audit_timeout) {
1429                 smb_time_audit_log_fname("readlinkat", timediff,
1430                                 smb_fname->base_name);
1431         }
1432
1433         return result;
1434 }
1435
1436 static int smb_time_audit_linkat(vfs_handle_struct *handle,
1437                                 files_struct *srcfsp,
1438                                 const struct smb_filename *old_smb_fname,
1439                                 files_struct *dstfsp,
1440                                 const struct smb_filename *new_smb_fname,
1441                                 int flags)
1442 {
1443         int result;
1444         struct timespec ts1,ts2;
1445         double timediff;
1446
1447         clock_gettime_mono(&ts1);
1448         result = SMB_VFS_NEXT_LINKAT(handle,
1449                         srcfsp,
1450                         old_smb_fname,
1451                         dstfsp,
1452                         new_smb_fname,
1453                         flags);
1454         clock_gettime_mono(&ts2);
1455         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1456
1457         if (timediff > audit_timeout) {
1458                 smb_time_audit_log_fname("linkat", timediff,
1459                         new_smb_fname->base_name);
1460         }
1461
1462         return result;
1463 }
1464
1465 static int smb_time_audit_mknodat(vfs_handle_struct *handle,
1466                                 files_struct *dirfsp,
1467                                 const struct smb_filename *smb_fname,
1468                                 mode_t mode,
1469                                 SMB_DEV_T dev)
1470 {
1471         int result;
1472         struct timespec ts1,ts2;
1473         double timediff;
1474
1475         clock_gettime_mono(&ts1);
1476         result = SMB_VFS_NEXT_MKNODAT(handle,
1477                                 dirfsp,
1478                                 smb_fname,
1479                                 mode,
1480                                 dev);
1481         clock_gettime_mono(&ts2);
1482         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1483
1484         if (timediff > audit_timeout) {
1485                 smb_time_audit_log_smb_fname("mknodat", timediff, smb_fname);
1486         }
1487
1488         return result;
1489 }
1490
1491 static struct smb_filename *smb_time_audit_realpath(vfs_handle_struct *handle,
1492                                 TALLOC_CTX *ctx,
1493                                 const struct smb_filename *smb_fname)
1494 {
1495         struct smb_filename *result_fname;
1496         struct timespec ts1,ts2;
1497         double timediff;
1498
1499         clock_gettime_mono(&ts1);
1500         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
1501         clock_gettime_mono(&ts2);
1502         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1503
1504         if (timediff > audit_timeout) {
1505                 smb_time_audit_log_fname("realpath", timediff,
1506                                 smb_fname->base_name);
1507         }
1508
1509         return result_fname;
1510 }
1511
1512 static int smb_time_audit_chflags(vfs_handle_struct *handle,
1513                                 const struct smb_filename *smb_fname,
1514                                 unsigned int flags)
1515 {
1516         int result;
1517         struct timespec ts1,ts2;
1518         double timediff;
1519
1520         clock_gettime_mono(&ts1);
1521         result = SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
1522         clock_gettime_mono(&ts2);
1523         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1524
1525         if (timediff > audit_timeout) {
1526                 smb_time_audit_log_smb_fname("chflags", timediff, smb_fname);
1527         }
1528
1529         return result;
1530 }
1531
1532 static struct file_id smb_time_audit_file_id_create(struct vfs_handle_struct *handle,
1533                                                     const SMB_STRUCT_STAT *sbuf)
1534 {
1535         struct file_id id_zero;
1536         struct file_id result;
1537         struct timespec ts1,ts2;
1538         double timediff;
1539
1540         ZERO_STRUCT(id_zero);
1541
1542         clock_gettime_mono(&ts1);
1543         result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
1544         clock_gettime_mono(&ts2);
1545         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1546
1547         if (timediff > audit_timeout) {
1548                 smb_time_audit_log("file_id_create", timediff);
1549         }
1550
1551         return result;
1552 }
1553
1554 static uint64_t smb_time_audit_fs_file_id(struct vfs_handle_struct *handle,
1555                                           const SMB_STRUCT_STAT *sbuf)
1556 {
1557         uint64_t result;
1558         struct timespec ts1,ts2;
1559         double timediff;
1560
1561         clock_gettime_mono(&ts1);
1562         result = SMB_VFS_NEXT_FS_FILE_ID(handle, sbuf);
1563         clock_gettime_mono(&ts2);
1564         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1565
1566         if (timediff > audit_timeout) {
1567                 smb_time_audit_log("fs_file_id", timediff);
1568         }
1569
1570         return result;
1571 }
1572
1573 static NTSTATUS smb_time_audit_streaminfo(vfs_handle_struct *handle,
1574                                           struct files_struct *fsp,
1575                                           const struct smb_filename *smb_fname,
1576                                           TALLOC_CTX *mem_ctx,
1577                                           unsigned int *pnum_streams,
1578                                           struct stream_struct **pstreams)
1579 {
1580         NTSTATUS result;
1581         struct timespec ts1,ts2;
1582         double timediff;
1583
1584         clock_gettime_mono(&ts1);
1585         result = SMB_VFS_NEXT_STREAMINFO(handle, fsp, smb_fname, mem_ctx,
1586                                          pnum_streams, pstreams);
1587         clock_gettime_mono(&ts2);
1588         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1589
1590         if (timediff > audit_timeout) {
1591                 smb_time_audit_log_fsp("streaminfo", timediff, fsp);
1592         }
1593
1594         return result;
1595 }
1596
1597 static int smb_time_audit_get_real_filename(struct vfs_handle_struct *handle,
1598                                             const char *path,
1599                                             const char *name,
1600                                             TALLOC_CTX *mem_ctx,
1601                                             char **found_name)
1602 {
1603         int result;
1604         struct timespec ts1,ts2;
1605         double timediff;
1606
1607         clock_gettime_mono(&ts1);
1608         result = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx,
1609                                                 found_name);
1610         clock_gettime_mono(&ts2);
1611         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1612
1613         if (timediff > audit_timeout) {
1614                 smb_time_audit_log_fname("get_real_filename", timediff, path);
1615         }
1616
1617         return result;
1618 }
1619
1620 static const char *smb_time_audit_connectpath(vfs_handle_struct *handle,
1621                                         const struct smb_filename *smb_fname)
1622 {
1623         const char *result;
1624         struct timespec ts1,ts2;
1625         double timediff;
1626
1627         clock_gettime_mono(&ts1);
1628         result = SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname);
1629         clock_gettime_mono(&ts2);
1630         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1631
1632         if (timediff > audit_timeout) {
1633                 smb_time_audit_log_fname("connectpath", timediff,
1634                         smb_fname->base_name);
1635         }
1636
1637         return result;
1638 }
1639
1640 static NTSTATUS smb_time_audit_brl_lock_windows(struct vfs_handle_struct *handle,
1641                                                 struct byte_range_lock *br_lck,
1642                                                 struct lock_struct *plock)
1643 {
1644         NTSTATUS result;
1645         struct timespec ts1,ts2;
1646         double timediff;
1647
1648         clock_gettime_mono(&ts1);
1649         result = SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock);
1650         clock_gettime_mono(&ts2);
1651         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1652
1653         if (timediff > audit_timeout) {
1654                 smb_time_audit_log_fsp("brl_lock_windows", timediff,
1655                                        brl_fsp(br_lck));
1656         }
1657
1658         return result;
1659 }
1660
1661 static bool smb_time_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
1662                                               struct byte_range_lock *br_lck,
1663                                               const struct lock_struct *plock)
1664 {
1665         bool result;
1666         struct timespec ts1,ts2;
1667         double timediff;
1668
1669         clock_gettime_mono(&ts1);
1670         result = SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, br_lck, plock);
1671         clock_gettime_mono(&ts2);
1672         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1673
1674         if (timediff > audit_timeout) {
1675                 smb_time_audit_log_fsp("brl_unlock_windows", timediff,
1676                                        brl_fsp(br_lck));
1677         }
1678
1679         return result;
1680 }
1681
1682 static bool smb_time_audit_strict_lock_check(struct vfs_handle_struct *handle,
1683                                              struct files_struct *fsp,
1684                                              struct lock_struct *plock)
1685 {
1686         bool result;
1687         struct timespec ts1,ts2;
1688         double timediff;
1689
1690         clock_gettime_mono(&ts1);
1691         result = SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock);
1692         clock_gettime_mono(&ts2);
1693         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1694
1695         if (timediff > audit_timeout) {
1696                 smb_time_audit_log_fsp("strict_lock_check", timediff, fsp);
1697         }
1698
1699         return result;
1700 }
1701
1702 static NTSTATUS smb_time_audit_translate_name(struct vfs_handle_struct *handle,
1703                                               const char *name,
1704                                               enum vfs_translate_direction direction,
1705                                               TALLOC_CTX *mem_ctx,
1706                                               char **mapped_name)
1707 {
1708         NTSTATUS result;
1709         struct timespec ts1,ts2;
1710         double timediff;
1711
1712         clock_gettime_mono(&ts1);
1713         result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx,
1714                                              mapped_name);
1715         clock_gettime_mono(&ts2);
1716         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1717
1718         if (timediff > audit_timeout) {
1719                 smb_time_audit_log_fname("translate_name", timediff, name);
1720         }
1721
1722         return result;
1723 }
1724
1725 static NTSTATUS smb_time_audit_fsctl(struct vfs_handle_struct *handle,
1726                                 struct files_struct *fsp,
1727                                 TALLOC_CTX *ctx,
1728                                 uint32_t function,
1729                                 uint16_t req_flags,
1730                                 const uint8_t *_in_data,
1731                                 uint32_t in_len,
1732                                 uint8_t **_out_data,
1733                                 uint32_t max_out_len,
1734                                 uint32_t *out_len)
1735 {
1736         NTSTATUS result;
1737         struct timespec ts1,ts2;
1738         double timediff;
1739
1740         clock_gettime_mono(&ts1);
1741         result = SMB_VFS_NEXT_FSCTL(handle,
1742                                 fsp,
1743                                 ctx,
1744                                 function,
1745                                 req_flags,
1746                                 _in_data,
1747                                 in_len,
1748                                 _out_data,
1749                                 max_out_len,
1750                                 out_len);
1751         clock_gettime_mono(&ts2);
1752         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1753
1754         if (timediff > audit_timeout) {
1755                 smb_time_audit_log_fsp("fsctl", timediff, fsp);
1756         }
1757
1758         return result;
1759 }
1760
1761 static NTSTATUS smb_time_get_dos_attributes(struct vfs_handle_struct *handle,
1762                                         struct smb_filename *smb_fname,
1763                                         uint32_t *dosmode)
1764 {
1765         NTSTATUS result;
1766         struct timespec ts1,ts2;
1767         double timediff;
1768
1769         clock_gettime_mono(&ts1);
1770         result = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
1771                                 smb_fname,
1772                                 dosmode);
1773         clock_gettime_mono(&ts2);
1774         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1775
1776         if (timediff > audit_timeout) {
1777                 smb_time_audit_log_fname("get_dos_attributes",
1778                                 timediff,
1779                                 smb_fname->base_name);
1780         }
1781
1782         return result;
1783 }
1784
1785 struct smb_time_audit_get_dos_attributes_state {
1786         struct vfs_aio_state aio_state;
1787         files_struct *dir_fsp;
1788         const struct smb_filename *smb_fname;
1789         uint32_t dosmode;
1790 };
1791
1792 static void smb_time_audit_get_dos_attributes_done(struct tevent_req *subreq);
1793
1794 static struct tevent_req *smb_time_audit_get_dos_attributes_send(
1795                         TALLOC_CTX *mem_ctx,
1796                         struct tevent_context *ev,
1797                         struct vfs_handle_struct *handle,
1798                         files_struct *dir_fsp,
1799                         struct smb_filename *smb_fname)
1800 {
1801         struct tevent_req *req = NULL;
1802         struct smb_time_audit_get_dos_attributes_state *state = NULL;
1803         struct tevent_req *subreq = NULL;
1804
1805         req = tevent_req_create(mem_ctx, &state,
1806                                 struct smb_time_audit_get_dos_attributes_state);
1807         if (req == NULL) {
1808                 return NULL;
1809         }
1810         *state = (struct smb_time_audit_get_dos_attributes_state) {
1811                 .dir_fsp = dir_fsp,
1812                 .smb_fname = smb_fname,
1813         };
1814
1815         subreq = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_SEND(mem_ctx,
1816                                                       ev,
1817                                                       handle,
1818                                                       dir_fsp,
1819                                                       smb_fname);
1820         if (tevent_req_nomem(subreq, req)) {
1821                 return tevent_req_post(req, ev);
1822         }
1823         tevent_req_set_callback(subreq,
1824                                 smb_time_audit_get_dos_attributes_done,
1825                                 req);
1826
1827         return req;
1828 }
1829
1830 static void smb_time_audit_get_dos_attributes_done(struct tevent_req *subreq)
1831 {
1832         struct tevent_req *req =
1833                 tevent_req_callback_data(subreq,
1834                 struct tevent_req);
1835         struct smb_time_audit_get_dos_attributes_state *state =
1836                 tevent_req_data(req,
1837                 struct smb_time_audit_get_dos_attributes_state);
1838         NTSTATUS status;
1839
1840         status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_RECV(subreq,
1841                                                       &state->aio_state,
1842                                                       &state->dosmode);
1843         TALLOC_FREE(subreq);
1844         if (tevent_req_nterror(req, status)) {
1845                 return;
1846         }
1847
1848         tevent_req_done(req);
1849         return;
1850 }
1851
1852 static NTSTATUS smb_time_audit_get_dos_attributes_recv(struct tevent_req *req,
1853                                                 struct vfs_aio_state *aio_state,
1854                                                 uint32_t *dosmode)
1855 {
1856         struct smb_time_audit_get_dos_attributes_state *state =
1857                 tevent_req_data(req,
1858                 struct smb_time_audit_get_dos_attributes_state);
1859         NTSTATUS status;
1860         double timediff;
1861
1862         timediff = state->aio_state.duration * 1.0e-9;
1863
1864         if (timediff > audit_timeout) {
1865                 smb_time_audit_log_at("async get_dos_attributes",
1866                                       timediff,
1867                                       state->dir_fsp,
1868                                       state->smb_fname);
1869         }
1870
1871         if (tevent_req_is_nterror(req, &status)) {
1872                 tevent_req_received(req);
1873                 return status;
1874         }
1875
1876         *aio_state = state->aio_state;
1877         *dosmode = state->dosmode;
1878         tevent_req_received(req);
1879         return NT_STATUS_OK;
1880 }
1881
1882 static NTSTATUS smb_time_fget_dos_attributes(struct vfs_handle_struct *handle,
1883                                         struct files_struct *fsp,
1884                                         uint32_t *dosmode)
1885 {
1886         NTSTATUS result;
1887         struct timespec ts1,ts2;
1888         double timediff;
1889
1890         clock_gettime_mono(&ts1);
1891         result = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle,
1892                                 fsp,
1893                                 dosmode);
1894         clock_gettime_mono(&ts2);
1895         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1896
1897         if (timediff > audit_timeout) {
1898                 smb_time_audit_log_fsp("fget_dos_attributes", timediff, fsp);
1899         }
1900
1901         return result;
1902 }
1903
1904 static NTSTATUS smb_time_set_dos_attributes(struct vfs_handle_struct *handle,
1905                                         const struct smb_filename *smb_fname,
1906                                         uint32_t dosmode)
1907 {
1908         NTSTATUS result;
1909         struct timespec ts1,ts2;
1910         double timediff;
1911
1912         clock_gettime_mono(&ts1);
1913         result = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
1914                                 smb_fname,
1915                                 dosmode);
1916         clock_gettime_mono(&ts2);
1917         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1918
1919         if (timediff > audit_timeout) {
1920                 smb_time_audit_log_fname("set_dos_attributes",
1921                                 timediff,
1922                                 smb_fname->base_name);
1923         }
1924
1925         return result;
1926 }
1927
1928 static NTSTATUS smb_time_fset_dos_attributes(struct vfs_handle_struct *handle,
1929                                         struct files_struct *fsp,
1930                                         uint32_t dosmode)
1931 {
1932         NTSTATUS result;
1933         struct timespec ts1,ts2;
1934         double timediff;
1935
1936         clock_gettime_mono(&ts1);
1937         result = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle,
1938                                 fsp,
1939                                 dosmode);
1940         clock_gettime_mono(&ts2);
1941         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1942
1943         if (timediff > audit_timeout) {
1944                 smb_time_audit_log_fsp("fset_dos_attributes", timediff, fsp);
1945         }
1946
1947         return result;
1948 }
1949
1950 struct time_audit_offload_read_state {
1951         struct vfs_handle_struct *handle;
1952         struct timespec ts_send;
1953         DATA_BLOB token_blob;
1954 };
1955
1956 static void smb_time_audit_offload_read_done(struct tevent_req *subreq);
1957
1958 static struct tevent_req *smb_time_audit_offload_read_send(
1959         TALLOC_CTX *mem_ctx,
1960         struct tevent_context *ev,
1961         struct vfs_handle_struct *handle,
1962         struct files_struct *fsp,
1963         uint32_t fsctl,
1964         uint32_t ttl,
1965         off_t offset,
1966         size_t to_copy)
1967 {
1968         struct tevent_req *req = NULL;
1969         struct tevent_req *subreq = NULL;
1970         struct time_audit_offload_read_state *state = NULL;
1971
1972         req = tevent_req_create(mem_ctx, &state,
1973                                 struct time_audit_offload_read_state);
1974         if (req == NULL) {
1975                 return NULL;
1976         }
1977         state->handle = handle;
1978         clock_gettime_mono(&state->ts_send);
1979
1980         subreq = SMB_VFS_NEXT_OFFLOAD_READ_SEND(mem_ctx, ev,
1981                                                 handle, fsp,
1982                                                 fsctl, ttl,
1983                                                 offset, to_copy);
1984         if (tevent_req_nomem(subreq, req)) {
1985                 return tevent_req_post(req, ev);
1986         }
1987
1988         tevent_req_set_callback(subreq, smb_time_audit_offload_read_done, req);
1989         return req;
1990 }
1991
1992 static void smb_time_audit_offload_read_done(struct tevent_req *subreq)
1993 {
1994         struct tevent_req *req = tevent_req_callback_data(
1995                 subreq, struct tevent_req);
1996         struct time_audit_offload_read_state *state = tevent_req_data(
1997                 req, struct time_audit_offload_read_state);
1998         NTSTATUS status;
1999
2000         status = SMB_VFS_NEXT_OFFLOAD_READ_RECV(subreq,
2001                                                 state->handle,
2002                                                 state,
2003                                                 &state->token_blob);
2004         TALLOC_FREE(subreq);
2005         if (tevent_req_nterror(req, status)) {
2006                 return;
2007         }
2008         tevent_req_done(req);
2009 }
2010
2011 static NTSTATUS smb_time_audit_offload_read_recv(
2012         struct tevent_req *req,
2013         struct vfs_handle_struct *handle,
2014         TALLOC_CTX *mem_ctx,
2015         DATA_BLOB *token_blob)
2016 {
2017         struct time_audit_offload_read_state *state = tevent_req_data(
2018                 req, struct time_audit_offload_read_state);
2019         struct timespec ts_recv;
2020         double timediff;
2021         NTSTATUS status;
2022
2023         clock_gettime_mono(&ts_recv);
2024         timediff = nsec_time_diff(&ts_recv, &state->ts_send) * 1.0e-9;
2025         if (timediff > audit_timeout) {
2026                 smb_time_audit_log("offload_read", timediff);
2027         }
2028
2029         if (tevent_req_is_nterror(req, &status)) {
2030                 tevent_req_received(req);
2031                 return status;
2032         }
2033
2034         token_blob->length = state->token_blob.length;
2035         token_blob->data = talloc_move(mem_ctx, &state->token_blob.data);
2036
2037         tevent_req_received(req);
2038         return NT_STATUS_OK;
2039 }
2040
2041 struct time_audit_offload_write_state {
2042         struct timespec ts_send;
2043         struct vfs_handle_struct *handle;
2044         off_t copied;
2045 };
2046 static void smb_time_audit_offload_write_done(struct tevent_req *subreq);
2047
2048 static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_struct *handle,
2049                                                          TALLOC_CTX *mem_ctx,
2050                                                          struct tevent_context *ev,
2051                                                          uint32_t fsctl,
2052                                                          DATA_BLOB *token,
2053                                                          off_t transfer_offset,
2054                                                          struct files_struct *dest_fsp,
2055                                                          off_t dest_off,
2056                                                          off_t num)
2057 {
2058         struct tevent_req *req;
2059         struct tevent_req *subreq;
2060         struct time_audit_offload_write_state *state;
2061
2062         req = tevent_req_create(mem_ctx, &state,
2063                                 struct time_audit_offload_write_state);
2064         if (req == NULL) {
2065                 return NULL;
2066         }
2067
2068         state->handle = handle;
2069         clock_gettime_mono(&state->ts_send);
2070         subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev,
2071                                               fsctl, token, transfer_offset,
2072                                               dest_fsp, dest_off, num);
2073         if (tevent_req_nomem(subreq, req)) {
2074                 return tevent_req_post(req, ev);
2075         }
2076
2077         tevent_req_set_callback(subreq, smb_time_audit_offload_write_done, req);
2078         return req;
2079 }
2080
2081 static void smb_time_audit_offload_write_done(struct tevent_req *subreq)
2082 {
2083         struct tevent_req *req = tevent_req_callback_data(
2084                 subreq, struct tevent_req);
2085         struct time_audit_offload_write_state *state = tevent_req_data(
2086                 req, struct time_audit_offload_write_state);
2087         NTSTATUS status;
2088
2089         status = SMB_VFS_NEXT_OFFLOAD_WRITE_RECV(state->handle,
2090                                               subreq,
2091                                               &state->copied);
2092         TALLOC_FREE(subreq);
2093         if (tevent_req_nterror(req, status)) {
2094                 return;
2095         }
2096         tevent_req_done(req);
2097 }
2098
2099 static NTSTATUS smb_time_audit_offload_write_recv(struct vfs_handle_struct *handle,
2100                                                struct tevent_req *req,
2101                                                off_t *copied)
2102 {
2103         struct time_audit_offload_write_state *state = tevent_req_data(
2104                 req, struct time_audit_offload_write_state);
2105         struct timespec ts_recv;
2106         double timediff;
2107         NTSTATUS status;
2108
2109         clock_gettime_mono(&ts_recv);
2110         timediff = nsec_time_diff(&ts_recv, &state->ts_send)*1.0e-9;
2111         if (timediff > audit_timeout) {
2112                 smb_time_audit_log("offload_write", timediff);
2113         }
2114
2115         *copied = state->copied;
2116         if (tevent_req_is_nterror(req, &status)) {
2117                 tevent_req_received(req);
2118                 return status;
2119         }
2120
2121         tevent_req_received(req);
2122         return NT_STATUS_OK;
2123 }
2124
2125 static NTSTATUS smb_time_audit_get_compression(vfs_handle_struct *handle,
2126                                                TALLOC_CTX *mem_ctx,
2127                                                struct files_struct *fsp,
2128                                                struct smb_filename *smb_fname,
2129                                                uint16_t *_compression_fmt)
2130 {
2131         NTSTATUS result;
2132         struct timespec ts1,ts2;
2133         double timediff;
2134
2135         clock_gettime_mono(&ts1);
2136         result = SMB_VFS_NEXT_GET_COMPRESSION(handle, mem_ctx, fsp, smb_fname,
2137                                               _compression_fmt);
2138         clock_gettime_mono(&ts2);
2139         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2140
2141         if (timediff > audit_timeout) {
2142                 if (fsp !=  NULL) {
2143                         smb_time_audit_log_fsp("get_compression",
2144                                                timediff, fsp);
2145                 } else {
2146                         smb_time_audit_log_smb_fname("get_compression",
2147                                                      timediff, smb_fname);
2148                 }
2149         }
2150
2151         return result;
2152 }
2153
2154 static NTSTATUS smb_time_audit_set_compression(vfs_handle_struct *handle,
2155                                                TALLOC_CTX *mem_ctx,
2156                                                struct files_struct *fsp,
2157                                                uint16_t compression_fmt)
2158 {
2159         NTSTATUS result;
2160         struct timespec ts1,ts2;
2161         double timediff;
2162
2163         clock_gettime_mono(&ts1);
2164         result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
2165                                               compression_fmt);
2166         clock_gettime_mono(&ts2);
2167         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2168
2169         if (timediff > audit_timeout) {
2170                 smb_time_audit_log_fsp("set_compression", timediff, fsp);
2171         }
2172
2173         return result;
2174 }
2175
2176 static NTSTATUS smb_time_audit_readdir_attr(struct vfs_handle_struct *handle,
2177                                             const struct smb_filename *fname,
2178                                             TALLOC_CTX *mem_ctx,
2179                                             struct readdir_attr_data **pattr_data)
2180 {
2181         NTSTATUS status;
2182         struct timespec ts1,ts2;
2183         double timediff;
2184
2185         clock_gettime_mono(&ts1);
2186         status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
2187         clock_gettime_mono(&ts2);
2188         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2189
2190         if (timediff > audit_timeout) {
2191                 smb_time_audit_log_smb_fname("readdir_attr", timediff, fname);
2192         }
2193
2194         return status;
2195 }
2196
2197 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
2198                                            files_struct *fsp,
2199                                            uint32_t security_info,
2200                                            TALLOC_CTX *mem_ctx,
2201                                            struct security_descriptor **ppdesc)
2202 {
2203         NTSTATUS result;
2204         struct timespec ts1,ts2;
2205         double timediff;
2206
2207         clock_gettime_mono(&ts1);
2208         result = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
2209                                           mem_ctx, ppdesc);
2210         clock_gettime_mono(&ts2);
2211         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2212
2213         if (timediff > audit_timeout) {
2214                 smb_time_audit_log_fsp("fget_nt_acl", timediff, fsp);
2215         }
2216
2217         return result;
2218 }
2219
2220 static NTSTATUS smb_time_audit_get_nt_acl(vfs_handle_struct *handle,
2221                                           const struct smb_filename *smb_fname,
2222                                           uint32_t security_info,
2223                                           TALLOC_CTX *mem_ctx,
2224                                           struct security_descriptor **ppdesc)
2225 {
2226         NTSTATUS result;
2227         struct timespec ts1,ts2;
2228         double timediff;
2229
2230         clock_gettime_mono(&ts1);
2231         result = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2232                                          mem_ctx, ppdesc);
2233         clock_gettime_mono(&ts2);
2234         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2235
2236         if (timediff > audit_timeout) {
2237                 smb_time_audit_log_fname("get_nt_acl",
2238                         timediff,
2239                         smb_fname->base_name);
2240         }
2241
2242         return result;
2243 }
2244
2245 static NTSTATUS smb_time_audit_fset_nt_acl(vfs_handle_struct *handle,
2246                                            files_struct *fsp,
2247                                            uint32_t security_info_sent,
2248                                            const struct security_descriptor *psd)
2249 {
2250         NTSTATUS result;
2251         struct timespec ts1,ts2;
2252         double timediff;
2253
2254         clock_gettime_mono(&ts1);
2255         result = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent,
2256                                           psd);
2257         clock_gettime_mono(&ts2);
2258         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2259
2260         if (timediff > audit_timeout) {
2261                 smb_time_audit_log_fsp("fset_nt_acl", timediff, fsp);
2262         }
2263
2264         return result;
2265 }
2266
2267 static NTSTATUS smb_time_audit_audit_file(struct vfs_handle_struct *handle,
2268                                 struct smb_filename *smb_fname,
2269                                 struct security_acl *sacl,
2270                                 uint32_t access_requested,
2271                                 uint32_t access_denied)
2272 {
2273         NTSTATUS result;
2274         struct timespec ts1,ts2;
2275         double timediff;
2276
2277         clock_gettime_mono(&ts1);
2278         result = SMB_VFS_NEXT_AUDIT_FILE(handle,
2279                                         smb_fname,
2280                                         sacl,
2281                                         access_requested,
2282                                         access_denied);
2283         clock_gettime_mono(&ts2);
2284         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2285
2286         if (timediff > audit_timeout) {
2287                 smb_time_audit_log_fname("audit_file",
2288                         timediff,
2289                         smb_fname->base_name);
2290         }
2291
2292         return result;
2293 }
2294
2295 static SMB_ACL_T smb_time_audit_sys_acl_get_file(vfs_handle_struct *handle,
2296                                         const struct smb_filename *smb_fname,
2297                                         SMB_ACL_TYPE_T type,
2298                                         TALLOC_CTX *mem_ctx)
2299 {
2300         SMB_ACL_T result;
2301         struct timespec ts1,ts2;
2302         double timediff;
2303
2304         clock_gettime_mono(&ts1);
2305         result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, smb_fname,
2306                                 type, mem_ctx);
2307         clock_gettime_mono(&ts2);
2308         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2309
2310         if (timediff > audit_timeout) {
2311                 smb_time_audit_log_fname("sys_acl_get_file", timediff,
2312                         smb_fname->base_name);
2313         }
2314
2315         return result;
2316 }
2317
2318 static SMB_ACL_T smb_time_audit_sys_acl_get_fd(vfs_handle_struct *handle,
2319                                                files_struct *fsp,
2320                                                TALLOC_CTX *mem_ctx)
2321 {
2322         SMB_ACL_T result;
2323         struct timespec ts1,ts2;
2324         double timediff;
2325
2326         clock_gettime_mono(&ts1);
2327         result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
2328         clock_gettime_mono(&ts2);
2329         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2330
2331         if (timediff > audit_timeout) {
2332                 smb_time_audit_log_fsp("sys_acl_get_fd", timediff, fsp);
2333         }
2334
2335         return result;
2336 }
2337
2338
2339 static int smb_time_audit_sys_acl_blob_get_file(vfs_handle_struct *handle,
2340                                 const struct smb_filename *smb_fname,
2341                                 TALLOC_CTX *mem_ctx,
2342                                 char **blob_description,
2343                                 DATA_BLOB *blob)
2344 {
2345         int result;
2346         struct timespec ts1,ts2;
2347         double timediff;
2348
2349         clock_gettime_mono(&ts1);
2350         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle, smb_fname,
2351                                 mem_ctx, blob_description, blob);
2352         clock_gettime_mono(&ts2);
2353         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2354
2355         if (timediff > audit_timeout) {
2356                 smb_time_audit_log("sys_acl_blob_get_file", timediff);
2357         }
2358
2359         return result;
2360 }
2361
2362 static int smb_time_audit_sys_acl_blob_get_fd(vfs_handle_struct *handle,
2363                                               files_struct *fsp,
2364                                               TALLOC_CTX *mem_ctx, 
2365                                               char **blob_description,
2366                                               DATA_BLOB *blob)
2367 {
2368         int result;
2369         struct timespec ts1,ts2;
2370         double timediff;
2371
2372         clock_gettime_mono(&ts1);
2373         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx, blob_description, blob);
2374         clock_gettime_mono(&ts2);
2375         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2376
2377         if (timediff > audit_timeout) {
2378                 smb_time_audit_log("sys_acl_blob_get_fd", timediff);
2379         }
2380
2381         return result;
2382 }
2383
2384 static int smb_time_audit_sys_acl_set_file(vfs_handle_struct *handle,
2385                                            const struct smb_filename *smb_fname,
2386                                            SMB_ACL_TYPE_T acltype,
2387                                            SMB_ACL_T theacl)
2388 {
2389         int result;
2390         struct timespec ts1,ts2;
2391         double timediff;
2392
2393         clock_gettime_mono(&ts1);
2394         result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, smb_fname, acltype,
2395                                                theacl);
2396         clock_gettime_mono(&ts2);
2397         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2398
2399         if (timediff > audit_timeout) {
2400                 smb_time_audit_log_fname("sys_acl_set_file", timediff,
2401                         smb_fname->base_name);
2402         }
2403
2404         return result;
2405 }
2406
2407 static int smb_time_audit_sys_acl_set_fd(vfs_handle_struct *handle,
2408                                          files_struct *fsp,
2409                                          SMB_ACL_T theacl)
2410 {
2411         int result;
2412         struct timespec ts1,ts2;
2413         double timediff;
2414
2415         clock_gettime_mono(&ts1);
2416         result = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
2417         clock_gettime_mono(&ts2);
2418         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2419
2420         if (timediff > audit_timeout) {
2421                 smb_time_audit_log_fsp("sys_acl_set_fd", timediff, fsp);
2422         }
2423
2424         return result;
2425 }
2426
2427 static int smb_time_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
2428                                 const struct smb_filename *smb_fname)
2429 {
2430         int result;
2431         struct timespec ts1,ts2;
2432         double timediff;
2433
2434         clock_gettime_mono(&ts1);
2435         result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, smb_fname);
2436         clock_gettime_mono(&ts2);
2437         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2438
2439         if (timediff > audit_timeout) {
2440                 smb_time_audit_log_fname("sys_acl_delete_def_file", timediff,
2441                         smb_fname->base_name);
2442         }
2443
2444         return result;
2445 }
2446
2447 static ssize_t smb_time_audit_getxattr(struct vfs_handle_struct *handle,
2448                                 const struct smb_filename *smb_fname,
2449                                 const char *name,
2450                                 void *value,
2451                                 size_t size)
2452 {
2453         ssize_t result;
2454         struct timespec ts1,ts2;
2455         double timediff;
2456
2457         clock_gettime_mono(&ts1);
2458         result = SMB_VFS_NEXT_GETXATTR(handle, smb_fname, name, value, size);
2459         clock_gettime_mono(&ts2);
2460         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2461
2462         if (timediff > audit_timeout) {
2463                 smb_time_audit_log_fname("getxattr", timediff,
2464                         smb_fname->base_name);
2465         }
2466
2467         return result;
2468 }
2469
2470 struct smb_time_audit_getxattrat_state {
2471         struct vfs_aio_state aio_state;
2472         files_struct *dir_fsp;
2473         const struct smb_filename *smb_fname;
2474         const char *xattr_name;
2475         ssize_t xattr_size;
2476         uint8_t *xattr_value;
2477 };
2478
2479 static void smb_time_audit_getxattrat_done(struct tevent_req *subreq);
2480
2481 static struct tevent_req *smb_time_audit_getxattrat_send(
2482                         TALLOC_CTX *mem_ctx,
2483                         struct tevent_context *ev,
2484                         struct vfs_handle_struct *handle,
2485                         files_struct *dir_fsp,
2486                         const struct smb_filename *smb_fname,
2487                         const char *xattr_name,
2488                         size_t alloc_hint)
2489 {
2490         struct tevent_req *req = NULL;
2491         struct tevent_req *subreq = NULL;
2492         struct smb_time_audit_getxattrat_state *state = NULL;
2493
2494         req = tevent_req_create(mem_ctx, &state,
2495                                 struct smb_time_audit_getxattrat_state);
2496         if (req == NULL) {
2497                 return NULL;
2498         }
2499         *state = (struct smb_time_audit_getxattrat_state) {
2500                 .dir_fsp = dir_fsp,
2501                 .smb_fname = smb_fname,
2502                 .xattr_name = xattr_name,
2503         };
2504
2505         subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
2506                                               ev,
2507                                               handle,
2508                                               dir_fsp,
2509                                               smb_fname,
2510                                               xattr_name,
2511                                               alloc_hint);
2512         if (tevent_req_nomem(subreq, req)) {
2513                 return tevent_req_post(req, ev);
2514         }
2515         tevent_req_set_callback(subreq, smb_time_audit_getxattrat_done, req);
2516
2517         return req;
2518 }
2519
2520 static void smb_time_audit_getxattrat_done(struct tevent_req *subreq)
2521 {
2522         struct tevent_req *req = tevent_req_callback_data(
2523                 subreq, struct tevent_req);
2524         struct smb_time_audit_getxattrat_state *state = tevent_req_data(
2525                 req, struct smb_time_audit_getxattrat_state);
2526
2527         state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq,
2528                                                          &state->aio_state,
2529                                                          state,
2530                                                          &state->xattr_value);
2531         TALLOC_FREE(subreq);
2532         if (state->xattr_size == -1) {
2533                 tevent_req_error(req, state->aio_state.error);
2534                 return;
2535         }
2536
2537         tevent_req_done(req);
2538 }
2539
2540 static ssize_t smb_time_audit_getxattrat_recv(struct tevent_req *req,
2541                                               struct vfs_aio_state *aio_state,
2542                                               TALLOC_CTX *mem_ctx,
2543                                               uint8_t **xattr_value)
2544 {
2545         struct smb_time_audit_getxattrat_state *state = tevent_req_data(
2546                 req, struct smb_time_audit_getxattrat_state);
2547         ssize_t xattr_size;
2548         double timediff;
2549
2550         timediff = state->aio_state.duration * 1.0e-9;
2551
2552         if (timediff > audit_timeout) {
2553                 smb_time_audit_log_at("async getxattrat",
2554                                       timediff,
2555                                       state->dir_fsp,
2556                                       state->smb_fname);
2557         }
2558
2559         if (tevent_req_is_unix_error(req, &aio_state->error)) {
2560                 tevent_req_received(req);
2561                 return -1;
2562         }
2563
2564         *aio_state = state->aio_state;
2565         xattr_size = state->xattr_size;
2566         if (xattr_value != NULL) {
2567                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2568         }
2569
2570         tevent_req_received(req);
2571         return xattr_size;
2572 }
2573
2574 static ssize_t smb_time_audit_fgetxattr(struct vfs_handle_struct *handle,
2575                                         struct files_struct *fsp,
2576                                         const char *name, void *value,
2577                                         size_t size)
2578 {
2579         ssize_t result;
2580         struct timespec ts1,ts2;
2581         double timediff;
2582
2583         clock_gettime_mono(&ts1);
2584         result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
2585         clock_gettime_mono(&ts2);
2586         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2587
2588         if (timediff > audit_timeout) {
2589                 smb_time_audit_log_fsp("fgetxattr", timediff, fsp);
2590         }
2591
2592         return result;
2593 }
2594
2595 static ssize_t smb_time_audit_listxattr(struct vfs_handle_struct *handle,
2596                                         const struct smb_filename *smb_fname,
2597                                         char *list,
2598                                         size_t size)
2599 {
2600         ssize_t result;
2601         struct timespec ts1,ts2;
2602         double timediff;
2603
2604         clock_gettime_mono(&ts1);
2605         result = SMB_VFS_NEXT_LISTXATTR(handle, smb_fname, list, size);
2606         clock_gettime_mono(&ts2);
2607         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2608
2609         if (timediff > audit_timeout) {
2610                 smb_time_audit_log_fname("listxattr", timediff,
2611                                 smb_fname->base_name);
2612         }
2613
2614         return result;
2615 }
2616
2617 static ssize_t smb_time_audit_flistxattr(struct vfs_handle_struct *handle,
2618                                          struct files_struct *fsp, char *list,
2619                                          size_t size)
2620 {
2621         ssize_t result;
2622         struct timespec ts1,ts2;
2623         double timediff;
2624
2625         clock_gettime_mono(&ts1);
2626         result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
2627         clock_gettime_mono(&ts2);
2628         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2629
2630         if (timediff > audit_timeout) {
2631                 smb_time_audit_log_fsp("flistxattr", timediff, fsp);
2632         }
2633
2634         return result;
2635 }
2636
2637 static int smb_time_audit_removexattr(struct vfs_handle_struct *handle,
2638                                 const struct smb_filename *smb_fname,
2639                                 const char *name)
2640 {
2641         int result;
2642         struct timespec ts1,ts2;
2643         double timediff;
2644
2645         clock_gettime_mono(&ts1);
2646         result = SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, name);
2647         clock_gettime_mono(&ts2);
2648         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2649
2650         if (timediff > audit_timeout) {
2651                 smb_time_audit_log_fname("removexattr", timediff,
2652                         smb_fname->base_name);
2653         }
2654
2655         return result;
2656 }
2657
2658 static int smb_time_audit_fremovexattr(struct vfs_handle_struct *handle,
2659                                        struct files_struct *fsp,
2660                                        const char *name)
2661 {
2662         int result;
2663         struct timespec ts1,ts2;
2664         double timediff;
2665
2666         clock_gettime_mono(&ts1);
2667         result = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
2668         clock_gettime_mono(&ts2);
2669         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2670
2671         if (timediff > audit_timeout) {
2672                 smb_time_audit_log_fsp("fremovexattr", timediff, fsp);
2673         }
2674
2675         return result;
2676 }
2677
2678 static int smb_time_audit_setxattr(struct vfs_handle_struct *handle,
2679                                 const struct smb_filename *smb_fname,
2680                                 const char *name,
2681                                 const void *value,
2682                                 size_t size,
2683                                 int flags)
2684 {
2685         int result;
2686         struct timespec ts1,ts2;
2687         double timediff;
2688
2689         clock_gettime_mono(&ts1);
2690         result = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, name, value, size,
2691                                        flags);
2692         clock_gettime_mono(&ts2);
2693         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2694
2695         if (timediff > audit_timeout) {
2696                 smb_time_audit_log_fname("setxattr", timediff,
2697                                 smb_fname->base_name);
2698         }
2699
2700         return result;
2701 }
2702
2703 static int smb_time_audit_fsetxattr(struct vfs_handle_struct *handle,
2704                                     struct files_struct *fsp, const char *name,
2705                                     const void *value, size_t size, int flags)
2706 {
2707         int result;
2708         struct timespec ts1,ts2;
2709         double timediff;
2710
2711         clock_gettime_mono(&ts1);
2712         result = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags);
2713         clock_gettime_mono(&ts2);
2714         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2715
2716         if (timediff > audit_timeout) {
2717                 smb_time_audit_log_fsp("fsetxattr", timediff, fsp);
2718         }
2719
2720         return result;
2721 }
2722
2723 static bool smb_time_audit_aio_force(struct vfs_handle_struct *handle,
2724                                      struct files_struct *fsp)
2725 {
2726         bool result;
2727         struct timespec ts1,ts2;
2728         double timediff;
2729
2730         clock_gettime_mono(&ts1);
2731         result = SMB_VFS_NEXT_AIO_FORCE(handle, fsp);
2732         clock_gettime_mono(&ts2);
2733         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2734
2735         if (timediff > audit_timeout) {
2736                 smb_time_audit_log_fsp("aio_force", timediff, fsp);
2737         }
2738
2739         return result;
2740 }
2741
2742 static NTSTATUS smb_time_audit_durable_cookie(struct vfs_handle_struct *handle,
2743                                               struct files_struct *fsp,
2744                                               TALLOC_CTX *mem_ctx,
2745                                               DATA_BLOB *cookie)
2746 {
2747         NTSTATUS result;
2748         struct timespec ts1,ts2;
2749         double timediff;
2750
2751         clock_gettime_mono(&ts1);
2752         result = SMB_VFS_NEXT_DURABLE_COOKIE(handle, fsp, mem_ctx, cookie);
2753         clock_gettime_mono(&ts2);
2754         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2755
2756         if (timediff > audit_timeout) {
2757                 smb_time_audit_log_fsp("durable_cookie", timediff, fsp);
2758         }
2759
2760         return result;
2761 }
2762
2763 static NTSTATUS smb_time_audit_durable_disconnect(struct vfs_handle_struct *handle,
2764                                                   struct files_struct *fsp,
2765                                                   const DATA_BLOB old_cookie,
2766                                                   TALLOC_CTX *mem_ctx,
2767                                                   DATA_BLOB *new_cookie)
2768 {
2769         NTSTATUS result;
2770         struct timespec ts1,ts2;
2771         double timediff;
2772
2773         clock_gettime_mono(&ts1);
2774         result = SMB_VFS_NEXT_DURABLE_DISCONNECT(handle, fsp, old_cookie,
2775                                                  mem_ctx, new_cookie);
2776         clock_gettime_mono(&ts2);
2777         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2778
2779         if (timediff > audit_timeout) {
2780                 smb_time_audit_log_fsp("durable_disconnect", timediff, fsp);
2781         }
2782
2783         return result;
2784 }
2785
2786 static NTSTATUS smb_time_audit_durable_reconnect(struct vfs_handle_struct *handle,
2787                                                  struct smb_request *smb1req,
2788                                                  struct smbXsrv_open *op,
2789                                                  const DATA_BLOB old_cookie,
2790                                                  TALLOC_CTX *mem_ctx,
2791                                                  struct files_struct **fsp,
2792                                                  DATA_BLOB *new_cookie)
2793 {
2794         NTSTATUS result;
2795         struct timespec ts1,ts2;
2796         double timediff;
2797
2798         clock_gettime_mono(&ts1);
2799         result = SMB_VFS_NEXT_DURABLE_RECONNECT(handle, smb1req, op, old_cookie,
2800                                                 mem_ctx, fsp, new_cookie);
2801         clock_gettime_mono(&ts2);
2802         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2803
2804         if (timediff > audit_timeout) {
2805                 smb_time_audit_log("durable_reconnect", timediff);
2806         }
2807
2808         return result;
2809 }
2810
2811 /* VFS operations */
2812
2813 static struct vfs_fn_pointers vfs_time_audit_fns = {
2814         .connect_fn = smb_time_audit_connect,
2815         .disconnect_fn = smb_time_audit_disconnect,
2816         .disk_free_fn = smb_time_audit_disk_free,
2817         .get_quota_fn = smb_time_audit_get_quota,
2818         .set_quota_fn = smb_time_audit_set_quota,
2819         .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
2820         .statvfs_fn = smb_time_audit_statvfs,
2821         .fs_capabilities_fn = smb_time_audit_fs_capabilities,
2822         .get_dfs_referrals_fn = smb_time_audit_get_dfs_referrals,
2823         .opendir_fn = smb_time_audit_opendir,
2824         .fdopendir_fn = smb_time_audit_fdopendir,
2825         .readdir_fn = smb_time_audit_readdir,
2826         .seekdir_fn = smb_time_audit_seekdir,
2827         .telldir_fn = smb_time_audit_telldir,
2828         .rewind_dir_fn = smb_time_audit_rewinddir,
2829         .mkdirat_fn = smb_time_audit_mkdirat,
2830         .rmdir_fn = smb_time_audit_rmdir,
2831         .closedir_fn = smb_time_audit_closedir,
2832         .open_fn = smb_time_audit_open,
2833         .create_file_fn = smb_time_audit_create_file,
2834         .close_fn = smb_time_audit_close,
2835         .pread_fn = smb_time_audit_pread,
2836         .pread_send_fn = smb_time_audit_pread_send,
2837         .pread_recv_fn = smb_time_audit_pread_recv,
2838         .pwrite_fn = smb_time_audit_pwrite,
2839         .pwrite_send_fn = smb_time_audit_pwrite_send,
2840         .pwrite_recv_fn = smb_time_audit_pwrite_recv,
2841         .lseek_fn = smb_time_audit_lseek,
2842         .sendfile_fn = smb_time_audit_sendfile,
2843         .recvfile_fn = smb_time_audit_recvfile,
2844         .renameat_fn = smb_time_audit_renameat,
2845         .fsync_send_fn = smb_time_audit_fsync_send,
2846         .fsync_recv_fn = smb_time_audit_fsync_recv,
2847         .stat_fn = smb_time_audit_stat,
2848         .fstat_fn = smb_time_audit_fstat,
2849         .lstat_fn = smb_time_audit_lstat,
2850         .get_alloc_size_fn = smb_time_audit_get_alloc_size,
2851         .unlink_fn = smb_time_audit_unlink,
2852         .chmod_fn = smb_time_audit_chmod,
2853         .fchmod_fn = smb_time_audit_fchmod,
2854         .chown_fn = smb_time_audit_chown,
2855         .fchown_fn = smb_time_audit_fchown,
2856         .lchown_fn = smb_time_audit_lchown,
2857         .chdir_fn = smb_time_audit_chdir,
2858         .getwd_fn = smb_time_audit_getwd,
2859         .ntimes_fn = smb_time_audit_ntimes,
2860         .ftruncate_fn = smb_time_audit_ftruncate,
2861         .fallocate_fn = smb_time_audit_fallocate,
2862         .lock_fn = smb_time_audit_lock,
2863         .kernel_flock_fn = smb_time_audit_kernel_flock,
2864         .linux_setlease_fn = smb_time_audit_linux_setlease,
2865         .getlock_fn = smb_time_audit_getlock,
2866         .symlinkat_fn = smb_time_audit_symlinkat,
2867         .readlinkat_fn = smb_time_audit_readlinkat,
2868         .linkat_fn = smb_time_audit_linkat,
2869         .mknodat_fn = smb_time_audit_mknodat,
2870         .realpath_fn = smb_time_audit_realpath,
2871         .chflags_fn = smb_time_audit_chflags,
2872         .file_id_create_fn = smb_time_audit_file_id_create,
2873         .fs_file_id_fn = smb_time_audit_fs_file_id,
2874         .offload_read_send_fn = smb_time_audit_offload_read_send,
2875         .offload_read_recv_fn = smb_time_audit_offload_read_recv,
2876         .offload_write_send_fn = smb_time_audit_offload_write_send,
2877         .offload_write_recv_fn = smb_time_audit_offload_write_recv,
2878         .get_compression_fn = smb_time_audit_get_compression,
2879         .set_compression_fn = smb_time_audit_set_compression,
2880         .snap_check_path_fn = smb_time_audit_snap_check_path,
2881         .snap_create_fn = smb_time_audit_snap_create,
2882         .snap_delete_fn = smb_time_audit_snap_delete,
2883         .streaminfo_fn = smb_time_audit_streaminfo,
2884         .get_real_filename_fn = smb_time_audit_get_real_filename,
2885         .connectpath_fn = smb_time_audit_connectpath,
2886         .brl_lock_windows_fn = smb_time_audit_brl_lock_windows,
2887         .brl_unlock_windows_fn = smb_time_audit_brl_unlock_windows,
2888         .strict_lock_check_fn = smb_time_audit_strict_lock_check,
2889         .translate_name_fn = smb_time_audit_translate_name,
2890         .fsctl_fn = smb_time_audit_fsctl,
2891         .get_dos_attributes_fn = smb_time_get_dos_attributes,
2892         .get_dos_attributes_send_fn = smb_time_audit_get_dos_attributes_send,
2893         .get_dos_attributes_recv_fn = smb_time_audit_get_dos_attributes_recv,
2894         .fget_dos_attributes_fn = smb_time_fget_dos_attributes,
2895         .set_dos_attributes_fn = smb_time_set_dos_attributes,
2896         .fset_dos_attributes_fn = smb_time_fset_dos_attributes,
2897         .fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
2898         .get_nt_acl_fn = smb_time_audit_get_nt_acl,
2899         .fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
2900         .audit_file_fn = smb_time_audit_audit_file,
2901         .sys_acl_get_file_fn = smb_time_audit_sys_acl_get_file,
2902         .sys_acl_get_fd_fn = smb_time_audit_sys_acl_get_fd,
2903         .sys_acl_blob_get_file_fn = smb_time_audit_sys_acl_blob_get_file,
2904         .sys_acl_blob_get_fd_fn = smb_time_audit_sys_acl_blob_get_fd,
2905         .sys_acl_set_file_fn = smb_time_audit_sys_acl_set_file,
2906         .sys_acl_set_fd_fn = smb_time_audit_sys_acl_set_fd,
2907         .sys_acl_delete_def_file_fn = smb_time_audit_sys_acl_delete_def_file,
2908         .getxattr_fn = smb_time_audit_getxattr,
2909         .getxattrat_send_fn = smb_time_audit_getxattrat_send,
2910         .getxattrat_recv_fn = smb_time_audit_getxattrat_recv,
2911         .fgetxattr_fn = smb_time_audit_fgetxattr,
2912         .listxattr_fn = smb_time_audit_listxattr,
2913         .flistxattr_fn = smb_time_audit_flistxattr,
2914         .removexattr_fn = smb_time_audit_removexattr,
2915         .fremovexattr_fn = smb_time_audit_fremovexattr,
2916         .setxattr_fn = smb_time_audit_setxattr,
2917         .fsetxattr_fn = smb_time_audit_fsetxattr,
2918         .aio_force_fn = smb_time_audit_aio_force,
2919         .durable_cookie_fn = smb_time_audit_durable_cookie,
2920         .durable_disconnect_fn = smb_time_audit_durable_disconnect,
2921         .durable_reconnect_fn = smb_time_audit_durable_reconnect,
2922         .readdir_attr_fn = smb_time_audit_readdir_attr,
2923 };
2924
2925
2926 static_decl_vfs;
2927 NTSTATUS vfs_time_audit_init(TALLOC_CTX *ctx)
2928 {
2929         smb_vfs_assert_all_fns(&vfs_time_audit_fns, "time_audit");
2930
2931         audit_timeout = (double)lp_parm_int(-1, "time_audit", "timeout",
2932                                             10000) / 1000.0;
2933         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "time_audit",
2934                                 &vfs_time_audit_fns);
2935 }