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