s3:vfs: add create tags to SMB_VFS_CREATEFILE
[amitay/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_fname(const char *syscallname, double elapsed,
90                                     const char *fname)
91 {
92         char cwd[PATH_MAX];
93         char *msg = NULL;
94
95         if (getcwd(cwd, sizeof(cwd)) == NULL) {
96                 snprintf(cwd, sizeof(cwd), "<getcwd() error %d>", errno);
97         }
98         if (fname != NULL) {
99                 msg = talloc_asprintf(talloc_tos(),
100                                       "cwd = \"%s\", filename = \"%s\"",
101                                       cwd, fname);
102         } else {
103                 msg = talloc_asprintf(talloc_tos(),
104                                       "cwd = \"%s\", filename = <NULL>",
105                                       cwd);
106         }
107         smb_time_audit_log_msg(syscallname, elapsed, msg);
108         TALLOC_FREE(msg);
109 }
110
111 static void smb_time_audit_log_smb_fname(const char *syscallname, double elapsed,
112                                        const struct smb_filename *smb_fname)
113 {
114         if (smb_fname != NULL) {
115                 smb_time_audit_log_fname(syscallname, elapsed,
116                                          smb_fname->base_name);
117         } else {
118                 smb_time_audit_log_fname(syscallname, elapsed,
119                                          "smb_fname = <NULL>");
120         }
121 }
122
123 static int smb_time_audit_connect(vfs_handle_struct *handle,
124                                   const char *svc, const char *user)
125 {
126         int result;
127         struct timespec ts1,ts2;
128         double timediff;
129
130         if (!handle) {
131                 return -1;
132         }
133
134         clock_gettime_mono(&ts1);
135         result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
136         clock_gettime_mono(&ts2);
137         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
138         if (timediff > audit_timeout) {
139                 smb_time_audit_log_msg("connect", timediff, user);
140         }
141         return result;
142 }
143
144 static void smb_time_audit_disconnect(vfs_handle_struct *handle)
145 {
146         struct timespec ts1,ts2;
147         double timediff;
148
149         clock_gettime_mono(&ts1);
150         SMB_VFS_NEXT_DISCONNECT(handle);
151         clock_gettime_mono(&ts2);
152         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
153
154         if (timediff > audit_timeout) {
155                 smb_time_audit_log("disconnect", timediff);
156         }
157 }
158
159 static uint64_t smb_time_audit_disk_free(vfs_handle_struct *handle,
160                                          const char *path,
161                                          bool small_query, uint64_t *bsize,
162                                          uint64_t *dfree, uint64_t *dsize)
163 {
164         uint64_t result;
165         struct timespec ts1,ts2;
166         double timediff;
167
168         clock_gettime_mono(&ts1);
169         result = SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize,
170                                         dfree, dsize);
171         clock_gettime_mono(&ts2);
172         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
173
174         /* Don't have a reasonable notion of failure here */
175         if (timediff > audit_timeout) {
176                 smb_time_audit_log_fname("disk_free", timediff, path);
177         }
178
179         return result;
180 }
181
182 static int smb_time_audit_get_quota(struct vfs_handle_struct *handle,
183                                     enum SMB_QUOTA_TYPE qtype, unid_t id,
184                                     SMB_DISK_QUOTA *qt)
185 {
186         int result;
187         struct timespec ts1,ts2;
188         double timediff;
189
190         clock_gettime_mono(&ts1);
191         result = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt);
192         clock_gettime_mono(&ts2);
193         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
194
195         if (timediff > audit_timeout) {
196                 smb_time_audit_log("get_quota", timediff);
197         }
198         return result;
199 }
200
201 static int smb_time_audit_set_quota(struct vfs_handle_struct *handle,
202                                     enum SMB_QUOTA_TYPE qtype, unid_t id,
203                                     SMB_DISK_QUOTA *qt)
204 {
205         int result;
206         struct timespec ts1,ts2;
207         double timediff;
208
209         clock_gettime_mono(&ts1);
210         result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt);
211         clock_gettime_mono(&ts2);
212         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
213
214         if (timediff > audit_timeout) {
215                 smb_time_audit_log("set_quota", timediff);
216         }
217
218         return result;
219 }
220
221 static int smb_time_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
222                                                struct files_struct *fsp,
223                                                struct shadow_copy_data *shadow_copy_data,
224                                                bool labels)
225 {
226         int result;
227         struct timespec ts1,ts2;
228         double timediff;
229
230         clock_gettime_mono(&ts1);
231         result = SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp,
232                                                    shadow_copy_data, labels);
233         clock_gettime_mono(&ts2);
234         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
235
236         if (timediff > audit_timeout) {
237                 smb_time_audit_log_fsp("get_shadow_copy_data", timediff, fsp);
238         }
239
240         return result;
241 }
242
243 static int smb_time_audit_statvfs(struct vfs_handle_struct *handle,
244                                   const char *path,
245                                   struct vfs_statvfs_struct *statbuf)
246 {
247         int result;
248         struct timespec ts1,ts2;
249         double timediff;
250
251         clock_gettime_mono(&ts1);
252         result = SMB_VFS_NEXT_STATVFS(handle, path, statbuf);
253         clock_gettime_mono(&ts2);
254         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
255
256         if (timediff > audit_timeout) {
257                 smb_time_audit_log_fname("statvfs", timediff, path);
258         }
259
260         return result;
261 }
262
263 static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle,
264                                                enum timestamp_set_resolution *p_ts_res)
265 {
266         uint32_t result;
267         struct timespec ts1,ts2;
268         double timediff;
269
270         clock_gettime_mono(&ts1);
271         result = SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
272         clock_gettime_mono(&ts2);
273         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
274
275         if (timediff > audit_timeout) {
276                 smb_time_audit_log("fs_capabilities", timediff);
277         }
278
279         return result;
280 }
281
282 static DIR *smb_time_audit_opendir(vfs_handle_struct *handle,
283                                               const char *fname,
284                                               const char *mask, uint32 attr)
285 {
286         DIR *result;
287         struct timespec ts1,ts2;
288         double timediff;
289
290         clock_gettime_mono(&ts1);
291         result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
292         clock_gettime_mono(&ts2);
293         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
294
295         if (timediff > audit_timeout) {
296                 smb_time_audit_log_fname("opendir", timediff, fname);
297         }
298
299         return result;
300 }
301
302 static DIR *smb_time_audit_fdopendir(vfs_handle_struct *handle,
303                                               files_struct *fsp,
304                                               const char *mask, uint32 attr)
305 {
306         DIR *result;
307         struct timespec ts1,ts2;
308         double timediff;
309
310         clock_gettime_mono(&ts1);
311         result = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr);
312         clock_gettime_mono(&ts2);
313         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
314
315         if (timediff > audit_timeout) {
316                 smb_time_audit_log_fsp("fdopendir", timediff, fsp);
317         }
318
319         return result;
320 }
321
322 static struct dirent *smb_time_audit_readdir(vfs_handle_struct *handle,
323                                                  DIR *dirp,
324                                                  SMB_STRUCT_STAT *sbuf)
325 {
326         struct dirent *result;
327         struct timespec ts1,ts2;
328         double timediff;
329
330         clock_gettime_mono(&ts1);
331         result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf);
332         clock_gettime_mono(&ts2);
333         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
334
335         if (timediff > audit_timeout) {
336                 smb_time_audit_log("readdir", timediff);
337         }
338
339         return result;
340 }
341
342 static void smb_time_audit_seekdir(vfs_handle_struct *handle,
343                                    DIR *dirp, long offset)
344 {
345         struct timespec ts1,ts2;
346         double timediff;
347
348         clock_gettime_mono(&ts1);
349         SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset);
350         clock_gettime_mono(&ts2);
351         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
352
353         if (timediff > audit_timeout) {
354                 smb_time_audit_log("seekdir", timediff);
355         }
356
357 }
358
359 static long smb_time_audit_telldir(vfs_handle_struct *handle,
360                                    DIR *dirp)
361 {
362         long result;
363         struct timespec ts1,ts2;
364         double timediff;
365
366         clock_gettime_mono(&ts1);
367         result = SMB_VFS_NEXT_TELLDIR(handle, dirp);
368         clock_gettime_mono(&ts2);
369         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
370
371         if (timediff > audit_timeout) {
372                 smb_time_audit_log("telldir", timediff);
373         }
374
375         return result;
376 }
377
378 static void smb_time_audit_rewinddir(vfs_handle_struct *handle,
379                                      DIR *dirp)
380 {
381         struct timespec ts1,ts2;
382         double timediff;
383
384         clock_gettime_mono(&ts1);
385         SMB_VFS_NEXT_REWINDDIR(handle, dirp);
386         clock_gettime_mono(&ts2);
387         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
388
389         if (timediff > audit_timeout) {
390                 smb_time_audit_log("rewinddir", timediff);
391         }
392
393 }
394
395 static int smb_time_audit_mkdir(vfs_handle_struct *handle,
396                                 const char *path, mode_t mode)
397 {
398         int result;
399         struct timespec ts1,ts2;
400         double timediff;
401
402         clock_gettime_mono(&ts1);
403         result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
404         clock_gettime_mono(&ts2);
405         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
406
407         if (timediff > audit_timeout) {
408                 smb_time_audit_log_fname("mkdir", timediff, path);
409         }
410
411         return result;
412 }
413
414 static int smb_time_audit_rmdir(vfs_handle_struct *handle,
415                                 const char *path)
416 {
417         int result;
418         struct timespec ts1,ts2;
419         double timediff;
420
421         clock_gettime_mono(&ts1);
422         result = SMB_VFS_NEXT_RMDIR(handle, path);
423         clock_gettime_mono(&ts2);
424         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
425
426         if (timediff > audit_timeout) {
427                 smb_time_audit_log_fname("rmdir", timediff, path);
428         }
429
430         return result;
431 }
432
433 static int smb_time_audit_closedir(vfs_handle_struct *handle,
434                                    DIR *dirp)
435 {
436         int result;
437         struct timespec ts1,ts2;
438         double timediff;
439
440         clock_gettime_mono(&ts1);
441         result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
442         clock_gettime_mono(&ts2);
443         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
444
445         if (timediff > audit_timeout) {
446                 smb_time_audit_log("closedir", timediff);
447         }
448
449         return result;
450 }
451
452 static void smb_time_audit_init_search_op(vfs_handle_struct *handle,
453                                           DIR *dirp)
454 {
455         struct timespec ts1,ts2;
456         double timediff;
457
458         clock_gettime_mono(&ts1);
459         SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp);
460         clock_gettime_mono(&ts2);
461         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
462
463         if (timediff > audit_timeout) {
464                 smb_time_audit_log("init_search_op", timediff);
465         }
466 }
467
468 static int smb_time_audit_open(vfs_handle_struct *handle,
469                                struct smb_filename *fname,
470                                files_struct *fsp,
471                                int flags, mode_t mode)
472 {
473         int result;
474         struct timespec ts1,ts2;
475         double timediff;
476
477         clock_gettime_mono(&ts1);
478         result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
479         clock_gettime_mono(&ts2);
480         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
481
482         if (timediff > audit_timeout) {
483                 smb_time_audit_log_fsp("open", timediff, fsp);
484         }
485
486         return result;
487 }
488
489 static NTSTATUS smb_time_audit_create_file(vfs_handle_struct *handle,
490                                            struct smb_request *req,
491                                            uint16_t root_dir_fid,
492                                            struct smb_filename *fname,
493                                            uint32_t access_mask,
494                                            uint32_t share_access,
495                                            uint32_t create_disposition,
496                                            uint32_t create_options,
497                                            uint32_t file_attributes,
498                                            uint32_t oplock_request,
499                                            struct smb2_lease *lease,
500                                            uint64_t allocation_size,
501                                            uint32_t private_flags,
502                                            struct security_descriptor *sd,
503                                            struct ea_list *ea_list,
504                                            files_struct **result_fsp,
505                                            int *pinfo,
506                                            const struct smb2_create_blobs *in_context_blobs,
507                                            struct smb2_create_blobs *out_context_blobs)
508 {
509         NTSTATUS result;
510         struct timespec ts1,ts2;
511         double timediff;
512
513         clock_gettime_mono(&ts1);
514         result = SMB_VFS_NEXT_CREATE_FILE(
515                 handle,                                 /* handle */
516                 req,                                    /* req */
517                 root_dir_fid,                           /* root_dir_fid */
518                 fname,                                  /* fname */
519                 access_mask,                            /* access_mask */
520                 share_access,                           /* share_access */
521                 create_disposition,                     /* create_disposition*/
522                 create_options,                         /* create_options */
523                 file_attributes,                        /* file_attributes */
524                 oplock_request,                         /* oplock_request */
525                 lease,                                  /* lease */
526                 allocation_size,                        /* allocation_size */
527                 private_flags,
528                 sd,                                     /* sd */
529                 ea_list,                                /* ea_list */
530                 result_fsp,                             /* result */
531                 pinfo,
532                 in_context_blobs, out_context_blobs);   /* create context */
533         clock_gettime_mono(&ts2);
534         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
535
536         if (timediff > audit_timeout) {
537                 /*
538                  * can't use result_fsp this time, may have
539                  * invalid content causing smbd crash
540                  */
541                 smb_time_audit_log_smb_fname("create_file", timediff,
542                                            fname);
543         }
544
545         return result;
546 }
547
548 static int smb_time_audit_close(vfs_handle_struct *handle, files_struct *fsp)
549 {
550         int result;
551         struct timespec ts1,ts2;
552         double timediff;
553
554         clock_gettime_mono(&ts1);
555         result = SMB_VFS_NEXT_CLOSE(handle, fsp);
556         clock_gettime_mono(&ts2);
557         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
558
559         if (timediff > audit_timeout) {
560                 smb_time_audit_log_fsp("close", timediff, fsp);
561         }
562
563         return result;
564 }
565
566 static ssize_t smb_time_audit_read(vfs_handle_struct *handle,
567                                    files_struct *fsp, void *data, size_t n)
568 {
569         ssize_t result;
570         struct timespec ts1,ts2;
571         double timediff;
572
573         clock_gettime_mono(&ts1);
574         result = SMB_VFS_NEXT_READ(handle, fsp, data, n);
575         clock_gettime_mono(&ts2);
576         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
577
578         if (timediff > audit_timeout) {
579                 smb_time_audit_log_fsp("read", timediff, fsp);
580         }
581
582         return result;
583 }
584
585 static ssize_t smb_time_audit_pread(vfs_handle_struct *handle,
586                                     files_struct *fsp,
587                                     void *data, size_t n, off_t offset)
588 {
589         ssize_t result;
590         struct timespec ts1,ts2;
591         double timediff;
592
593         clock_gettime_mono(&ts1);
594         result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
595         clock_gettime_mono(&ts2);
596         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
597
598         if (timediff > audit_timeout) {
599                 smb_time_audit_log_fsp("pread", timediff, fsp);
600         }
601
602         return result;
603 }
604
605 struct smb_time_audit_pread_state {
606         struct files_struct *fsp;
607         struct timespec ts1;
608         ssize_t ret;
609         int err;
610 };
611
612 static void smb_time_audit_pread_done(struct tevent_req *subreq);
613
614 static struct tevent_req *smb_time_audit_pread_send(
615         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
616         struct tevent_context *ev, struct files_struct *fsp,
617         void *data, size_t n, off_t offset)
618 {
619         struct tevent_req *req, *subreq;
620         struct smb_time_audit_pread_state *state;
621
622         req = tevent_req_create(mem_ctx, &state,
623                                 struct smb_time_audit_pread_state);
624         if (req == NULL) {
625                 return NULL;
626         }
627         clock_gettime_mono(&state->ts1);
628         state->fsp = fsp;
629
630         subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
631                                          n, offset);
632         if (tevent_req_nomem(subreq, req)) {
633                 return tevent_req_post(req, ev);
634         }
635         tevent_req_set_callback(subreq, smb_time_audit_pread_done, req);
636         return req;
637 }
638
639 static void smb_time_audit_pread_done(struct tevent_req *subreq)
640 {
641         struct tevent_req *req = tevent_req_callback_data(
642                 subreq, struct tevent_req);
643         struct smb_time_audit_pread_state *state = tevent_req_data(
644                 req, struct smb_time_audit_pread_state);
645
646         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
647         TALLOC_FREE(subreq);
648         tevent_req_done(req);
649 }
650
651 static ssize_t smb_time_audit_pread_recv(struct tevent_req *req, int *err)
652 {
653         struct smb_time_audit_pread_state *state = tevent_req_data(
654                 req, struct smb_time_audit_pread_state);
655         struct timespec ts2;
656         double timediff;
657
658         clock_gettime_mono(&ts2);
659         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
660
661         if (timediff > audit_timeout) {
662                 smb_time_audit_log_fsp("pread", timediff, state->fsp);
663         }
664
665         if (tevent_req_is_unix_error(req, err)) {
666                 return -1;
667         }
668         *err = state->err;
669         return state->ret;
670 }
671
672 static ssize_t smb_time_audit_write(vfs_handle_struct *handle,
673                                     files_struct *fsp,
674                                     const void *data, size_t n)
675 {
676         ssize_t result;
677         struct timespec ts1,ts2;
678         double timediff;
679
680         clock_gettime_mono(&ts1);
681         result = SMB_VFS_NEXT_WRITE(handle, fsp, data, n);
682         clock_gettime_mono(&ts2);
683         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
684
685         if (timediff > audit_timeout) {
686                 smb_time_audit_log_fsp("write", timediff, fsp);
687         }
688
689         return result;
690 }
691
692 static ssize_t smb_time_audit_pwrite(vfs_handle_struct *handle,
693                                      files_struct *fsp,
694                                      const void *data, size_t n,
695                                      off_t offset)
696 {
697         ssize_t result;
698         struct timespec ts1,ts2;
699         double timediff;
700
701         clock_gettime_mono(&ts1);
702         result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
703         clock_gettime_mono(&ts2);
704         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
705
706         if (timediff > audit_timeout) {
707                 smb_time_audit_log_fsp("pwrite", timediff, fsp);
708         }
709
710         return result;
711 }
712
713 struct smb_time_audit_pwrite_state {
714         struct files_struct *fsp;
715         struct timespec ts1;
716         ssize_t ret;
717         int err;
718 };
719
720 static void smb_time_audit_pwrite_done(struct tevent_req *subreq);
721
722 static struct tevent_req *smb_time_audit_pwrite_send(
723         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
724         struct tevent_context *ev, struct files_struct *fsp,
725         const void *data, size_t n, off_t offset)
726 {
727         struct tevent_req *req, *subreq;
728         struct smb_time_audit_pwrite_state *state;
729
730         req = tevent_req_create(mem_ctx, &state,
731                                 struct smb_time_audit_pwrite_state);
732         if (req == NULL) {
733                 return NULL;
734         }
735         clock_gettime_mono(&state->ts1);
736         state->fsp = fsp;
737
738         subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
739                                          n, offset);
740         if (tevent_req_nomem(subreq, req)) {
741                 return tevent_req_post(req, ev);
742         }
743         tevent_req_set_callback(subreq, smb_time_audit_pwrite_done, req);
744         return req;
745 }
746
747 static void smb_time_audit_pwrite_done(struct tevent_req *subreq)
748 {
749         struct tevent_req *req = tevent_req_callback_data(
750                 subreq, struct tevent_req);
751         struct smb_time_audit_pwrite_state *state = tevent_req_data(
752                 req, struct smb_time_audit_pwrite_state);
753
754         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
755         TALLOC_FREE(subreq);
756         tevent_req_done(req);
757 }
758
759 static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req, int *err)
760 {
761         struct smb_time_audit_pwrite_state *state = tevent_req_data(
762                 req, struct smb_time_audit_pwrite_state);
763         struct timespec ts2;
764         double timediff;
765
766         clock_gettime_mono(&ts2);
767         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
768
769         if (timediff > audit_timeout) {
770                 smb_time_audit_log_fsp("pwrite", timediff, state->fsp);
771         }
772
773         if (tevent_req_is_unix_error(req, err)) {
774                 return -1;
775         }
776         *err = state->err;
777         return state->ret;
778 }
779
780 static off_t smb_time_audit_lseek(vfs_handle_struct *handle,
781                                       files_struct *fsp,
782                                       off_t offset, int whence)
783 {
784         off_t result;
785         struct timespec ts1,ts2;
786         double timediff;
787
788         clock_gettime_mono(&ts1);
789         result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
790         clock_gettime_mono(&ts2);
791         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
792
793         if (timediff > audit_timeout) {
794                 smb_time_audit_log_fsp("lseek", timediff, fsp);
795         }
796
797         return result;
798 }
799
800 static ssize_t smb_time_audit_sendfile(vfs_handle_struct *handle, int tofd,
801                                        files_struct *fromfsp,
802                                        const DATA_BLOB *hdr, off_t offset,
803                                        size_t n)
804 {
805         ssize_t result;
806         struct timespec ts1,ts2;
807         double timediff;
808
809         clock_gettime_mono(&ts1);
810         result = SMB_VFS_NEXT_SENDFILE(handle, tofd, fromfsp, hdr, offset, n);
811         clock_gettime_mono(&ts2);
812         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
813
814         if (timediff > audit_timeout) {
815                 smb_time_audit_log_fsp("sendfile", timediff, fromfsp);
816         }
817
818         return result;
819 }
820
821 static ssize_t smb_time_audit_recvfile(vfs_handle_struct *handle, int fromfd,
822                                        files_struct *tofsp,
823                                        off_t offset,
824                                        size_t n)
825 {
826         ssize_t result;
827         struct timespec ts1,ts2;
828         double timediff;
829
830         clock_gettime_mono(&ts1);
831         result = SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, n);
832         clock_gettime_mono(&ts2);
833         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
834
835         if (timediff > audit_timeout) {
836                 smb_time_audit_log_fsp("recvfile", timediff, tofsp);
837         }
838
839         return result;
840 }
841
842 static int smb_time_audit_rename(vfs_handle_struct *handle,
843                                  const struct smb_filename *oldname,
844                                  const struct smb_filename *newname)
845 {
846         int result;
847         struct timespec ts1,ts2;
848         double timediff;
849
850         clock_gettime_mono(&ts1);
851         result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
852         clock_gettime_mono(&ts2);
853         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
854
855         if (timediff > audit_timeout) {
856                 smb_time_audit_log_smb_fname("rename", timediff, newname);
857         }
858
859         return result;
860 }
861
862 static int smb_time_audit_fsync(vfs_handle_struct *handle, files_struct *fsp)
863 {
864         int result;
865         struct timespec ts1,ts2;
866         double timediff;
867
868         clock_gettime_mono(&ts1);
869         result = SMB_VFS_NEXT_FSYNC(handle, fsp);
870         clock_gettime_mono(&ts2);
871         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
872
873         if (timediff > audit_timeout) {
874                 smb_time_audit_log_fsp("fsync", timediff, fsp);
875         }
876
877         return result;
878 }
879
880 struct smb_time_audit_fsync_state {
881         struct files_struct *fsp;
882         struct timespec ts1;
883         int ret;
884         int err;
885 };
886
887 static void smb_time_audit_fsync_done(struct tevent_req *subreq);
888
889 static struct tevent_req *smb_time_audit_fsync_send(
890         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
891         struct tevent_context *ev, struct files_struct *fsp)
892 {
893         struct tevent_req *req, *subreq;
894         struct smb_time_audit_fsync_state *state;
895
896         req = tevent_req_create(mem_ctx, &state,
897                                 struct smb_time_audit_fsync_state);
898         if (req == NULL) {
899                 return NULL;
900         }
901         clock_gettime_mono(&state->ts1);
902         state->fsp = fsp;
903
904         subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
905         if (tevent_req_nomem(subreq, req)) {
906                 return tevent_req_post(req, ev);
907         }
908         tevent_req_set_callback(subreq, smb_time_audit_fsync_done, req);
909         return req;
910 }
911
912 static void smb_time_audit_fsync_done(struct tevent_req *subreq)
913 {
914         struct tevent_req *req = tevent_req_callback_data(
915                 subreq, struct tevent_req);
916         struct smb_time_audit_fsync_state *state = tevent_req_data(
917                 req, struct smb_time_audit_fsync_state);
918
919         state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->err);
920         TALLOC_FREE(subreq);
921         tevent_req_done(req);
922 }
923
924 static int smb_time_audit_fsync_recv(struct tevent_req *req, int *err)
925 {
926         struct smb_time_audit_fsync_state *state = tevent_req_data(
927                 req, struct smb_time_audit_fsync_state);
928         struct timespec ts2;
929         double timediff;
930
931         clock_gettime_mono(&ts2);
932         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
933
934         if (timediff > audit_timeout) {
935                 smb_time_audit_log_fsp("fsync", timediff, state->fsp);
936         }
937
938         if (tevent_req_is_unix_error(req, err)) {
939                 return -1;
940         }
941         *err = state->err;
942         return state->ret;
943 }
944
945 static int smb_time_audit_stat(vfs_handle_struct *handle,
946                                struct smb_filename *fname)
947 {
948         int result;
949         struct timespec ts1,ts2;
950         double timediff;
951
952         clock_gettime_mono(&ts1);
953         result = SMB_VFS_NEXT_STAT(handle, fname);
954         clock_gettime_mono(&ts2);
955         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
956
957         if (timediff > audit_timeout) {
958                 smb_time_audit_log_smb_fname("stat", timediff, fname);
959         }
960
961         return result;
962 }
963
964 static int smb_time_audit_fstat(vfs_handle_struct *handle, files_struct *fsp,
965                                 SMB_STRUCT_STAT *sbuf)
966 {
967         int result;
968         struct timespec ts1,ts2;
969         double timediff;
970
971         clock_gettime_mono(&ts1);
972         result = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
973         clock_gettime_mono(&ts2);
974         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
975
976         if (timediff > audit_timeout) {
977                 smb_time_audit_log_fsp("fstat", timediff, fsp);
978         }
979
980         return result;
981 }
982
983 static int smb_time_audit_lstat(vfs_handle_struct *handle,
984                                 struct smb_filename *path)
985 {
986         int result;
987         struct timespec ts1,ts2;
988         double timediff;
989
990         clock_gettime_mono(&ts1);
991         result = SMB_VFS_NEXT_LSTAT(handle, path);
992         clock_gettime_mono(&ts2);
993         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
994
995         if (timediff > audit_timeout) {
996                 smb_time_audit_log_smb_fname("lstat", timediff, path);
997         }
998
999         return result;
1000 }
1001
1002 static uint64_t smb_time_audit_get_alloc_size(vfs_handle_struct *handle,
1003                                               files_struct *fsp,
1004                                               const SMB_STRUCT_STAT *sbuf)
1005 {
1006         uint64_t result;
1007         struct timespec ts1,ts2;
1008         double timediff;
1009
1010         clock_gettime_mono(&ts1);
1011         result = SMB_VFS_NEXT_GET_ALLOC_SIZE(handle, fsp, sbuf);
1012         clock_gettime_mono(&ts2);
1013         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1014
1015         if (timediff > audit_timeout) {
1016                 smb_time_audit_log_fsp("get_alloc_size", timediff, fsp);
1017         }
1018
1019         return result;
1020 }
1021
1022 static int smb_time_audit_unlink(vfs_handle_struct *handle,
1023                                  const struct smb_filename *path)
1024 {
1025         int result;
1026         struct timespec ts1,ts2;
1027         double timediff;
1028
1029         clock_gettime_mono(&ts1);
1030         result = SMB_VFS_NEXT_UNLINK(handle, path);
1031         clock_gettime_mono(&ts2);
1032         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1033
1034         if (timediff > audit_timeout) {
1035                 smb_time_audit_log_smb_fname("unlink", timediff, path);
1036         }
1037
1038         return result;
1039 }
1040
1041 static int smb_time_audit_chmod(vfs_handle_struct *handle,
1042                                 const char *path, mode_t mode)
1043 {
1044         int result;
1045         struct timespec ts1,ts2;
1046         double timediff;
1047
1048         clock_gettime_mono(&ts1);
1049         result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
1050         clock_gettime_mono(&ts2);
1051         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1052
1053         if (timediff > audit_timeout) {
1054                 smb_time_audit_log_fname("chmod", timediff, path);
1055         }
1056
1057         return result;
1058 }
1059
1060 static int smb_time_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp,
1061                                  mode_t mode)
1062 {
1063         int result;
1064         struct timespec ts1,ts2;
1065         double timediff;
1066
1067         clock_gettime_mono(&ts1);
1068         result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1069         clock_gettime_mono(&ts2);
1070         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1071
1072         if (timediff > audit_timeout) {
1073                 smb_time_audit_log_fsp("fchmod", timediff, fsp);
1074         }
1075
1076         return result;
1077 }
1078
1079 static int smb_time_audit_chown(vfs_handle_struct *handle,
1080                                 const char *path, uid_t uid, gid_t gid)
1081 {
1082         int result;
1083         struct timespec ts1,ts2;
1084         double timediff;
1085
1086         clock_gettime_mono(&ts1);
1087         result = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
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_fname("chown", timediff, path);
1093         }
1094
1095         return result;
1096 }
1097
1098 static int smb_time_audit_fchown(vfs_handle_struct *handle, files_struct *fsp,
1099                                  uid_t uid, gid_t gid)
1100 {
1101         int result;
1102         struct timespec ts1,ts2;
1103         double timediff;
1104
1105         clock_gettime_mono(&ts1);
1106         result = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1107         clock_gettime_mono(&ts2);
1108         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1109
1110         if (timediff > audit_timeout) {
1111                 smb_time_audit_log_fsp("fchown", timediff, fsp);
1112         }
1113
1114         return result;
1115 }
1116
1117 static int smb_time_audit_lchown(vfs_handle_struct *handle,
1118                                  const char *path, uid_t uid, gid_t gid)
1119 {
1120         int result;
1121         struct timespec ts1,ts2;
1122         double timediff;
1123
1124         clock_gettime_mono(&ts1);
1125         result = SMB_VFS_NEXT_LCHOWN(handle, path, uid, gid);
1126         clock_gettime_mono(&ts2);
1127         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1128
1129         if (timediff > audit_timeout) {
1130                 smb_time_audit_log_fname("lchown", timediff, path);
1131         }
1132
1133         return result;
1134 }
1135
1136 static int smb_time_audit_chdir(vfs_handle_struct *handle, const char *path)
1137 {
1138         int result;
1139         struct timespec ts1,ts2;
1140         double timediff;
1141
1142         clock_gettime_mono(&ts1);
1143         result = SMB_VFS_NEXT_CHDIR(handle, path);
1144         clock_gettime_mono(&ts2);
1145         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1146
1147         if (timediff > audit_timeout) {
1148                 smb_time_audit_log_fname("chdir", timediff, path);
1149         }
1150
1151         return result;
1152 }
1153
1154 static char *smb_time_audit_getwd(vfs_handle_struct *handle)
1155 {
1156         char *result;
1157         struct timespec ts1,ts2;
1158         double timediff;
1159
1160         clock_gettime_mono(&ts1);
1161         result = SMB_VFS_NEXT_GETWD(handle);
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("getwd", timediff);
1167         }
1168
1169         return result;
1170 }
1171
1172 static int smb_time_audit_ntimes(vfs_handle_struct *handle,
1173                                  const struct smb_filename *path,
1174                                  struct smb_file_time *ft)
1175 {
1176         int result;
1177         struct timespec ts1,ts2;
1178         double timediff;
1179
1180         clock_gettime_mono(&ts1);
1181         result = SMB_VFS_NEXT_NTIMES(handle, path, ft);
1182         clock_gettime_mono(&ts2);
1183         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1184
1185         if (timediff > audit_timeout) {
1186                 smb_time_audit_log_smb_fname("ntimes", timediff, path);
1187         }
1188
1189         return result;
1190 }
1191
1192 static int smb_time_audit_ftruncate(vfs_handle_struct *handle,
1193                                     files_struct *fsp,
1194                                     off_t len)
1195 {
1196         int result;
1197         struct timespec ts1,ts2;
1198         double timediff;
1199
1200         clock_gettime_mono(&ts1);
1201         result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
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_fsp("ftruncate", timediff, fsp);
1207         }
1208
1209         return result;
1210 }
1211
1212 static int smb_time_audit_fallocate(vfs_handle_struct *handle,
1213                                     files_struct *fsp,
1214                                     enum vfs_fallocate_mode mode,
1215                                     off_t offset,
1216                                     off_t len)
1217 {
1218         int result;
1219         struct timespec ts1,ts2;
1220         double timediff;
1221
1222         clock_gettime_mono(&ts1);
1223         result = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1224         clock_gettime_mono(&ts2);
1225         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1226
1227         if (timediff > audit_timeout) {
1228                 smb_time_audit_log_fsp("fallocate", timediff, fsp);
1229         }
1230
1231         return result;
1232 }
1233
1234 static bool smb_time_audit_lock(vfs_handle_struct *handle, files_struct *fsp,
1235                                 int op, off_t offset, off_t count,
1236                                 int type)
1237 {
1238         bool result;
1239         struct timespec ts1,ts2;
1240         double timediff;
1241
1242         clock_gettime_mono(&ts1);
1243         result = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
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_fsp("lock", timediff, fsp);
1249         }
1250
1251         return result;
1252 }
1253
1254 static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
1255                                        struct files_struct *fsp,
1256                                        uint32 share_mode, uint32 access_mask)
1257 {
1258         int result;
1259         struct timespec ts1,ts2;
1260         double timediff;
1261
1262         clock_gettime_mono(&ts1);
1263         result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode,
1264                                            access_mask);
1265         clock_gettime_mono(&ts2);
1266         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1267
1268         if (timediff > audit_timeout) {
1269                 smb_time_audit_log_fsp("kernel_flock", timediff, fsp);
1270         }
1271
1272         return result;
1273 }
1274
1275 static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
1276                                          files_struct *fsp,
1277                                          int leasetype)
1278 {
1279         int result;
1280         struct timespec ts1,ts2;
1281         double timediff;
1282
1283         clock_gettime_mono(&ts1);
1284         result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
1285         clock_gettime_mono(&ts2);
1286         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1287
1288         if (timediff > audit_timeout) {
1289                 smb_time_audit_log_fsp("linux_setlease", timediff, fsp);
1290         }
1291
1292         return result;
1293 }
1294
1295 static bool smb_time_audit_getlock(vfs_handle_struct *handle,
1296                                    files_struct *fsp,
1297                                    off_t *poffset, off_t *pcount,
1298                                    int *ptype, pid_t *ppid)
1299 {
1300         bool result;
1301         struct timespec ts1,ts2;
1302         double timediff;
1303
1304         clock_gettime_mono(&ts1);
1305         result = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype,
1306                                       ppid);
1307         clock_gettime_mono(&ts2);
1308         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1309
1310         if (timediff > audit_timeout) {
1311                 smb_time_audit_log_fsp("getlock", timediff, fsp);
1312         }
1313
1314         return result;
1315 }
1316
1317 static int smb_time_audit_symlink(vfs_handle_struct *handle,
1318                                   const char *oldpath, const char *newpath)
1319 {
1320         int result;
1321         struct timespec ts1,ts2;
1322         double timediff;
1323
1324         clock_gettime_mono(&ts1);
1325         result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
1326         clock_gettime_mono(&ts2);
1327         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1328
1329         if (timediff > audit_timeout) {
1330                 smb_time_audit_log_fname("symlink", timediff, newpath);
1331         }
1332
1333         return result;
1334 }
1335
1336 static int smb_time_audit_readlink(vfs_handle_struct *handle,
1337                           const char *path, char *buf, size_t bufsiz)
1338 {
1339         int result;
1340         struct timespec ts1,ts2;
1341         double timediff;
1342
1343         clock_gettime_mono(&ts1);
1344         result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
1345         clock_gettime_mono(&ts2);
1346         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1347
1348         if (timediff > audit_timeout) {
1349                 smb_time_audit_log_fname("readlink", timediff, path);
1350         }
1351
1352         return result;
1353 }
1354
1355 static int smb_time_audit_link(vfs_handle_struct *handle,
1356                                const char *oldpath, const char *newpath)
1357 {
1358         int result;
1359         struct timespec ts1,ts2;
1360         double timediff;
1361
1362         clock_gettime_mono(&ts1);
1363         result = SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
1364         clock_gettime_mono(&ts2);
1365         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1366
1367         if (timediff > audit_timeout) {
1368                 smb_time_audit_log_fname("link", timediff, newpath);
1369         }
1370
1371         return result;
1372 }
1373
1374 static int smb_time_audit_mknod(vfs_handle_struct *handle,
1375                                 const char *pathname, mode_t mode,
1376                                 SMB_DEV_T dev)
1377 {
1378         int result;
1379         struct timespec ts1,ts2;
1380         double timediff;
1381
1382         clock_gettime_mono(&ts1);
1383         result = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev);
1384         clock_gettime_mono(&ts2);
1385         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1386
1387         if (timediff > audit_timeout) {
1388                 smb_time_audit_log_fname("mknod", timediff, pathname);
1389         }
1390
1391         return result;
1392 }
1393
1394 static char *smb_time_audit_realpath(vfs_handle_struct *handle,
1395                                      const char *path)
1396 {
1397         char *result;
1398         struct timespec ts1,ts2;
1399         double timediff;
1400
1401         clock_gettime_mono(&ts1);
1402         result = SMB_VFS_NEXT_REALPATH(handle, path);
1403         clock_gettime_mono(&ts2);
1404         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1405
1406         if (timediff > audit_timeout) {
1407                 smb_time_audit_log_fname("realpath", timediff, path);
1408         }
1409
1410         return result;
1411 }
1412
1413 static NTSTATUS smb_time_audit_notify_watch(struct vfs_handle_struct *handle,
1414                         struct sys_notify_context *ctx,
1415                         const char *path,
1416                         uint32_t *filter,
1417                         uint32_t *subdir_filter,
1418                         void (*callback)(struct sys_notify_context *ctx,
1419                                         void *private_data,
1420                                         struct notify_event *ev),
1421                         void *private_data, void *handle_p)
1422 {
1423         NTSTATUS result;
1424         struct timespec ts1,ts2;
1425         double timediff;
1426
1427         clock_gettime_mono(&ts1);
1428         result = SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, path,
1429                                            filter, subdir_filter, callback,
1430                                            private_data, handle_p);
1431         clock_gettime_mono(&ts2);
1432         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1433
1434         if (timediff > audit_timeout) {
1435                 smb_time_audit_log_fname("notify_watch", timediff, path);
1436         }
1437
1438         return result;
1439 }
1440
1441 static int smb_time_audit_chflags(vfs_handle_struct *handle,
1442                                   const char *path, unsigned int flags)
1443 {
1444         int result;
1445         struct timespec ts1,ts2;
1446         double timediff;
1447
1448         clock_gettime_mono(&ts1);
1449         result = SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
1450         clock_gettime_mono(&ts2);
1451         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1452
1453         if (timediff > audit_timeout) {
1454                 smb_time_audit_log_fname("chflags", timediff, path);
1455         }
1456
1457         return result;
1458 }
1459
1460 static struct file_id smb_time_audit_file_id_create(struct vfs_handle_struct *handle,
1461                                                     const SMB_STRUCT_STAT *sbuf)
1462 {
1463         struct file_id id_zero;
1464         struct file_id result;
1465         struct timespec ts1,ts2;
1466         double timediff;
1467
1468         ZERO_STRUCT(id_zero);
1469
1470         clock_gettime_mono(&ts1);
1471         result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
1472         clock_gettime_mono(&ts2);
1473         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1474
1475         if (timediff > audit_timeout) {
1476                 smb_time_audit_log("file_id_create", timediff);
1477         }
1478
1479         return result;
1480 }
1481
1482 static NTSTATUS smb_time_audit_streaminfo(vfs_handle_struct *handle,
1483                                           struct files_struct *fsp,
1484                                           const char *fname,
1485                                           TALLOC_CTX *mem_ctx,
1486                                           unsigned int *pnum_streams,
1487                                           struct stream_struct **pstreams)
1488 {
1489         NTSTATUS result;
1490         struct timespec ts1,ts2;
1491         double timediff;
1492
1493         clock_gettime_mono(&ts1);
1494         result = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
1495                                          pnum_streams, pstreams);
1496         clock_gettime_mono(&ts2);
1497         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1498
1499         if (timediff > audit_timeout) {
1500                 smb_time_audit_log_fsp("streaminfo", timediff, fsp);
1501         }
1502
1503         return result;
1504 }
1505
1506 static int smb_time_audit_get_real_filename(struct vfs_handle_struct *handle,
1507                                             const char *path,
1508                                             const char *name,
1509                                             TALLOC_CTX *mem_ctx,
1510                                             char **found_name)
1511 {
1512         int result;
1513         struct timespec ts1,ts2;
1514         double timediff;
1515
1516         clock_gettime_mono(&ts1);
1517         result = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx,
1518                                                 found_name);
1519         clock_gettime_mono(&ts2);
1520         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1521
1522         if (timediff > audit_timeout) {
1523                 smb_time_audit_log_fname("get_real_filename", timediff, path);
1524         }
1525
1526         return result;
1527 }
1528
1529 static const char *smb_time_audit_connectpath(vfs_handle_struct *handle,
1530                                               const char *fname)
1531 {
1532         const char *result;
1533         struct timespec ts1,ts2;
1534         double timediff;
1535
1536         clock_gettime_mono(&ts1);
1537         result = SMB_VFS_NEXT_CONNECTPATH(handle, fname);
1538         clock_gettime_mono(&ts2);
1539         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1540
1541         if (timediff > audit_timeout) {
1542                 smb_time_audit_log_fname("connectpath", timediff, fname);
1543         }
1544
1545         return result;
1546 }
1547
1548 static NTSTATUS smb_time_audit_brl_lock_windows(struct vfs_handle_struct *handle,
1549                                                 struct byte_range_lock *br_lck,
1550                                                 struct lock_struct *plock,
1551                                                 bool blocking_lock)
1552 {
1553         NTSTATUS result;
1554         struct timespec ts1,ts2;
1555         double timediff;
1556
1557         clock_gettime_mono(&ts1);
1558         result = SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock,
1559                                                blocking_lock);
1560         clock_gettime_mono(&ts2);
1561         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1562
1563         if (timediff > audit_timeout) {
1564                 smb_time_audit_log_fsp("brl_lock_windows", timediff,
1565                                        brl_fsp(br_lck));
1566         }
1567
1568         return result;
1569 }
1570
1571 static bool smb_time_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
1572                                               struct messaging_context *msg_ctx,
1573                                               struct byte_range_lock *br_lck,
1574                                               const struct lock_struct *plock)
1575 {
1576         bool result;
1577         struct timespec ts1,ts2;
1578         double timediff;
1579
1580         clock_gettime_mono(&ts1);
1581         result = SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, msg_ctx, br_lck,
1582                                                  plock);
1583         clock_gettime_mono(&ts2);
1584         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1585
1586         if (timediff > audit_timeout) {
1587                 smb_time_audit_log_fsp("brl_unlock_windows", timediff,
1588                                        brl_fsp(br_lck));
1589         }
1590
1591         return result;
1592 }
1593
1594 static bool smb_time_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
1595                                               struct byte_range_lock *br_lck,
1596                                               struct lock_struct *plock)
1597 {
1598         bool result;
1599         struct timespec ts1,ts2;
1600         double timediff;
1601
1602         clock_gettime_mono(&ts1);
1603         result = SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock);
1604         clock_gettime_mono(&ts2);
1605         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1606
1607         if (timediff > audit_timeout) {
1608                 smb_time_audit_log_fsp("brl_cancel_windows", timediff,
1609                                        brl_fsp(br_lck));
1610         }
1611
1612         return result;
1613 }
1614
1615 static bool smb_time_audit_strict_lock(struct vfs_handle_struct *handle,
1616                                        struct files_struct *fsp,
1617                                        struct lock_struct *plock)
1618 {
1619         bool result;
1620         struct timespec ts1,ts2;
1621         double timediff;
1622
1623         clock_gettime_mono(&ts1);
1624         result = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
1625         clock_gettime_mono(&ts2);
1626         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1627
1628         if (timediff > audit_timeout) {
1629                 smb_time_audit_log_fsp("strict_lock", timediff, fsp);
1630         }
1631
1632         return result;
1633 }
1634
1635 static void smb_time_audit_strict_unlock(struct vfs_handle_struct *handle,
1636                                          struct files_struct *fsp,
1637                                          struct lock_struct *plock)
1638 {
1639         struct timespec ts1,ts2;
1640         double timediff;
1641
1642         clock_gettime_mono(&ts1);
1643         SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
1644         clock_gettime_mono(&ts2);
1645         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1646
1647         if (timediff > audit_timeout) {
1648                 smb_time_audit_log_fsp("strict_unlock", timediff, fsp);
1649         }
1650 }
1651
1652 static NTSTATUS smb_time_audit_translate_name(struct vfs_handle_struct *handle,
1653                                               const char *name,
1654                                               enum vfs_translate_direction direction,
1655                                               TALLOC_CTX *mem_ctx,
1656                                               char **mapped_name)
1657 {
1658         NTSTATUS result;
1659         struct timespec ts1,ts2;
1660         double timediff;
1661
1662         clock_gettime_mono(&ts1);
1663         result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx,
1664                                              mapped_name);
1665         clock_gettime_mono(&ts2);
1666         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1667
1668         if (timediff > audit_timeout) {
1669                 smb_time_audit_log_fname("translate_name", timediff, name);
1670         }
1671
1672         return result;
1673 }
1674
1675 struct time_audit_cc_state {
1676         struct timespec ts_send;
1677         struct vfs_handle_struct *handle;
1678         off_t copied;
1679 };
1680 static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq);
1681
1682 static struct tevent_req *smb_time_audit_copy_chunk_send(struct vfs_handle_struct *handle,
1683                                                          TALLOC_CTX *mem_ctx,
1684                                                          struct tevent_context *ev,
1685                                                          struct files_struct *src_fsp,
1686                                                          off_t src_off,
1687                                                          struct files_struct *dest_fsp,
1688                                                          off_t dest_off,
1689                                                          off_t num)
1690 {
1691         struct tevent_req *req;
1692         struct tevent_req *subreq;
1693         struct time_audit_cc_state *cc_state;
1694
1695         req = tevent_req_create(mem_ctx, &cc_state, struct time_audit_cc_state);
1696         if (req == NULL) {
1697                 return NULL;
1698         }
1699
1700         cc_state->handle = handle;
1701         clock_gettime_mono(&cc_state->ts_send);
1702         subreq = SMB_VFS_NEXT_COPY_CHUNK_SEND(handle, cc_state, ev,
1703                                               src_fsp, src_off,
1704                                               dest_fsp, dest_off, num);
1705         if (tevent_req_nomem(subreq, req)) {
1706                 return tevent_req_post(req, ev);
1707         }
1708
1709         tevent_req_set_callback(subreq, smb_time_audit_copy_chunk_done, req);
1710         return req;
1711 }
1712
1713 static void smb_time_audit_copy_chunk_done(struct tevent_req *subreq)
1714 {
1715         struct tevent_req *req = tevent_req_callback_data(
1716                 subreq, struct tevent_req);
1717         struct time_audit_cc_state *cc_state
1718                         = tevent_req_data(req, struct time_audit_cc_state);
1719         NTSTATUS status;
1720
1721         status = SMB_VFS_NEXT_COPY_CHUNK_RECV(cc_state->handle,
1722                                               subreq,
1723                                               &cc_state->copied);
1724         TALLOC_FREE(subreq);
1725         if (tevent_req_nterror(req, status)) {
1726                 return;
1727         }
1728         tevent_req_done(req);
1729 }
1730
1731 static NTSTATUS smb_time_audit_copy_chunk_recv(struct vfs_handle_struct *handle,
1732                                                struct tevent_req *req,
1733                                                off_t *copied)
1734 {
1735         struct time_audit_cc_state *cc_state
1736                         = tevent_req_data(req, struct time_audit_cc_state);
1737         struct timespec ts_recv;
1738         double timediff;
1739         NTSTATUS status;
1740
1741         clock_gettime_mono(&ts_recv);
1742         timediff = nsec_time_diff(&ts_recv, &cc_state->ts_send)*1.0e-9;
1743         if (timediff > audit_timeout) {
1744                 smb_time_audit_log("copy_chunk", timediff);
1745         }
1746
1747         *copied = cc_state->copied;
1748         if (tevent_req_is_nterror(req, &status)) {
1749                 tevent_req_received(req);
1750                 return status;
1751         }
1752
1753         tevent_req_received(req);
1754         return NT_STATUS_OK;
1755 }
1756
1757 static NTSTATUS smb_time_audit_get_compression(vfs_handle_struct *handle,
1758                                                TALLOC_CTX *mem_ctx,
1759                                                struct files_struct *fsp,
1760                                                struct smb_filename *smb_fname,
1761                                                uint16_t *_compression_fmt)
1762 {
1763         NTSTATUS result;
1764         struct timespec ts1,ts2;
1765         double timediff;
1766
1767         clock_gettime_mono(&ts1);
1768         result = SMB_VFS_NEXT_GET_COMPRESSION(handle, mem_ctx, fsp, smb_fname,
1769                                               _compression_fmt);
1770         clock_gettime_mono(&ts2);
1771         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1772
1773         if (timediff > audit_timeout) {
1774                 if (fsp !=  NULL) {
1775                         smb_time_audit_log_fsp("get_compression",
1776                                                timediff, fsp);
1777                 } else {
1778                         smb_time_audit_log_smb_fname("get_compression",
1779                                                      timediff, smb_fname);
1780                 }
1781         }
1782
1783         return result;
1784 }
1785
1786 static NTSTATUS smb_time_audit_set_compression(vfs_handle_struct *handle,
1787                                                TALLOC_CTX *mem_ctx,
1788                                                struct files_struct *fsp,
1789                                                uint16_t compression_fmt)
1790 {
1791         NTSTATUS result;
1792         struct timespec ts1,ts2;
1793         double timediff;
1794
1795         clock_gettime_mono(&ts1);
1796         result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
1797                                               compression_fmt);
1798         clock_gettime_mono(&ts2);
1799         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1800
1801         if (timediff > audit_timeout) {
1802                 smb_time_audit_log_fsp("set_compression", timediff, fsp);
1803         }
1804
1805         return result;
1806 }
1807
1808 static NTSTATUS smb_time_audit_readdir_attr(struct vfs_handle_struct *handle,
1809                                             const struct smb_filename *fname,
1810                                             TALLOC_CTX *mem_ctx,
1811                                             struct readdir_attr_data **pattr_data)
1812 {
1813         NTSTATUS status;
1814         struct timespec ts1,ts2;
1815         double timediff;
1816
1817         clock_gettime_mono(&ts1);
1818         status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data);
1819         clock_gettime_mono(&ts2);
1820         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1821
1822         if (timediff > audit_timeout) {
1823                 smb_time_audit_log_smb_fname("readdir_attr", timediff, fname);
1824         }
1825
1826         return status;
1827 }
1828
1829 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
1830                                            files_struct *fsp,
1831                                            uint32 security_info,
1832                                            TALLOC_CTX *mem_ctx,
1833                                            struct security_descriptor **ppdesc)
1834 {
1835         NTSTATUS result;
1836         struct timespec ts1,ts2;
1837         double timediff;
1838
1839         clock_gettime_mono(&ts1);
1840         result = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1841                                           mem_ctx, ppdesc);
1842         clock_gettime_mono(&ts2);
1843         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1844
1845         if (timediff > audit_timeout) {
1846                 smb_time_audit_log_fsp("fget_nt_acl", timediff, fsp);
1847         }
1848
1849         return result;
1850 }
1851
1852 static NTSTATUS smb_time_audit_get_nt_acl(vfs_handle_struct *handle,
1853                                           const char *name,
1854                                           uint32 security_info,
1855                                           TALLOC_CTX *mem_ctx,
1856                                           struct security_descriptor **ppdesc)
1857 {
1858         NTSTATUS result;
1859         struct timespec ts1,ts2;
1860         double timediff;
1861
1862         clock_gettime_mono(&ts1);
1863         result = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
1864                                          mem_ctx, ppdesc);
1865         clock_gettime_mono(&ts2);
1866         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1867
1868         if (timediff > audit_timeout) {
1869                 smb_time_audit_log_fname("get_nt_acl", timediff, name);
1870         }
1871
1872         return result;
1873 }
1874
1875 static NTSTATUS smb_time_audit_fset_nt_acl(vfs_handle_struct *handle,
1876                                            files_struct *fsp,
1877                                            uint32 security_info_sent,
1878                                            const struct security_descriptor *psd)
1879 {
1880         NTSTATUS result;
1881         struct timespec ts1,ts2;
1882         double timediff;
1883
1884         clock_gettime_mono(&ts1);
1885         result = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent,
1886                                           psd);
1887         clock_gettime_mono(&ts2);
1888         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1889
1890         if (timediff > audit_timeout) {
1891                 smb_time_audit_log_fsp("fset_nt_acl", timediff, fsp);
1892         }
1893
1894         return result;
1895 }
1896
1897 static int smb_time_audit_chmod_acl(vfs_handle_struct *handle,
1898                                     const char *path, mode_t mode)
1899 {
1900         int result;
1901         struct timespec ts1,ts2;
1902         double timediff;
1903
1904         clock_gettime_mono(&ts1);
1905         result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
1906         clock_gettime_mono(&ts2);
1907         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1908
1909         if (timediff > audit_timeout) {
1910                 smb_time_audit_log_fname("chmod_acl", timediff, path);
1911         }
1912
1913         return result;
1914 }
1915
1916 static int smb_time_audit_fchmod_acl(vfs_handle_struct *handle,
1917                                      files_struct *fsp, mode_t mode)
1918 {
1919         int result;
1920         struct timespec ts1,ts2;
1921         double timediff;
1922
1923         clock_gettime_mono(&ts1);
1924         result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
1925         clock_gettime_mono(&ts2);
1926         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1927
1928         if (timediff > audit_timeout) {
1929                 smb_time_audit_log_fsp("fchmod_acl", timediff, fsp);
1930         }
1931
1932         return result;
1933 }
1934
1935 static SMB_ACL_T smb_time_audit_sys_acl_get_file(vfs_handle_struct *handle,
1936                                                  const char *path_p,
1937                                                  SMB_ACL_TYPE_T type,
1938                                                  TALLOC_CTX *mem_ctx)
1939 {
1940         SMB_ACL_T result;
1941         struct timespec ts1,ts2;
1942         double timediff;
1943
1944         clock_gettime_mono(&ts1);
1945         result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type, mem_ctx);
1946         clock_gettime_mono(&ts2);
1947         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1948
1949         if (timediff > audit_timeout) {
1950                 smb_time_audit_log_fname("sys_acl_get_file", timediff, path_p);
1951         }
1952
1953         return result;
1954 }
1955
1956 static SMB_ACL_T smb_time_audit_sys_acl_get_fd(vfs_handle_struct *handle,
1957                                                files_struct *fsp,
1958                                                TALLOC_CTX *mem_ctx)
1959 {
1960         SMB_ACL_T result;
1961         struct timespec ts1,ts2;
1962         double timediff;
1963
1964         clock_gettime_mono(&ts1);
1965         result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
1966         clock_gettime_mono(&ts2);
1967         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1968
1969         if (timediff > audit_timeout) {
1970                 smb_time_audit_log_fsp("sys_acl_get_fd", timediff, fsp);
1971         }
1972
1973         return result;
1974 }
1975
1976
1977 static int smb_time_audit_sys_acl_blob_get_file(vfs_handle_struct *handle,
1978                                                 const char *path_p,
1979                                                 TALLOC_CTX *mem_ctx, 
1980                                                 char **blob_description,
1981                                                 DATA_BLOB *blob)
1982 {
1983         int result;
1984         struct timespec ts1,ts2;
1985         double timediff;
1986
1987         clock_gettime_mono(&ts1);
1988         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle, path_p, mem_ctx, blob_description, blob);
1989         clock_gettime_mono(&ts2);
1990         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1991
1992         if (timediff > audit_timeout) {
1993                 smb_time_audit_log("sys_acl_blob_get_file", timediff);
1994         }
1995
1996         return result;
1997 }
1998
1999 static int smb_time_audit_sys_acl_blob_get_fd(vfs_handle_struct *handle,
2000                                               files_struct *fsp,
2001                                               TALLOC_CTX *mem_ctx, 
2002                                               char **blob_description,
2003                                               DATA_BLOB *blob)
2004 {
2005         int result;
2006         struct timespec ts1,ts2;
2007         double timediff;
2008
2009         clock_gettime_mono(&ts1);
2010         result = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx, blob_description, blob);
2011         clock_gettime_mono(&ts2);
2012         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2013
2014         if (timediff > audit_timeout) {
2015                 smb_time_audit_log("sys_acl_blob_get_fd", timediff);
2016         }
2017
2018         return result;
2019 }
2020
2021 static int smb_time_audit_sys_acl_set_file(vfs_handle_struct *handle,
2022                                            const char *name,
2023                                            SMB_ACL_TYPE_T acltype,
2024                                            SMB_ACL_T theacl)
2025 {
2026         int result;
2027         struct timespec ts1,ts2;
2028         double timediff;
2029
2030         clock_gettime_mono(&ts1);
2031         result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype,
2032                                                theacl);
2033         clock_gettime_mono(&ts2);
2034         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2035
2036         if (timediff > audit_timeout) {
2037                 smb_time_audit_log_fname("sys_acl_set_file", timediff, name);
2038         }
2039
2040         return result;
2041 }
2042
2043 static int smb_time_audit_sys_acl_set_fd(vfs_handle_struct *handle,
2044                                          files_struct *fsp,
2045                                          SMB_ACL_T theacl)
2046 {
2047         int result;
2048         struct timespec ts1,ts2;
2049         double timediff;
2050
2051         clock_gettime_mono(&ts1);
2052         result = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
2053         clock_gettime_mono(&ts2);
2054         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2055
2056         if (timediff > audit_timeout) {
2057                 smb_time_audit_log_fsp("sys_acl_set_fd", timediff, fsp);
2058         }
2059
2060         return result;
2061 }
2062
2063 static int smb_time_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
2064                                                   const char *path)
2065 {
2066         int result;
2067         struct timespec ts1,ts2;
2068         double timediff;
2069
2070         clock_gettime_mono(&ts1);
2071         result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path);
2072         clock_gettime_mono(&ts2);
2073         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2074
2075         if (timediff > audit_timeout) {
2076                 smb_time_audit_log_fname("sys_acl_delete_def_file", timediff, path);
2077         }
2078
2079         return result;
2080 }
2081
2082 static ssize_t smb_time_audit_getxattr(struct vfs_handle_struct *handle,
2083                                        const char *path, const char *name,
2084                                        void *value, size_t size)
2085 {
2086         ssize_t result;
2087         struct timespec ts1,ts2;
2088         double timediff;
2089
2090         clock_gettime_mono(&ts1);
2091         result = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, size);
2092         clock_gettime_mono(&ts2);
2093         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2094
2095         if (timediff > audit_timeout) {
2096                 smb_time_audit_log_fname("getxattr", timediff, path);
2097         }
2098
2099         return result;
2100 }
2101
2102 static ssize_t smb_time_audit_fgetxattr(struct vfs_handle_struct *handle,
2103                                         struct files_struct *fsp,
2104                                         const char *name, void *value,
2105                                         size_t size)
2106 {
2107         ssize_t result;
2108         struct timespec ts1,ts2;
2109         double timediff;
2110
2111         clock_gettime_mono(&ts1);
2112         result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
2113         clock_gettime_mono(&ts2);
2114         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2115
2116         if (timediff > audit_timeout) {
2117                 smb_time_audit_log_fsp("fgetxattr", timediff, fsp);
2118         }
2119
2120         return result;
2121 }
2122
2123 static ssize_t smb_time_audit_listxattr(struct vfs_handle_struct *handle,
2124                                         const char *path, char *list,
2125                                         size_t size)
2126 {
2127         ssize_t result;
2128         struct timespec ts1,ts2;
2129         double timediff;
2130
2131         clock_gettime_mono(&ts1);
2132         result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size);
2133         clock_gettime_mono(&ts2);
2134         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2135
2136         if (timediff > audit_timeout) {
2137                 smb_time_audit_log_fname("listxattr", timediff, path);
2138         }
2139
2140         return result;
2141 }
2142
2143 static ssize_t smb_time_audit_flistxattr(struct vfs_handle_struct *handle,
2144                                          struct files_struct *fsp, char *list,
2145                                          size_t size)
2146 {
2147         ssize_t result;
2148         struct timespec ts1,ts2;
2149         double timediff;
2150
2151         clock_gettime_mono(&ts1);
2152         result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
2153         clock_gettime_mono(&ts2);
2154         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2155
2156         if (timediff > audit_timeout) {
2157                 smb_time_audit_log_fsp("flistxattr", timediff, fsp);
2158         }
2159
2160         return result;
2161 }
2162
2163 static int smb_time_audit_removexattr(struct vfs_handle_struct *handle,
2164                                       const char *path, const char *name)
2165 {
2166         int result;
2167         struct timespec ts1,ts2;
2168         double timediff;
2169
2170         clock_gettime_mono(&ts1);
2171         result = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
2172         clock_gettime_mono(&ts2);
2173         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2174
2175         if (timediff > audit_timeout) {
2176                 smb_time_audit_log_fname("removexattr", timediff, path);
2177         }
2178
2179         return result;
2180 }
2181
2182 static int smb_time_audit_fremovexattr(struct vfs_handle_struct *handle,
2183                                        struct files_struct *fsp,
2184                                        const char *name)
2185 {
2186         int result;
2187         struct timespec ts1,ts2;
2188         double timediff;
2189
2190         clock_gettime_mono(&ts1);
2191         result = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
2192         clock_gettime_mono(&ts2);
2193         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2194
2195         if (timediff > audit_timeout) {
2196                 smb_time_audit_log_fsp("fremovexattr", timediff, fsp);
2197         }
2198
2199         return result;
2200 }
2201
2202 static int smb_time_audit_setxattr(struct vfs_handle_struct *handle,
2203                                    const char *path, const char *name,
2204                                    const void *value, size_t size,
2205                                    int flags)
2206 {
2207         int result;
2208         struct timespec ts1,ts2;
2209         double timediff;
2210
2211         clock_gettime_mono(&ts1);
2212         result = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, size,
2213                                        flags);
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_fname("setxattr", timediff, path);
2219         }
2220
2221         return result;
2222 }
2223
2224 static int smb_time_audit_fsetxattr(struct vfs_handle_struct *handle,
2225                                     struct files_struct *fsp, const char *name,
2226                                     const void *value, size_t size, int flags)
2227 {
2228         int result;
2229         struct timespec ts1,ts2;
2230         double timediff;
2231
2232         clock_gettime_mono(&ts1);
2233         result = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags);
2234         clock_gettime_mono(&ts2);
2235         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2236
2237         if (timediff > audit_timeout) {
2238                 smb_time_audit_log_fsp("fsetxattr", timediff, fsp);
2239         }
2240
2241         return result;
2242 }
2243
2244 static bool smb_time_audit_aio_force(struct vfs_handle_struct *handle,
2245                                      struct files_struct *fsp)
2246 {
2247         bool result;
2248         struct timespec ts1,ts2;
2249         double timediff;
2250
2251         clock_gettime_mono(&ts1);
2252         result = SMB_VFS_NEXT_AIO_FORCE(handle, fsp);
2253         clock_gettime_mono(&ts2);
2254         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2255
2256         if (timediff > audit_timeout) {
2257                 smb_time_audit_log_fsp("aio_force", timediff, fsp);
2258         }
2259
2260         return result;
2261 }
2262
2263 static bool smb_time_audit_is_offline(struct vfs_handle_struct *handle,
2264                                       const struct smb_filename *fname,
2265                                       SMB_STRUCT_STAT *sbuf)
2266 {
2267         bool result;
2268         struct timespec ts1,ts2;
2269         double timediff;
2270
2271         clock_gettime_mono(&ts1);
2272         result = SMB_VFS_NEXT_IS_OFFLINE(handle, fname, sbuf);
2273         clock_gettime_mono(&ts2);
2274         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2275
2276         if (timediff > audit_timeout) {
2277                 smb_time_audit_log_smb_fname("is_offline", timediff, fname);
2278         }
2279
2280         return result;
2281 }
2282
2283 static int smb_time_audit_set_offline(struct vfs_handle_struct *handle,
2284                                       const struct smb_filename *fname)
2285 {
2286         int result;
2287         struct timespec ts1,ts2;
2288         double timediff;
2289
2290         clock_gettime_mono(&ts1);
2291         result = SMB_VFS_NEXT_SET_OFFLINE(handle, fname);
2292         clock_gettime_mono(&ts2);
2293         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2294
2295         if (timediff > audit_timeout) {
2296                 smb_time_audit_log_smb_fname("set_offline", timediff, fname);
2297         }
2298
2299         return result;
2300 }
2301
2302 static NTSTATUS smb_time_audit_durable_cookie(struct vfs_handle_struct *handle,
2303                                               struct files_struct *fsp,
2304                                               TALLOC_CTX *mem_ctx,
2305                                               DATA_BLOB *cookie)
2306 {
2307         NTSTATUS result;
2308         struct timespec ts1,ts2;
2309         double timediff;
2310
2311         clock_gettime_mono(&ts1);
2312         result = SMB_VFS_NEXT_DURABLE_COOKIE(handle, fsp, mem_ctx, cookie);
2313         clock_gettime_mono(&ts2);
2314         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2315
2316         if (timediff > audit_timeout) {
2317                 smb_time_audit_log_fsp("durable_cookie", timediff, fsp);
2318         }
2319
2320         return result;
2321 }
2322
2323 static NTSTATUS smb_time_audit_durable_disconnect(struct vfs_handle_struct *handle,
2324                                                   struct files_struct *fsp,
2325                                                   const DATA_BLOB old_cookie,
2326                                                   TALLOC_CTX *mem_ctx,
2327                                                   DATA_BLOB *new_cookie)
2328 {
2329         NTSTATUS result;
2330         struct timespec ts1,ts2;
2331         double timediff;
2332
2333         clock_gettime_mono(&ts1);
2334         result = SMB_VFS_NEXT_DURABLE_DISCONNECT(handle, fsp, old_cookie,
2335                                                  mem_ctx, new_cookie);
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_fsp("durable_disconnect", timediff, fsp);
2341         }
2342
2343         return result;
2344 }
2345
2346 static NTSTATUS smb_time_audit_durable_reconnect(struct vfs_handle_struct *handle,
2347                                                  struct smb_request *smb1req,
2348                                                  struct smbXsrv_open *op,
2349                                                  const DATA_BLOB old_cookie,
2350                                                  TALLOC_CTX *mem_ctx,
2351                                                  struct files_struct **fsp,
2352                                                  DATA_BLOB *new_cookie)
2353 {
2354         NTSTATUS result;
2355         struct timespec ts1,ts2;
2356         double timediff;
2357
2358         clock_gettime_mono(&ts1);
2359         result = SMB_VFS_NEXT_DURABLE_RECONNECT(handle, smb1req, op, old_cookie,
2360                                                 mem_ctx, fsp, new_cookie);
2361         clock_gettime_mono(&ts2);
2362         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
2363
2364         if (timediff > audit_timeout) {
2365                 smb_time_audit_log("durable_reconnect", timediff);
2366         }
2367
2368         return result;
2369 }
2370
2371 /* VFS operations */
2372
2373 static struct vfs_fn_pointers vfs_time_audit_fns = {
2374         .connect_fn = smb_time_audit_connect,
2375         .disconnect_fn = smb_time_audit_disconnect,
2376         .disk_free_fn = smb_time_audit_disk_free,
2377         .get_quota_fn = smb_time_audit_get_quota,
2378         .set_quota_fn = smb_time_audit_set_quota,
2379         .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
2380         .statvfs_fn = smb_time_audit_statvfs,
2381         .fs_capabilities_fn = smb_time_audit_fs_capabilities,
2382         .opendir_fn = smb_time_audit_opendir,
2383         .fdopendir_fn = smb_time_audit_fdopendir,
2384         .readdir_fn = smb_time_audit_readdir,
2385         .seekdir_fn = smb_time_audit_seekdir,
2386         .telldir_fn = smb_time_audit_telldir,
2387         .rewind_dir_fn = smb_time_audit_rewinddir,
2388         .mkdir_fn = smb_time_audit_mkdir,
2389         .rmdir_fn = smb_time_audit_rmdir,
2390         .closedir_fn = smb_time_audit_closedir,
2391         .init_search_op_fn = smb_time_audit_init_search_op,
2392         .open_fn = smb_time_audit_open,
2393         .create_file_fn = smb_time_audit_create_file,
2394         .close_fn = smb_time_audit_close,
2395         .read_fn = smb_time_audit_read,
2396         .pread_fn = smb_time_audit_pread,
2397         .pread_send_fn = smb_time_audit_pread_send,
2398         .pread_recv_fn = smb_time_audit_pread_recv,
2399         .write_fn = smb_time_audit_write,
2400         .pwrite_fn = smb_time_audit_pwrite,
2401         .pwrite_send_fn = smb_time_audit_pwrite_send,
2402         .pwrite_recv_fn = smb_time_audit_pwrite_recv,
2403         .lseek_fn = smb_time_audit_lseek,
2404         .sendfile_fn = smb_time_audit_sendfile,
2405         .recvfile_fn = smb_time_audit_recvfile,
2406         .rename_fn = smb_time_audit_rename,
2407         .fsync_fn = smb_time_audit_fsync,
2408         .fsync_send_fn = smb_time_audit_fsync_send,
2409         .fsync_recv_fn = smb_time_audit_fsync_recv,
2410         .stat_fn = smb_time_audit_stat,
2411         .fstat_fn = smb_time_audit_fstat,
2412         .lstat_fn = smb_time_audit_lstat,
2413         .get_alloc_size_fn = smb_time_audit_get_alloc_size,
2414         .unlink_fn = smb_time_audit_unlink,
2415         .chmod_fn = smb_time_audit_chmod,
2416         .fchmod_fn = smb_time_audit_fchmod,
2417         .chown_fn = smb_time_audit_chown,
2418         .fchown_fn = smb_time_audit_fchown,
2419         .lchown_fn = smb_time_audit_lchown,
2420         .chdir_fn = smb_time_audit_chdir,
2421         .getwd_fn = smb_time_audit_getwd,
2422         .ntimes_fn = smb_time_audit_ntimes,
2423         .ftruncate_fn = smb_time_audit_ftruncate,
2424         .fallocate_fn = smb_time_audit_fallocate,
2425         .lock_fn = smb_time_audit_lock,
2426         .kernel_flock_fn = smb_time_audit_kernel_flock,
2427         .linux_setlease_fn = smb_time_audit_linux_setlease,
2428         .getlock_fn = smb_time_audit_getlock,
2429         .symlink_fn = smb_time_audit_symlink,
2430         .readlink_fn = smb_time_audit_readlink,
2431         .link_fn = smb_time_audit_link,
2432         .mknod_fn = smb_time_audit_mknod,
2433         .realpath_fn = smb_time_audit_realpath,
2434         .notify_watch_fn = smb_time_audit_notify_watch,
2435         .chflags_fn = smb_time_audit_chflags,
2436         .file_id_create_fn = smb_time_audit_file_id_create,
2437         .streaminfo_fn = smb_time_audit_streaminfo,
2438         .get_real_filename_fn = smb_time_audit_get_real_filename,
2439         .connectpath_fn = smb_time_audit_connectpath,
2440         .brl_lock_windows_fn = smb_time_audit_brl_lock_windows,
2441         .brl_unlock_windows_fn = smb_time_audit_brl_unlock_windows,
2442         .brl_cancel_windows_fn = smb_time_audit_brl_cancel_windows,
2443         .strict_lock_fn = smb_time_audit_strict_lock,
2444         .strict_unlock_fn = smb_time_audit_strict_unlock,
2445         .translate_name_fn = smb_time_audit_translate_name,
2446         .copy_chunk_send_fn = smb_time_audit_copy_chunk_send,
2447         .copy_chunk_recv_fn = smb_time_audit_copy_chunk_recv,
2448         .get_compression_fn = smb_time_audit_get_compression,
2449         .set_compression_fn = smb_time_audit_set_compression,
2450         .readdir_attr_fn = smb_time_audit_readdir_attr,
2451         .fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
2452         .get_nt_acl_fn = smb_time_audit_get_nt_acl,
2453         .fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
2454         .chmod_acl_fn = smb_time_audit_chmod_acl,
2455         .fchmod_acl_fn = smb_time_audit_fchmod_acl,
2456         .sys_acl_get_file_fn = smb_time_audit_sys_acl_get_file,
2457         .sys_acl_get_fd_fn = smb_time_audit_sys_acl_get_fd,
2458         .sys_acl_blob_get_file_fn = smb_time_audit_sys_acl_blob_get_file,
2459         .sys_acl_blob_get_fd_fn = smb_time_audit_sys_acl_blob_get_fd,
2460         .sys_acl_set_file_fn = smb_time_audit_sys_acl_set_file,
2461         .sys_acl_set_fd_fn = smb_time_audit_sys_acl_set_fd,
2462         .sys_acl_delete_def_file_fn = smb_time_audit_sys_acl_delete_def_file,
2463         .getxattr_fn = smb_time_audit_getxattr,
2464         .fgetxattr_fn = smb_time_audit_fgetxattr,
2465         .listxattr_fn = smb_time_audit_listxattr,
2466         .flistxattr_fn = smb_time_audit_flistxattr,
2467         .removexattr_fn = smb_time_audit_removexattr,
2468         .fremovexattr_fn = smb_time_audit_fremovexattr,
2469         .setxattr_fn = smb_time_audit_setxattr,
2470         .fsetxattr_fn = smb_time_audit_fsetxattr,
2471         .aio_force_fn = smb_time_audit_aio_force,
2472         .is_offline_fn = smb_time_audit_is_offline,
2473         .set_offline_fn = smb_time_audit_set_offline,
2474         .durable_cookie_fn = smb_time_audit_durable_cookie,
2475         .durable_disconnect_fn = smb_time_audit_durable_disconnect,
2476         .durable_reconnect_fn = smb_time_audit_durable_reconnect,
2477 };
2478
2479
2480 NTSTATUS vfs_time_audit_init(void);
2481 NTSTATUS vfs_time_audit_init(void)
2482 {
2483         audit_timeout = (double)lp_parm_int(-1, "time_audit", "timeout",
2484                                             10000) / 1000.0;
2485         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "time_audit",
2486                                 &vfs_time_audit_fns);
2487 }