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