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