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