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