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