s3: VFS: vfs_time_audit. Implement unlinkat().
[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_unlink(vfs_handle_struct *handle,
1069                                  const struct smb_filename *path)
1070 {
1071         int result;
1072         struct timespec ts1,ts2;
1073         double timediff;
1074
1075         clock_gettime_mono(&ts1);
1076         result = SMB_VFS_NEXT_UNLINK(handle, path);
1077         clock_gettime_mono(&ts2);
1078         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1079
1080         if (timediff > audit_timeout) {
1081                 smb_time_audit_log_smb_fname("unlink", timediff, path);
1082         }
1083
1084         return result;
1085 }
1086
1087 static int smb_time_audit_unlinkat(vfs_handle_struct *handle,
1088                         struct files_struct *dirfsp,
1089                         const struct smb_filename *path,
1090                         int flags)
1091 {
1092         int result;
1093         struct timespec ts1,ts2;
1094         double timediff;
1095
1096         clock_gettime_mono(&ts1);
1097         result = SMB_VFS_NEXT_UNLINKAT(handle,
1098                                 dirfsp,
1099                                 path,
1100                                 flags);
1101         clock_gettime_mono(&ts2);
1102         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1103
1104         if (timediff > audit_timeout) {
1105                 smb_time_audit_log_smb_fname("unlinkat", timediff, path);
1106         }
1107
1108         return result;
1109 }
1110
1111 static int smb_time_audit_chmod(vfs_handle_struct *handle,
1112                         const struct smb_filename *smb_fname,
1113                         mode_t mode)
1114 {
1115         int result;
1116         struct timespec ts1,ts2;
1117         double timediff;
1118
1119         clock_gettime_mono(&ts1);
1120         result = SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
1121         clock_gettime_mono(&ts2);
1122         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1123
1124         if (timediff > audit_timeout) {
1125                 smb_time_audit_log_fname("chmod",
1126                         timediff,
1127                         smb_fname->base_name);
1128         }
1129
1130         return result;
1131 }
1132
1133 static int smb_time_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp,
1134                                  mode_t mode)
1135 {
1136         int result;
1137         struct timespec ts1,ts2;
1138         double timediff;
1139
1140         clock_gettime_mono(&ts1);
1141         result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1142         clock_gettime_mono(&ts2);
1143         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1144
1145         if (timediff > audit_timeout) {
1146                 smb_time_audit_log_fsp("fchmod", timediff, fsp);
1147         }
1148
1149         return result;
1150 }
1151
1152 static int smb_time_audit_chown(vfs_handle_struct *handle,
1153                         const struct smb_filename *smb_fname,
1154                         uid_t uid,
1155                         gid_t gid)
1156 {
1157         int result;
1158         struct timespec ts1,ts2;
1159         double timediff;
1160
1161         clock_gettime_mono(&ts1);
1162         result = SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
1163         clock_gettime_mono(&ts2);
1164         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1165
1166         if (timediff > audit_timeout) {
1167                 smb_time_audit_log_fname("chown",
1168                         timediff,
1169                         smb_fname->base_name);
1170         }
1171
1172         return result;
1173 }
1174
1175 static int smb_time_audit_fchown(vfs_handle_struct *handle, files_struct *fsp,
1176                                  uid_t uid, gid_t gid)
1177 {
1178         int result;
1179         struct timespec ts1,ts2;
1180         double timediff;
1181
1182         clock_gettime_mono(&ts1);
1183         result = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1184         clock_gettime_mono(&ts2);
1185         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1186
1187         if (timediff > audit_timeout) {
1188                 smb_time_audit_log_fsp("fchown", timediff, fsp);
1189         }
1190
1191         return result;
1192 }
1193
1194 static int smb_time_audit_lchown(vfs_handle_struct *handle,
1195                         const struct smb_filename *smb_fname,
1196                         uid_t uid,
1197                         gid_t gid)
1198 {
1199         int result;
1200         struct timespec ts1,ts2;
1201         double timediff;
1202
1203         clock_gettime_mono(&ts1);
1204         result = SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
1205         clock_gettime_mono(&ts2);
1206         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1207
1208         if (timediff > audit_timeout) {
1209                 smb_time_audit_log_fname("lchown",
1210                         timediff,
1211                         smb_fname->base_name);
1212         }
1213
1214         return result;
1215 }
1216
1217 static int smb_time_audit_chdir(vfs_handle_struct *handle,
1218                         const struct smb_filename *smb_fname)
1219 {
1220         int result;
1221         struct timespec ts1,ts2;
1222         double timediff;
1223
1224         clock_gettime_mono(&ts1);
1225         result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
1226         clock_gettime_mono(&ts2);
1227         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1228
1229         if (timediff > audit_timeout) {
1230                 smb_time_audit_log_fname("chdir",
1231                         timediff,
1232                         smb_fname->base_name);
1233         }
1234
1235         return result;
1236 }
1237
1238 static struct smb_filename *smb_time_audit_getwd(vfs_handle_struct *handle,
1239                                         TALLOC_CTX *mem_ctx)
1240 {
1241         struct smb_filename *result;
1242         struct timespec ts1,ts2;
1243         double timediff;
1244
1245         clock_gettime_mono(&ts1);
1246         result = SMB_VFS_NEXT_GETWD(handle, mem_ctx);
1247         clock_gettime_mono(&ts2);
1248         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1249
1250         if (timediff > audit_timeout) {
1251                 smb_time_audit_log("getwd", timediff);
1252         }
1253
1254         return result;
1255 }
1256
1257 static int smb_time_audit_ntimes(vfs_handle_struct *handle,
1258                                  const struct smb_filename *path,
1259                                  struct smb_file_time *ft)
1260 {
1261         int result;
1262         struct timespec ts1,ts2;
1263         double timediff;
1264
1265         clock_gettime_mono(&ts1);
1266         result = SMB_VFS_NEXT_NTIMES(handle, path, ft);
1267         clock_gettime_mono(&ts2);
1268         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1269
1270         if (timediff > audit_timeout) {
1271                 smb_time_audit_log_smb_fname("ntimes", timediff, path);
1272         }
1273
1274         return result;
1275 }
1276
1277 static int smb_time_audit_ftruncate(vfs_handle_struct *handle,
1278                                     files_struct *fsp,
1279                                     off_t len)
1280 {
1281         int result;
1282         struct timespec ts1,ts2;
1283         double timediff;
1284
1285         clock_gettime_mono(&ts1);
1286         result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
1287         clock_gettime_mono(&ts2);
1288         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1289
1290         if (timediff > audit_timeout) {
1291                 smb_time_audit_log_fsp("ftruncate", timediff, fsp);
1292         }
1293
1294         return result;
1295 }
1296
1297 static int smb_time_audit_fallocate(vfs_handle_struct *handle,
1298                                     files_struct *fsp,
1299                                     uint32_t mode,
1300                                     off_t offset,
1301                                     off_t len)
1302 {
1303         int result;
1304         int saved_errno = 0;
1305         struct timespec ts1,ts2;
1306         double timediff;
1307
1308         clock_gettime_mono(&ts1);
1309         result = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1310         if (result == -1) {
1311                 saved_errno = errno;
1312         }
1313         clock_gettime_mono(&ts2);
1314         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1315
1316         if (timediff > audit_timeout) {
1317                 smb_time_audit_log_fsp("fallocate", timediff, fsp);
1318         }
1319         if (result == -1) {
1320                 errno = saved_errno;
1321         }
1322         return result;
1323 }
1324
1325 static bool smb_time_audit_lock(vfs_handle_struct *handle, files_struct *fsp,
1326                                 int op, off_t offset, off_t count,
1327                                 int type)
1328 {
1329         bool result;
1330         struct timespec ts1,ts2;
1331         double timediff;
1332
1333         clock_gettime_mono(&ts1);
1334         result = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
1335         clock_gettime_mono(&ts2);
1336         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1337
1338         if (timediff > audit_timeout) {
1339                 smb_time_audit_log_fsp("lock", timediff, fsp);
1340         }
1341
1342         return result;
1343 }
1344
1345 static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
1346                                        struct files_struct *fsp,
1347                                        uint32_t share_mode, uint32_t access_mask)
1348 {
1349         int result;
1350         struct timespec ts1,ts2;
1351         double timediff;
1352
1353         clock_gettime_mono(&ts1);
1354         result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode,
1355                                            access_mask);
1356         clock_gettime_mono(&ts2);
1357         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1358
1359         if (timediff > audit_timeout) {
1360                 smb_time_audit_log_fsp("kernel_flock", timediff, fsp);
1361         }
1362
1363         return result;
1364 }
1365
1366 static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
1367                                          files_struct *fsp,
1368                                          int leasetype)
1369 {
1370         int result;
1371         struct timespec ts1,ts2;
1372         double timediff;
1373
1374         clock_gettime_mono(&ts1);
1375         result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
1376         clock_gettime_mono(&ts2);
1377         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1378
1379         if (timediff > audit_timeout) {
1380                 smb_time_audit_log_fsp("linux_setlease", timediff, fsp);
1381         }
1382
1383         return result;
1384 }
1385
1386 static bool smb_time_audit_getlock(vfs_handle_struct *handle,
1387                                    files_struct *fsp,
1388                                    off_t *poffset, off_t *pcount,
1389                                    int *ptype, pid_t *ppid)
1390 {
1391         bool result;
1392         struct timespec ts1,ts2;
1393         double timediff;
1394
1395         clock_gettime_mono(&ts1);
1396         result = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype,
1397                                       ppid);
1398         clock_gettime_mono(&ts2);
1399         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1400
1401         if (timediff > audit_timeout) {
1402                 smb_time_audit_log_fsp("getlock", timediff, fsp);
1403         }
1404
1405         return result;
1406 }
1407
1408 static int smb_time_audit_symlinkat(vfs_handle_struct *handle,
1409                                 const char *link_contents,
1410                                 struct files_struct *dirfsp,
1411                                 const struct smb_filename *new_smb_fname)
1412 {
1413         int result;
1414         struct timespec ts1,ts2;
1415         double timediff;
1416
1417         clock_gettime_mono(&ts1);
1418         result = SMB_VFS_NEXT_SYMLINKAT(handle,
1419                                 link_contents,
1420                                 dirfsp,
1421                                 new_smb_fname);
1422         clock_gettime_mono(&ts2);
1423         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1424
1425         if (timediff > audit_timeout) {
1426                 smb_time_audit_log_fname("symlinkat", timediff,
1427                         new_smb_fname->base_name);
1428         }
1429
1430         return result;
1431 }
1432
1433 static int smb_time_audit_readlinkat(vfs_handle_struct *handle,
1434                                 files_struct *dirfsp,
1435                                 const struct smb_filename *smb_fname,
1436                                 char *buf,
1437                                 size_t bufsiz)
1438 {
1439         int result;
1440         struct timespec ts1,ts2;
1441         double timediff;
1442
1443         clock_gettime_mono(&ts1);
1444         result = SMB_VFS_NEXT_READLINKAT(handle,
1445                                 dirfsp,
1446                                 smb_fname,
1447                                 buf,
1448                                 bufsiz);
1449         clock_gettime_mono(&ts2);
1450         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1451
1452         if (timediff > audit_timeout) {
1453                 smb_time_audit_log_fname("readlinkat", timediff,
1454                                 smb_fname->base_name);
1455         }
1456
1457         return result;
1458 }
1459
1460 static int smb_time_audit_linkat(vfs_handle_struct *handle,
1461                                 files_struct *srcfsp,
1462                                 const struct smb_filename *old_smb_fname,
1463                                 files_struct *dstfsp,
1464                                 const struct smb_filename *new_smb_fname,
1465                                 int flags)
1466 {
1467         int result;
1468         struct timespec ts1,ts2;
1469         double timediff;
1470
1471         clock_gettime_mono(&ts1);
1472         result = SMB_VFS_NEXT_LINKAT(handle,
1473                         srcfsp,
1474                         old_smb_fname,
1475                         dstfsp,
1476                         new_smb_fname,
1477                         flags);
1478         clock_gettime_mono(&ts2);
1479         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1480
1481         if (timediff > audit_timeout) {
1482                 smb_time_audit_log_fname("linkat", timediff,
1483                         new_smb_fname->base_name);
1484         }
1485
1486         return result;
1487 }
1488
1489 static int smb_time_audit_mknodat(vfs_handle_struct *handle,
1490                                 files_struct *dirfsp,
1491                                 const struct smb_filename *smb_fname,
1492                                 mode_t mode,
1493                                 SMB_DEV_T dev)
1494 {
1495         int result;
1496         struct timespec ts1,ts2;
1497         double timediff;
1498
1499         clock_gettime_mono(&ts1);
1500         result = SMB_VFS_NEXT_MKNODAT(handle,
1501                                 dirfsp,
1502                                 smb_fname,
1503                                 mode,
1504                                 dev);
1505         clock_gettime_mono(&ts2);
1506         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1507
1508         if (timediff > audit_timeout) {
1509                 smb_time_audit_log_smb_fname("mknodat", timediff, smb_fname);
1510         }
1511
1512         return result;
1513 }
1514
1515 static struct smb_filename *smb_time_audit_realpath(vfs_handle_struct *handle,
1516                                 TALLOC_CTX *ctx,
1517                                 const struct smb_filename *smb_fname)
1518 {
1519         struct smb_filename *result_fname;
1520         struct timespec ts1,ts2;
1521         double timediff;
1522
1523         clock_gettime_mono(&ts1);
1524         result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
1525         clock_gettime_mono(&ts2);
1526         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1527
1528         if (timediff > audit_timeout) {
1529                 smb_time_audit_log_fname("realpath", timediff,
1530                                 smb_fname->base_name);
1531         }
1532
1533         return result_fname;
1534 }
1535
1536 static int smb_time_audit_chflags(vfs_handle_struct *handle,
1537                                 const struct smb_filename *smb_fname,
1538                                 unsigned int flags)
1539 {
1540         int result;
1541         struct timespec ts1,ts2;
1542         double timediff;
1543
1544         clock_gettime_mono(&ts1);
1545         result = SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
1546         clock_gettime_mono(&ts2);
1547         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1548
1549         if (timediff > audit_timeout) {
1550                 smb_time_audit_log_smb_fname("chflags", timediff, smb_fname);
1551         }
1552
1553         return result;
1554 }
1555
1556 static struct file_id smb_time_audit_file_id_create(struct vfs_handle_struct *handle,
1557                                                     const SMB_STRUCT_STAT *sbuf)
1558 {
1559         struct file_id id_zero;
1560         struct file_id result;
1561         struct timespec ts1,ts2;
1562         double timediff;
1563
1564         ZERO_STRUCT(id_zero);
1565
1566         clock_gettime_mono(&ts1);
1567         result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
1568         clock_gettime_mono(&ts2);
1569         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1570
1571         if (timediff > audit_timeout) {
1572                 smb_time_audit_log("file_id_create", timediff);
1573         }
1574
1575         return result;
1576 }
1577
1578 static uint64_t smb_time_audit_fs_file_id(struct vfs_handle_struct *handle,
1579                                           const SMB_STRUCT_STAT *sbuf)
1580 {
1581         uint64_t result;
1582         struct timespec ts1,ts2;
1583         double timediff;
1584
1585         clock_gettime_mono(&ts1);
1586         result = SMB_VFS_NEXT_FS_FILE_ID(handle, sbuf);
1587         clock_gettime_mono(&ts2);
1588         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1589
1590         if (timediff > audit_timeout) {
1591                 smb_time_audit_log("fs_file_id", timediff);
1592         }
1593
1594         return result;
1595 }
1596
1597 static NTSTATUS smb_time_audit_streaminfo(vfs_handle_struct *handle,
1598                                           struct files_struct *fsp,
1599                                           const struct smb_filename *smb_fname,
1600                                           TALLOC_CTX *mem_ctx,
1601                                           unsigned int *pnum_streams,
1602                                           struct stream_struct **pstreams)
1603 {
1604         NTSTATUS result;
1605         struct timespec ts1,ts2;
1606         double timediff;
1607
1608         clock_gettime_mono(&ts1);
1609         result = SMB_VFS_NEXT_STREAMINFO(handle, fsp, smb_fname, mem_ctx,
1610                                          pnum_streams, pstreams);
1611         clock_gettime_mono(&ts2);
1612         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1613
1614         if (timediff > audit_timeout) {
1615                 smb_time_audit_log_fsp("streaminfo", timediff, fsp);
1616         }
1617
1618         return result;
1619 }
1620
1621 static int smb_time_audit_get_real_filename(struct vfs_handle_struct *handle,
1622                                             const char *path,
1623                                             const char *name,
1624                                             TALLOC_CTX *mem_ctx,
1625                                             char **found_name)
1626 {
1627         int result;
1628         struct timespec ts1,ts2;
1629         double timediff;
1630
1631         clock_gettime_mono(&ts1);
1632         result = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx,
1633                                                 found_name);
1634         clock_gettime_mono(&ts2);
1635         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1636
1637         if (timediff > audit_timeout) {
1638                 smb_time_audit_log_fname("get_real_filename", timediff, path);
1639         }
1640
1641         return result;
1642 }
1643
1644 static const char *smb_time_audit_connectpath(vfs_handle_struct *handle,
1645                                         const struct smb_filename *smb_fname)
1646 {
1647         const char *result;
1648         struct timespec ts1,ts2;
1649         double timediff;
1650
1651         clock_gettime_mono(&ts1);
1652         result = SMB_VFS_NEXT_CONNECTPATH(handle, smb_fname);
1653         clock_gettime_mono(&ts2);
1654         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1655
1656         if (timediff > audit_timeout) {
1657                 smb_time_audit_log_fname("connectpath", timediff,
1658                         smb_fname->base_name);
1659         }
1660
1661         return result;
1662 }
1663
1664 static NTSTATUS smb_time_audit_brl_lock_windows(struct vfs_handle_struct *handle,
1665                                                 struct byte_range_lock *br_lck,
1666                                                 struct lock_struct *plock)
1667 {
1668         NTSTATUS result;
1669         struct timespec ts1,ts2;
1670         double timediff;
1671
1672         clock_gettime_mono(&ts1);
1673         result = SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock);
1674         clock_gettime_mono(&ts2);
1675         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1676
1677         if (timediff > audit_timeout) {
1678                 smb_time_audit_log_fsp("brl_lock_windows", timediff,
1679                                        brl_fsp(br_lck));
1680         }
1681
1682         return result;
1683 }
1684
1685 static bool smb_time_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
1686                                               struct byte_range_lock *br_lck,
1687                                               const struct lock_struct *plock)
1688 {
1689         bool result;
1690         struct timespec ts1,ts2;
1691         double timediff;
1692
1693         clock_gettime_mono(&ts1);
1694         result = SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, br_lck, plock);
1695         clock_gettime_mono(&ts2);
1696         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1697
1698         if (timediff > audit_timeout) {
1699                 smb_time_audit_log_fsp("brl_unlock_windows", timediff,
1700                                        brl_fsp(br_lck));
1701         }
1702
1703         return result;
1704 }
1705
1706 static bool smb_time_audit_strict_lock_check(struct vfs_handle_struct *handle,
1707                                              struct files_struct *fsp,
1708                                              struct lock_struct *plock)
1709 {
1710         bool result;
1711         struct timespec ts1,ts2;
1712         double timediff;
1713
1714         clock_gettime_mono(&ts1);
1715         result = SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock);
1716         clock_gettime_mono(&ts2);
1717         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1718
1719         if (timediff > audit_timeout) {
1720                 smb_time_audit_log_fsp("strict_lock_check", timediff, fsp);
1721         }
1722
1723         return result;
1724 }
1725
1726 static NTSTATUS smb_time_audit_translate_name(struct vfs_handle_struct *handle,
1727                                               const char *name,
1728                                               enum vfs_translate_direction direction,
1729                                               TALLOC_CTX *mem_ctx,
1730                                               char **mapped_name)
1731 {
1732         NTSTATUS result;
1733         struct timespec ts1,ts2;
1734         double timediff;
1735
1736         clock_gettime_mono(&ts1);
1737         result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx,
1738                                              mapped_name);
1739         clock_gettime_mono(&ts2);
1740         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1741
1742         if (timediff > audit_timeout) {
1743                 smb_time_audit_log_fname("translate_name", timediff, name);
1744         }
1745
1746         return result;
1747 }
1748
1749 static NTSTATUS smb_time_audit_fsctl(struct vfs_handle_struct *handle,
1750                                 struct files_struct *fsp,
1751                                 TALLOC_CTX *ctx,
1752                                 uint32_t function,
1753                                 uint16_t req_flags,
1754                                 const uint8_t *_in_data,
1755                                 uint32_t in_len,
1756                                 uint8_t **_out_data,
1757                                 uint32_t max_out_len,
1758                                 uint32_t *out_len)
1759 {
1760         NTSTATUS result;
1761         struct timespec ts1,ts2;
1762         double timediff;
1763
1764         clock_gettime_mono(&ts1);
1765         result = SMB_VFS_NEXT_FSCTL(handle,
1766                                 fsp,
1767                                 ctx,
1768                                 function,
1769                                 req_flags,
1770                                 _in_data,
1771                                 in_len,
1772                                 _out_data,
1773                                 max_out_len,
1774                                 out_len);
1775         clock_gettime_mono(&ts2);
1776         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1777
1778         if (timediff > audit_timeout) {
1779                 smb_time_audit_log_fsp("fsctl", timediff, fsp);
1780         }
1781
1782         return result;
1783 }
1784
1785 static NTSTATUS smb_time_get_dos_attributes(struct vfs_handle_struct *handle,
1786                                         struct smb_filename *smb_fname,
1787                                         uint32_t *dosmode)
1788 {
1789         NTSTATUS result;
1790         struct timespec ts1,ts2;
1791         double timediff;
1792
1793         clock_gettime_mono(&ts1);
1794         result = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
1795                                 smb_fname,
1796                                 dosmode);
1797         clock_gettime_mono(&ts2);
1798         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1799
1800         if (timediff > audit_timeout) {
1801                 smb_time_audit_log_fname("get_dos_attributes",
1802                                 timediff,
1803                                 smb_fname->base_name);
1804         }
1805
1806         return result;
1807 }
1808
1809 struct smb_time_audit_get_dos_attributes_state {
1810         struct vfs_aio_state aio_state;
1811         files_struct *dir_fsp;
1812         const struct smb_filename *smb_fname;
1813         uint32_t dosmode;
1814 };
1815
1816 static void smb_time_audit_get_dos_attributes_done(struct tevent_req *subreq);
1817
1818 static struct tevent_req *smb_time_audit_get_dos_attributes_send(
1819                         TALLOC_CTX *mem_ctx,
1820                         struct tevent_context *ev,
1821                         struct vfs_handle_struct *handle,
1822                         files_struct *dir_fsp,
1823                         struct smb_filename *smb_fname)
1824 {
1825         struct tevent_req *req = NULL;
1826         struct smb_time_audit_get_dos_attributes_state *state = NULL;
1827         struct tevent_req *subreq = NULL;
1828
1829         req = tevent_req_create(mem_ctx, &state,
1830                                 struct smb_time_audit_get_dos_attributes_state);
1831         if (req == NULL) {
1832                 return NULL;
1833         }
1834         *state = (struct smb_time_audit_get_dos_attributes_state) {
1835                 .dir_fsp = dir_fsp,
1836                 .smb_fname = smb_fname,
1837         };
1838
1839         subreq = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_SEND(mem_ctx,
1840                                                       ev,
1841                                                       handle,
1842                                                       dir_fsp,
1843                                                       smb_fname);
1844         if (tevent_req_nomem(subreq, req)) {
1845                 return tevent_req_post(req, ev);
1846         }
1847         tevent_req_set_callback(subreq,
1848                                 smb_time_audit_get_dos_attributes_done,
1849                                 req);
1850
1851         return req;
1852 }
1853
1854 static void smb_time_audit_get_dos_attributes_done(struct tevent_req *subreq)
1855 {
1856         struct tevent_req *req =
1857                 tevent_req_callback_data(subreq,
1858                 struct tevent_req);
1859         struct smb_time_audit_get_dos_attributes_state *state =
1860                 tevent_req_data(req,
1861                 struct smb_time_audit_get_dos_attributes_state);
1862         NTSTATUS status;
1863
1864         status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_RECV(subreq,
1865                                                       &state->aio_state,
1866                                                       &state->dosmode);
1867         TALLOC_FREE(subreq);
1868         if (tevent_req_nterror(req, status)) {
1869                 return;
1870         }
1871
1872         tevent_req_done(req);
1873         return;
1874 }
1875
1876 static NTSTATUS smb_time_audit_get_dos_attributes_recv(struct tevent_req *req,
1877                                                 struct vfs_aio_state *aio_state,
1878                                                 uint32_t *dosmode)
1879 {
1880         struct smb_time_audit_get_dos_attributes_state *state =
1881                 tevent_req_data(req,
1882                 struct smb_time_audit_get_dos_attributes_state);
1883         NTSTATUS status;
1884         double timediff;
1885
1886         timediff = state->aio_state.duration * 1.0e-9;
1887
1888         if (timediff > audit_timeout) {
1889                 smb_time_audit_log_at("async get_dos_attributes",
1890                                       timediff,
1891                                       state->dir_fsp,
1892                                       state->smb_fname);
1893         }
1894
1895         if (tevent_req_is_nterror(req, &status)) {
1896                 tevent_req_received(req);
1897                 return status;
1898         }
1899
1900         *aio_state = state->aio_state;
1901         *dosmode = state->dosmode;
1902         tevent_req_received(req);
1903         return NT_STATUS_OK;
1904 }
1905
1906 static NTSTATUS smb_time_fget_dos_attributes(struct vfs_handle_struct *handle,
1907                                         struct files_struct *fsp,
1908                                         uint32_t *dosmode)
1909 {
1910         NTSTATUS result;
1911         struct timespec ts1,ts2;
1912         double timediff;
1913
1914         clock_gettime_mono(&ts1);
1915         result = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle,
1916                                 fsp,
1917                                 dosmode);
1918         clock_gettime_mono(&ts2);
1919         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1920
1921         if (timediff > audit_timeout) {
1922                 smb_time_audit_log_fsp("fget_dos_attributes", timediff, fsp);
1923         }
1924
1925         return result;
1926 }
1927
1928 static NTSTATUS smb_time_set_dos_attributes(struct vfs_handle_struct *handle,
1929                                         const struct smb_filename *smb_fname,
1930                                         uint32_t dosmode)
1931 {
1932         NTSTATUS result;
1933         struct timespec ts1,ts2;
1934         double timediff;
1935
1936         clock_gettime_mono(&ts1);
1937         result = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
1938                                 smb_fname,
1939                                 dosmode);
1940         clock_gettime_mono(&ts2);
1941         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1942
1943         if (timediff > audit_timeout) {
1944                 smb_time_audit_log_fname("set_dos_attributes",
1945                                 timediff,
1946                                 smb_fname->base_name);
1947         }
1948
1949         return result;
1950 }
1951
1952 static NTSTATUS smb_time_fset_dos_attributes(struct vfs_handle_struct *handle,
1953                                         struct files_struct *fsp,
1954                                         uint32_t dosmode)
1955 {
1956         NTSTATUS result;
1957         struct timespec ts1,ts2;
1958         double timediff;
1959
1960         clock_gettime_mono(&ts1);
1961         result = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle,
1962                                 fsp,
1963                                 dosmode);
1964         clock_gettime_mono(&ts2);
1965         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1966
1967         if (timediff > audit_timeout) {
1968                 smb_time_audit_log_fsp("fset_dos_attributes", timediff, fsp);
1969         }
1970
1971         return result;
1972 }
1973
1974 struct time_audit_offload_read_state {
1975         struct vfs_handle_struct *handle;
1976         struct timespec ts_send;
1977         DATA_BLOB token_blob;
1978 };
1979
1980 static void smb_time_audit_offload_read_done(struct tevent_req *subreq);
1981
1982 static struct tevent_req *smb_time_audit_offload_read_send(
1983         TALLOC_CTX *mem_ctx,
1984         struct tevent_context *ev,
1985         struct vfs_handle_struct *handle,
1986         struct files_struct *fsp,
1987         uint32_t fsctl,
1988         uint32_t ttl,
1989         off_t offset,
1990         size_t to_copy)
1991 {
1992         struct tevent_req *req = NULL;
1993         struct tevent_req *subreq = NULL;
1994         struct time_audit_offload_read_state *state = NULL;
1995
1996         req = tevent_req_create(mem_ctx, &state,
1997                                 struct time_audit_offload_read_state);
1998         if (req == NULL) {
1999                 return NULL;
2000         }
2001         state->handle = handle;
2002         clock_gettime_mono(&state->ts_send);
2003
2004         subreq = SMB_VFS_NEXT_OFFLOAD_READ_SEND(mem_ctx, ev,
2005                                                 handle, fsp,
2006                                                 fsctl, ttl,
2007                                                 offset, to_copy);
2008         if (tevent_req_nomem(subreq, req)) {
2009                 return tevent_req_post(req, ev);
2010         }
2011
2012         tevent_req_set_callback(subreq, smb_time_audit_offload_read_done, req);
2013         return req;
2014 }
2015
2016 static void smb_time_audit_offload_read_done(struct tevent_req *subreq)
2017 {
2018         struct tevent_req *req = tevent_req_callback_data(
2019                 subreq, struct tevent_req);
2020         struct time_audit_offload_read_state *state = tevent_req_data(
2021                 req, struct time_audit_offload_read_state);
2022         NTSTATUS status;
2023
2024         status = SMB_VFS_NEXT_OFFLOAD_READ_RECV(subreq,
2025                                                 state->handle,
2026                                                 state,
2027                                                 &state->token_blob);
2028         TALLOC_FREE(subreq);
2029         if (tevent_req_nterror(req, status)) {
2030                 return;
2031         }
2032         tevent_req_done(req);
2033 }
2034
2035 static NTSTATUS smb_time_audit_offload_read_recv(
2036         struct tevent_req *req,
2037         struct vfs_handle_struct *handle,
2038         TALLOC_CTX *mem_ctx,
2039         DATA_BLOB *token_blob)
2040 {
2041         struct time_audit_offload_read_state *state = tevent_req_data(
2042                 req, struct time_audit_offload_read_state);
2043         struct timespec ts_recv;
2044         double timediff;
2045         NTSTATUS status;
2046
2047         clock_gettime_mono(&ts_recv);
2048         timediff = nsec_time_diff(&ts_recv, &state->ts_send) * 1.0e-9;
2049         if (timediff > audit_timeout) {
2050                 smb_time_audit_log("offload_read", timediff);
2051         }
2052
2053         if (tevent_req_is_nterror(req, &status)) {
2054                 tevent_req_received(req);
2055                 return status;
2056         }
2057
2058         token_blob->length = state->token_blob.length;
2059         token_blob->data = talloc_move(mem_ctx, &state->token_blob.data);
2060
2061         tevent_req_received(req);
2062         return NT_STATUS_OK;
2063 }
2064
2065 struct time_audit_offload_write_state {
2066         struct timespec ts_send;
2067         struct vfs_handle_struct *handle;
2068         off_t copied;
2069 };
2070 static void smb_time_audit_offload_write_done(struct tevent_req *subreq);
2071
2072 static struct tevent_req *smb_time_audit_offload_write_send(struct vfs_handle_struct *handle,
2073                                                          TALLOC_CTX *mem_ctx,
2074                                                          struct tevent_context *ev,
2075                                                          uint32_t fsctl,
2076                                                          DATA_BLOB *token,
2077                                                          off_t transfer_offset,
2078                                                          struct files_struct *dest_fsp,
2079                                                          off_t dest_off,
2080                                                          off_t num)
2081 {
2082         struct tevent_req *req;
2083         struct tevent_req *subreq;
2084         struct time_audit_offload_write_state *state;
2085
2086         req = tevent_req_create(mem_ctx, &state,
2087                                 struct time_audit_offload_write_state);
2088         if (req == NULL) {
2089                 return NULL;
2090         }
2091
2092         state->handle = handle;
2093         clock_gettime_mono(&state->ts_send);
2094         subreq = SMB_VFS_NEXT_OFFLOAD_WRITE_SEND(handle, state, ev,
2095                                               fsctl, token, transfer_offset,
2096                                               dest_fsp, dest_off, num);
2097         if (tevent_req_nomem(subreq, req)) {
2098                 return tevent_req_post(req, ev);
2099         }
2100
2101         tevent_req_set_callback(subreq, smb_time_audit_offload_write_done, req);
2102         return req;
2103 }
2104
2105 static void smb_time_audit_offload_write_done(struct tevent_req *subreq)
2106 {
2107         struct tevent_req *req = tevent_req_callback_data(
2108                 subreq, struct tevent_req);
2109         struct time_audit_offload_write_state *state = tevent_req_data(
2110                 req, struct time_audit_offload_write_state);
2111         NTSTATUS status;
2112
2113         status = SMB_VFS_NEXT_OFFLOAD_WRITE_RECV(state->handle,
2114                                               subreq,
2115                                               &state->copied);
2116         TALLOC_FREE(subreq);
2117         if (tevent_req_nterror(req, status)) {
2118                 return;
2119         }
2120         tevent_req_done(req);
2121 }
2122
2123 static NTSTATUS smb_time_audit_offload_write_recv(struct vfs_handle_struct *handle,
2124                                                struct tevent_req *req,
2125                                                off_t *copied)
2126 {
2127         struct time_audit_offload_write_state *state = tevent_req_data(
2128                 req, struct time_audit_offload_write_state);
2129         struct timespec ts_recv;
2130         double timediff;
2131         NTSTATUS status;
2132
2133         clock_gettime_mono(&ts_recv);
2134         timediff = nsec_time_diff(&ts_recv, &state->ts_send)*1.0e-9;
2135         if (timediff > audit_timeout) {
2136                 smb_time_audit_log("offload_write", timediff);
2137         }
2138
2139         *copied = state->copied;
2140         if (tevent_req_is_nterror(req, &status)) {
2141                 tevent_req_received(req);
2142                 return status;
2143         }
2144
2145         tevent_req_received(req);
2146         return NT_STATUS_OK;
2147 }
2148
2149 static NTSTATUS smb_time_audit_get_compression(vfs_handle_struct *handle,
2150                                                TALLOC_CTX *mem_ctx,
2151                                                struct files_struct *fsp,
2152                                                struct smb_filename *smb_fname,
2153                                                uint16_t *_compression_fmt)
2154 {
2155         NTSTATUS result;
2156         struct timespec ts1,ts2;
2157         double timediff;
2158
2159         clock_gettime_mono(&ts1);
2160         result = SMB_VFS_NEXT_GET_COMPRESSION(handle, mem_ctx, fsp, smb_fname,
2161                                               _compression_fmt);
2162         clock_gettime_mono(&ts2);
2163         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2164
2165         if (timediff > audit_timeout) {
2166                 if (fsp !=  NULL) {
2167                         smb_time_audit_log_fsp("get_compression",
2168                                                timediff, fsp);
2169                 } else {
2170                         smb_time_audit_log_smb_fname("get_compression",
2171                                                      timediff, smb_fname);
2172                 }
2173         }
2174
2175         return result;
2176 }
2177
2178 static NTSTATUS smb_time_audit_set_compression(vfs_handle_struct *handle,
2179                                                TALLOC_CTX *mem_ctx,
2180                                                struct files_struct *fsp,
2181                                                uint16_t compression_fmt)
2182 {
2183         NTSTATUS result;
2184         struct timespec ts1,ts2;
2185         double timediff;
2186
2187         clock_gettime_mono(&ts1);
2188         result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
2189                                               compression_fmt);
2190         clock_gettime_mono(&ts2);
2191         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2192
2193         if (timediff > audit_timeout) {
2194                 smb_time_audit_log_fsp("set_compression", timediff, fsp);
2195         }
2196
2197         return result;
2198 }
2199
2200 static NTSTATUS smb_time_audit_readdir_attr(struct vfs_handle_struct *handle,
2201                                             const struct smb_filename *fname,
2202                                             TALLOC_CTX *mem_ctx,
2203                                             struct readdir_attr_data **pattr_data)
2204 {
2205         NTSTATUS status;
2206         struct timespec ts1,ts2;
2207         double timediff;
2208
2209         clock_gettime_mono(&ts1);
2210         status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
2211         clock_gettime_mono(&ts2);
2212         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2213
2214         if (timediff > audit_timeout) {
2215                 smb_time_audit_log_smb_fname("readdir_attr", timediff, fname);
2216         }
2217
2218         return status;
2219 }
2220
2221 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
2222                                            files_struct *fsp,
2223                                            uint32_t security_info,
2224                                            TALLOC_CTX *mem_ctx,
2225                                            struct security_descriptor **ppdesc)
2226 {
2227         NTSTATUS result;
2228         struct timespec ts1,ts2;
2229         double timediff;
2230
2231         clock_gettime_mono(&ts1);
2232         result = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
2233                                           mem_ctx, ppdesc);
2234         clock_gettime_mono(&ts2);
2235         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2236
2237         if (timediff > audit_timeout) {
2238                 smb_time_audit_log_fsp("fget_nt_acl", timediff, fsp);
2239         }
2240
2241         return result;
2242 }
2243
2244 static NTSTATUS smb_time_audit_get_nt_acl(vfs_handle_struct *handle,
2245                                           const struct smb_filename *smb_fname,
2246                                           uint32_t security_info,
2247                                           TALLOC_CTX *mem_ctx,
2248                                           struct security_descriptor **ppdesc)
2249 {
2250         NTSTATUS result;
2251         struct timespec ts1,ts2;
2252         double timediff;
2253
2254         clock_gettime_mono(&ts1);
2255         result = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
2256                                          mem_ctx, ppdesc);
2257         clock_gettime_mono(&ts2);
2258         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2259
2260         if (timediff > audit_timeout) {
2261                 smb_time_audit_log_fname("get_nt_acl",
2262                         timediff,
2263                         smb_fname->base_name);
2264         }
2265
2266         return result;
2267 }
2268
2269 static NTSTATUS smb_time_audit_fset_nt_acl(vfs_handle_struct *handle,
2270                                            files_struct *fsp,
2271                                            uint32_t security_info_sent,
2272                                            const struct security_descriptor *psd)
2273 {
2274         NTSTATUS result;
2275         struct timespec ts1,ts2;
2276         double timediff;
2277
2278         clock_gettime_mono(&ts1);
2279         result = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent,
2280                                           psd);
2281         clock_gettime_mono(&ts2);
2282         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2283
2284         if (timediff > audit_timeout) {
2285                 smb_time_audit_log_fsp("fset_nt_acl", timediff, fsp);
2286         }
2287
2288         return result;
2289 }
2290
2291 static NTSTATUS smb_time_audit_audit_file(struct vfs_handle_struct *handle,
2292                                 struct smb_filename *smb_fname,
2293                                 struct security_acl *sacl,
2294                                 uint32_t access_requested,
2295                                 uint32_t access_denied)
2296 {
2297         NTSTATUS result;
2298         struct timespec ts1,ts2;
2299         double timediff;
2300
2301         clock_gettime_mono(&ts1);
2302         result = SMB_VFS_NEXT_AUDIT_FILE(handle,
2303                                         smb_fname,
2304                                         sacl,
2305                                         access_requested,
2306                                         access_denied);
2307         clock_gettime_mono(&ts2);
2308         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2309
2310         if (timediff > audit_timeout) {
2311                 smb_time_audit_log_fname("audit_file",
2312                         timediff,
2313                         smb_fname->base_name);
2314         }
2315
2316         return result;
2317 }
2318
2319 static SMB_ACL_T smb_time_audit_sys_acl_get_file(vfs_handle_struct *handle,
2320                                         const struct smb_filename *smb_fname,
2321                                         SMB_ACL_TYPE_T type,
2322                                         TALLOC_CTX *mem_ctx)
2323 {
2324         SMB_ACL_T result;
2325         struct timespec ts1,ts2;
2326         double timediff;
2327
2328         clock_gettime_mono(&ts1);
2329         result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, smb_fname,
2330                                 type, mem_ctx);
2331         clock_gettime_mono(&ts2);
2332         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2333
2334         if (timediff > audit_timeout) {
2335                 smb_time_audit_log_fname("sys_acl_get_file", timediff,
2336                         smb_fname->base_name);
2337         }
2338
2339         return result;
2340 }
2341
2342 static SMB_ACL_T smb_time_audit_sys_acl_get_fd(vfs_handle_struct *handle,
2343                                                files_struct *fsp,
2344                                                TALLOC_CTX *mem_ctx)
2345 {
2346         SMB_ACL_T result;
2347         struct timespec ts1,ts2;
2348         double timediff;
2349
2350         clock_gettime_mono(&ts1);
2351         result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
2352         clock_gettime_mono(&ts2);
2353         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2354
2355         if (timediff > audit_timeout) {
2356                 smb_time_audit_log_fsp("sys_acl_get_fd", timediff, fsp);
2357         }
2358
2359         return result;
2360 }
2361
2362
2363 static int smb_time_audit_sys_acl_blob_get_file(vfs_handle_struct *handle,
2364                                 const struct smb_filename *smb_fname,
2365                                 TALLOC_CTX *mem_ctx,
2366                                 char **blob_description,
2367                                 DATA_BLOB *blob)
2368 {
2369         int result;
2370         struct timespec ts1,ts2;
2371         double timediff;
2372
2373         clock_gettime_mono(&ts1);
2374         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle, smb_fname,
2375                                 mem_ctx, blob_description, blob);
2376         clock_gettime_mono(&ts2);
2377         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2378
2379         if (timediff > audit_timeout) {
2380                 smb_time_audit_log("sys_acl_blob_get_file", timediff);
2381         }
2382
2383         return result;
2384 }
2385
2386 static int smb_time_audit_sys_acl_blob_get_fd(vfs_handle_struct *handle,
2387                                               files_struct *fsp,
2388                                               TALLOC_CTX *mem_ctx, 
2389                                               char **blob_description,
2390                                               DATA_BLOB *blob)
2391 {
2392         int result;
2393         struct timespec ts1,ts2;
2394         double timediff;
2395
2396         clock_gettime_mono(&ts1);
2397         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx, blob_description, blob);
2398         clock_gettime_mono(&ts2);
2399         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2400
2401         if (timediff > audit_timeout) {
2402                 smb_time_audit_log("sys_acl_blob_get_fd", timediff);
2403         }
2404
2405         return result;
2406 }
2407
2408 static int smb_time_audit_sys_acl_set_file(vfs_handle_struct *handle,
2409                                            const struct smb_filename *smb_fname,
2410                                            SMB_ACL_TYPE_T acltype,
2411                                            SMB_ACL_T theacl)
2412 {
2413         int result;
2414         struct timespec ts1,ts2;
2415         double timediff;
2416
2417         clock_gettime_mono(&ts1);
2418         result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, smb_fname, acltype,
2419                                                theacl);
2420         clock_gettime_mono(&ts2);
2421         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2422
2423         if (timediff > audit_timeout) {
2424                 smb_time_audit_log_fname("sys_acl_set_file", timediff,
2425                         smb_fname->base_name);
2426         }
2427
2428         return result;
2429 }
2430
2431 static int smb_time_audit_sys_acl_set_fd(vfs_handle_struct *handle,
2432                                          files_struct *fsp,
2433                                          SMB_ACL_T theacl)
2434 {
2435         int result;
2436         struct timespec ts1,ts2;
2437         double timediff;
2438
2439         clock_gettime_mono(&ts1);
2440         result = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
2441         clock_gettime_mono(&ts2);
2442         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2443
2444         if (timediff > audit_timeout) {
2445                 smb_time_audit_log_fsp("sys_acl_set_fd", timediff, fsp);
2446         }
2447
2448         return result;
2449 }
2450
2451 static int smb_time_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
2452                                 const struct smb_filename *smb_fname)
2453 {
2454         int result;
2455         struct timespec ts1,ts2;
2456         double timediff;
2457
2458         clock_gettime_mono(&ts1);
2459         result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, smb_fname);
2460         clock_gettime_mono(&ts2);
2461         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2462
2463         if (timediff > audit_timeout) {
2464                 smb_time_audit_log_fname("sys_acl_delete_def_file", timediff,
2465                         smb_fname->base_name);
2466         }
2467
2468         return result;
2469 }
2470
2471 static ssize_t smb_time_audit_getxattr(struct vfs_handle_struct *handle,
2472                                 const struct smb_filename *smb_fname,
2473                                 const char *name,
2474                                 void *value,
2475                                 size_t size)
2476 {
2477         ssize_t result;
2478         struct timespec ts1,ts2;
2479         double timediff;
2480
2481         clock_gettime_mono(&ts1);
2482         result = SMB_VFS_NEXT_GETXATTR(handle, smb_fname, name, value, size);
2483         clock_gettime_mono(&ts2);
2484         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2485
2486         if (timediff > audit_timeout) {
2487                 smb_time_audit_log_fname("getxattr", timediff,
2488                         smb_fname->base_name);
2489         }
2490
2491         return result;
2492 }
2493
2494 struct smb_time_audit_getxattrat_state {
2495         struct vfs_aio_state aio_state;
2496         files_struct *dir_fsp;
2497         const struct smb_filename *smb_fname;
2498         const char *xattr_name;
2499         ssize_t xattr_size;
2500         uint8_t *xattr_value;
2501 };
2502
2503 static void smb_time_audit_getxattrat_done(struct tevent_req *subreq);
2504
2505 static struct tevent_req *smb_time_audit_getxattrat_send(
2506                         TALLOC_CTX *mem_ctx,
2507                         struct tevent_context *ev,
2508                         struct vfs_handle_struct *handle,
2509                         files_struct *dir_fsp,
2510                         const struct smb_filename *smb_fname,
2511                         const char *xattr_name,
2512                         size_t alloc_hint)
2513 {
2514         struct tevent_req *req = NULL;
2515         struct tevent_req *subreq = NULL;
2516         struct smb_time_audit_getxattrat_state *state = NULL;
2517
2518         req = tevent_req_create(mem_ctx, &state,
2519                                 struct smb_time_audit_getxattrat_state);
2520         if (req == NULL) {
2521                 return NULL;
2522         }
2523         *state = (struct smb_time_audit_getxattrat_state) {
2524                 .dir_fsp = dir_fsp,
2525                 .smb_fname = smb_fname,
2526                 .xattr_name = xattr_name,
2527         };
2528
2529         subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
2530                                               ev,
2531                                               handle,
2532                                               dir_fsp,
2533                                               smb_fname,
2534                                               xattr_name,
2535                                               alloc_hint);
2536         if (tevent_req_nomem(subreq, req)) {
2537                 return tevent_req_post(req, ev);
2538         }
2539         tevent_req_set_callback(subreq, smb_time_audit_getxattrat_done, req);
2540
2541         return req;
2542 }
2543
2544 static void smb_time_audit_getxattrat_done(struct tevent_req *subreq)
2545 {
2546         struct tevent_req *req = tevent_req_callback_data(
2547                 subreq, struct tevent_req);
2548         struct smb_time_audit_getxattrat_state *state = tevent_req_data(
2549                 req, struct smb_time_audit_getxattrat_state);
2550
2551         state->xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV(subreq,
2552                                                          &state->aio_state,
2553                                                          state,
2554                                                          &state->xattr_value);
2555         TALLOC_FREE(subreq);
2556         if (state->xattr_size == -1) {
2557                 tevent_req_error(req, state->aio_state.error);
2558                 return;
2559         }
2560
2561         tevent_req_done(req);
2562 }
2563
2564 static ssize_t smb_time_audit_getxattrat_recv(struct tevent_req *req,
2565                                               struct vfs_aio_state *aio_state,
2566                                               TALLOC_CTX *mem_ctx,
2567                                               uint8_t **xattr_value)
2568 {
2569         struct smb_time_audit_getxattrat_state *state = tevent_req_data(
2570                 req, struct smb_time_audit_getxattrat_state);
2571         ssize_t xattr_size;
2572         double timediff;
2573
2574         timediff = state->aio_state.duration * 1.0e-9;
2575
2576         if (timediff > audit_timeout) {
2577                 smb_time_audit_log_at("async getxattrat",
2578                                       timediff,
2579                                       state->dir_fsp,
2580                                       state->smb_fname);
2581         }
2582
2583         if (tevent_req_is_unix_error(req, &aio_state->error)) {
2584                 tevent_req_received(req);
2585                 return -1;
2586         }
2587
2588         *aio_state = state->aio_state;
2589         xattr_size = state->xattr_size;
2590         if (xattr_value != NULL) {
2591                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2592         }
2593
2594         tevent_req_received(req);
2595         return xattr_size;
2596 }
2597
2598 static ssize_t smb_time_audit_fgetxattr(struct vfs_handle_struct *handle,
2599                                         struct files_struct *fsp,
2600                                         const char *name, void *value,
2601                                         size_t size)
2602 {
2603         ssize_t result;
2604         struct timespec ts1,ts2;
2605         double timediff;
2606
2607         clock_gettime_mono(&ts1);
2608         result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
2609         clock_gettime_mono(&ts2);
2610         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2611
2612         if (timediff > audit_timeout) {
2613                 smb_time_audit_log_fsp("fgetxattr", timediff, fsp);
2614         }
2615
2616         return result;
2617 }
2618
2619 static ssize_t smb_time_audit_listxattr(struct vfs_handle_struct *handle,
2620                                         const struct smb_filename *smb_fname,
2621                                         char *list,
2622                                         size_t size)
2623 {
2624         ssize_t result;
2625         struct timespec ts1,ts2;
2626         double timediff;
2627
2628         clock_gettime_mono(&ts1);
2629         result = SMB_VFS_NEXT_LISTXATTR(handle, smb_fname, list, size);
2630         clock_gettime_mono(&ts2);
2631         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2632
2633         if (timediff > audit_timeout) {
2634                 smb_time_audit_log_fname("listxattr", timediff,
2635                                 smb_fname->base_name);
2636         }
2637
2638         return result;
2639 }
2640
2641 static ssize_t smb_time_audit_flistxattr(struct vfs_handle_struct *handle,
2642                                          struct files_struct *fsp, char *list,
2643                                          size_t size)
2644 {
2645         ssize_t result;
2646         struct timespec ts1,ts2;
2647         double timediff;
2648
2649         clock_gettime_mono(&ts1);
2650         result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
2651         clock_gettime_mono(&ts2);
2652         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2653
2654         if (timediff > audit_timeout) {
2655                 smb_time_audit_log_fsp("flistxattr", timediff, fsp);
2656         }
2657
2658         return result;
2659 }
2660
2661 static int smb_time_audit_removexattr(struct vfs_handle_struct *handle,
2662                                 const struct smb_filename *smb_fname,
2663                                 const char *name)
2664 {
2665         int result;
2666         struct timespec ts1,ts2;
2667         double timediff;
2668
2669         clock_gettime_mono(&ts1);
2670         result = SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, name);
2671         clock_gettime_mono(&ts2);
2672         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2673
2674         if (timediff > audit_timeout) {
2675                 smb_time_audit_log_fname("removexattr", timediff,
2676                         smb_fname->base_name);
2677         }
2678
2679         return result;
2680 }
2681
2682 static int smb_time_audit_fremovexattr(struct vfs_handle_struct *handle,
2683                                        struct files_struct *fsp,
2684                                        const char *name)
2685 {
2686         int result;
2687         struct timespec ts1,ts2;
2688         double timediff;
2689
2690         clock_gettime_mono(&ts1);
2691         result = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
2692         clock_gettime_mono(&ts2);
2693         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2694
2695         if (timediff > audit_timeout) {
2696                 smb_time_audit_log_fsp("fremovexattr", timediff, fsp);
2697         }
2698
2699         return result;
2700 }
2701
2702 static int smb_time_audit_setxattr(struct vfs_handle_struct *handle,
2703                                 const struct smb_filename *smb_fname,
2704                                 const char *name,
2705                                 const void *value,
2706                                 size_t size,
2707                                 int flags)
2708 {
2709         int result;
2710         struct timespec ts1,ts2;
2711         double timediff;
2712
2713         clock_gettime_mono(&ts1);
2714         result = SMB_VFS_NEXT_SETXATTR(handle, smb_fname, name, value, size,
2715                                        flags);
2716         clock_gettime_mono(&ts2);
2717         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2718
2719         if (timediff > audit_timeout) {
2720                 smb_time_audit_log_fname("setxattr", timediff,
2721                                 smb_fname->base_name);
2722         }
2723
2724         return result;
2725 }
2726
2727 static int smb_time_audit_fsetxattr(struct vfs_handle_struct *handle,
2728                                     struct files_struct *fsp, const char *name,
2729                                     const void *value, size_t size, int flags)
2730 {
2731         int result;
2732         struct timespec ts1,ts2;
2733         double timediff;
2734
2735         clock_gettime_mono(&ts1);
2736         result = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags);
2737         clock_gettime_mono(&ts2);
2738         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2739
2740         if (timediff > audit_timeout) {
2741                 smb_time_audit_log_fsp("fsetxattr", timediff, fsp);
2742         }
2743
2744         return result;
2745 }
2746
2747 static bool smb_time_audit_aio_force(struct vfs_handle_struct *handle,
2748                                      struct files_struct *fsp)
2749 {
2750         bool result;
2751         struct timespec ts1,ts2;
2752         double timediff;
2753
2754         clock_gettime_mono(&ts1);
2755         result = SMB_VFS_NEXT_AIO_FORCE(handle, fsp);
2756         clock_gettime_mono(&ts2);
2757         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2758
2759         if (timediff > audit_timeout) {
2760                 smb_time_audit_log_fsp("aio_force", timediff, fsp);
2761         }
2762
2763         return result;
2764 }
2765
2766 static NTSTATUS smb_time_audit_durable_cookie(struct vfs_handle_struct *handle,
2767                                               struct files_struct *fsp,
2768                                               TALLOC_CTX *mem_ctx,
2769                                               DATA_BLOB *cookie)
2770 {
2771         NTSTATUS result;
2772         struct timespec ts1,ts2;
2773         double timediff;
2774
2775         clock_gettime_mono(&ts1);
2776         result = SMB_VFS_NEXT_DURABLE_COOKIE(handle, fsp, mem_ctx, cookie);
2777         clock_gettime_mono(&ts2);
2778         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2779
2780         if (timediff > audit_timeout) {
2781                 smb_time_audit_log_fsp("durable_cookie", timediff, fsp);
2782         }
2783
2784         return result;
2785 }
2786
2787 static NTSTATUS smb_time_audit_durable_disconnect(struct vfs_handle_struct *handle,
2788                                                   struct files_struct *fsp,
2789                                                   const DATA_BLOB old_cookie,
2790                                                   TALLOC_CTX *mem_ctx,
2791                                                   DATA_BLOB *new_cookie)
2792 {
2793         NTSTATUS result;
2794         struct timespec ts1,ts2;
2795         double timediff;
2796
2797         clock_gettime_mono(&ts1);
2798         result = SMB_VFS_NEXT_DURABLE_DISCONNECT(handle, fsp, old_cookie,
2799                                                  mem_ctx, new_cookie);
2800         clock_gettime_mono(&ts2);
2801         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2802
2803         if (timediff > audit_timeout) {
2804                 smb_time_audit_log_fsp("durable_disconnect", timediff, fsp);
2805         }
2806
2807         return result;
2808 }
2809
2810 static NTSTATUS smb_time_audit_durable_reconnect(struct vfs_handle_struct *handle,
2811                                                  struct smb_request *smb1req,
2812                                                  struct smbXsrv_open *op,
2813                                                  const DATA_BLOB old_cookie,
2814                                                  TALLOC_CTX *mem_ctx,
2815                                                  struct files_struct **fsp,
2816                                                  DATA_BLOB *new_cookie)
2817 {
2818         NTSTATUS result;
2819         struct timespec ts1,ts2;
2820         double timediff;
2821
2822         clock_gettime_mono(&ts1);
2823         result = SMB_VFS_NEXT_DURABLE_RECONNECT(handle, smb1req, op, old_cookie,
2824                                                 mem_ctx, fsp, new_cookie);
2825         clock_gettime_mono(&ts2);
2826         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2827
2828         if (timediff > audit_timeout) {
2829                 smb_time_audit_log("durable_reconnect", timediff);
2830         }
2831
2832         return result;
2833 }
2834
2835 /* VFS operations */
2836
2837 static struct vfs_fn_pointers vfs_time_audit_fns = {
2838         .connect_fn = smb_time_audit_connect,
2839         .disconnect_fn = smb_time_audit_disconnect,
2840         .disk_free_fn = smb_time_audit_disk_free,
2841         .get_quota_fn = smb_time_audit_get_quota,
2842         .set_quota_fn = smb_time_audit_set_quota,
2843         .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
2844         .statvfs_fn = smb_time_audit_statvfs,
2845         .fs_capabilities_fn = smb_time_audit_fs_capabilities,
2846         .get_dfs_referrals_fn = smb_time_audit_get_dfs_referrals,
2847         .opendir_fn = smb_time_audit_opendir,
2848         .fdopendir_fn = smb_time_audit_fdopendir,
2849         .readdir_fn = smb_time_audit_readdir,
2850         .seekdir_fn = smb_time_audit_seekdir,
2851         .telldir_fn = smb_time_audit_telldir,
2852         .rewind_dir_fn = smb_time_audit_rewinddir,
2853         .mkdirat_fn = smb_time_audit_mkdirat,
2854         .rmdir_fn = smb_time_audit_rmdir,
2855         .closedir_fn = smb_time_audit_closedir,
2856         .open_fn = smb_time_audit_open,
2857         .create_file_fn = smb_time_audit_create_file,
2858         .close_fn = smb_time_audit_close,
2859         .pread_fn = smb_time_audit_pread,
2860         .pread_send_fn = smb_time_audit_pread_send,
2861         .pread_recv_fn = smb_time_audit_pread_recv,
2862         .pwrite_fn = smb_time_audit_pwrite,
2863         .pwrite_send_fn = smb_time_audit_pwrite_send,
2864         .pwrite_recv_fn = smb_time_audit_pwrite_recv,
2865         .lseek_fn = smb_time_audit_lseek,
2866         .sendfile_fn = smb_time_audit_sendfile,
2867         .recvfile_fn = smb_time_audit_recvfile,
2868         .renameat_fn = smb_time_audit_renameat,
2869         .fsync_send_fn = smb_time_audit_fsync_send,
2870         .fsync_recv_fn = smb_time_audit_fsync_recv,
2871         .stat_fn = smb_time_audit_stat,
2872         .fstat_fn = smb_time_audit_fstat,
2873         .lstat_fn = smb_time_audit_lstat,
2874         .get_alloc_size_fn = smb_time_audit_get_alloc_size,
2875         .unlink_fn = smb_time_audit_unlink,
2876         .unlinkat_fn = smb_time_audit_unlinkat,
2877         .chmod_fn = smb_time_audit_chmod,
2878         .fchmod_fn = smb_time_audit_fchmod,
2879         .chown_fn = smb_time_audit_chown,
2880         .fchown_fn = smb_time_audit_fchown,
2881         .lchown_fn = smb_time_audit_lchown,
2882         .chdir_fn = smb_time_audit_chdir,
2883         .getwd_fn = smb_time_audit_getwd,
2884         .ntimes_fn = smb_time_audit_ntimes,
2885         .ftruncate_fn = smb_time_audit_ftruncate,
2886         .fallocate_fn = smb_time_audit_fallocate,
2887         .lock_fn = smb_time_audit_lock,
2888         .kernel_flock_fn = smb_time_audit_kernel_flock,
2889         .linux_setlease_fn = smb_time_audit_linux_setlease,
2890         .getlock_fn = smb_time_audit_getlock,
2891         .symlinkat_fn = smb_time_audit_symlinkat,
2892         .readlinkat_fn = smb_time_audit_readlinkat,
2893         .linkat_fn = smb_time_audit_linkat,
2894         .mknodat_fn = smb_time_audit_mknodat,
2895         .realpath_fn = smb_time_audit_realpath,
2896         .chflags_fn = smb_time_audit_chflags,
2897         .file_id_create_fn = smb_time_audit_file_id_create,
2898         .fs_file_id_fn = smb_time_audit_fs_file_id,
2899         .offload_read_send_fn = smb_time_audit_offload_read_send,
2900         .offload_read_recv_fn = smb_time_audit_offload_read_recv,
2901         .offload_write_send_fn = smb_time_audit_offload_write_send,
2902         .offload_write_recv_fn = smb_time_audit_offload_write_recv,
2903         .get_compression_fn = smb_time_audit_get_compression,
2904         .set_compression_fn = smb_time_audit_set_compression,
2905         .snap_check_path_fn = smb_time_audit_snap_check_path,
2906         .snap_create_fn = smb_time_audit_snap_create,
2907         .snap_delete_fn = smb_time_audit_snap_delete,
2908         .streaminfo_fn = smb_time_audit_streaminfo,
2909         .get_real_filename_fn = smb_time_audit_get_real_filename,
2910         .connectpath_fn = smb_time_audit_connectpath,
2911         .brl_lock_windows_fn = smb_time_audit_brl_lock_windows,
2912         .brl_unlock_windows_fn = smb_time_audit_brl_unlock_windows,
2913         .strict_lock_check_fn = smb_time_audit_strict_lock_check,
2914         .translate_name_fn = smb_time_audit_translate_name,
2915         .fsctl_fn = smb_time_audit_fsctl,
2916         .get_dos_attributes_fn = smb_time_get_dos_attributes,
2917         .get_dos_attributes_send_fn = smb_time_audit_get_dos_attributes_send,
2918         .get_dos_attributes_recv_fn = smb_time_audit_get_dos_attributes_recv,
2919         .fget_dos_attributes_fn = smb_time_fget_dos_attributes,
2920         .set_dos_attributes_fn = smb_time_set_dos_attributes,
2921         .fset_dos_attributes_fn = smb_time_fset_dos_attributes,
2922         .fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
2923         .get_nt_acl_fn = smb_time_audit_get_nt_acl,
2924         .fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
2925         .audit_file_fn = smb_time_audit_audit_file,
2926         .sys_acl_get_file_fn = smb_time_audit_sys_acl_get_file,
2927         .sys_acl_get_fd_fn = smb_time_audit_sys_acl_get_fd,
2928         .sys_acl_blob_get_file_fn = smb_time_audit_sys_acl_blob_get_file,
2929         .sys_acl_blob_get_fd_fn = smb_time_audit_sys_acl_blob_get_fd,
2930         .sys_acl_set_file_fn = smb_time_audit_sys_acl_set_file,
2931         .sys_acl_set_fd_fn = smb_time_audit_sys_acl_set_fd,
2932         .sys_acl_delete_def_file_fn = smb_time_audit_sys_acl_delete_def_file,
2933         .getxattr_fn = smb_time_audit_getxattr,
2934         .getxattrat_send_fn = smb_time_audit_getxattrat_send,
2935         .getxattrat_recv_fn = smb_time_audit_getxattrat_recv,
2936         .fgetxattr_fn = smb_time_audit_fgetxattr,
2937         .listxattr_fn = smb_time_audit_listxattr,
2938         .flistxattr_fn = smb_time_audit_flistxattr,
2939         .removexattr_fn = smb_time_audit_removexattr,
2940         .fremovexattr_fn = smb_time_audit_fremovexattr,
2941         .setxattr_fn = smb_time_audit_setxattr,
2942         .fsetxattr_fn = smb_time_audit_fsetxattr,
2943         .aio_force_fn = smb_time_audit_aio_force,
2944         .durable_cookie_fn = smb_time_audit_durable_cookie,
2945         .durable_disconnect_fn = smb_time_audit_durable_disconnect,
2946         .durable_reconnect_fn = smb_time_audit_durable_reconnect,
2947         .readdir_attr_fn = smb_time_audit_readdir_attr,
2948 };
2949
2950
2951 static_decl_vfs;
2952 NTSTATUS vfs_time_audit_init(TALLOC_CTX *ctx)
2953 {
2954         smb_vfs_assert_all_fns(&vfs_time_audit_fns, "time_audit");
2955
2956         audit_timeout = (double)lp_parm_int(-1, "time_audit", "timeout",
2957                                             10000) / 1000.0;
2958         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "time_audit",
2959                                 &vfs_time_audit_fns);
2960 }