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