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