s3-vfs: rename open function to open_fn.
[amitay/samba.git] / source3 / modules / vfs_smb_traffic_analyzer.c
index 5af230a9c20461ced440dd236df6aa32c0318304..e8aa385d69cf5c0ec44284194bce742cad67d89f 100644 (file)
@@ -2,7 +2,7 @@
  * traffic-analyzer VFS module. Measure the smb traffic users create
  * on the net.
  *
- * Copyright (C) Holger Hetterich, 2008
+ * Copyright (C) Holger Hetterich, 2008-2010
  * Copyright (C) Jeremy Allison, 2008
  *
  * This program is free software; you can redistribute it and/or modify
  */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "../smbd/globals.h"
+#include "../lib/crypto/crypto.h"
+#include "vfs_smb_traffic_analyzer.h"
+#include "../libcli/security/security.h"
+#include "secrets.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "auth.h"
 
 /* abstraction for the send_over_network function */
-
 enum sock_type {INTERNET_SOCKET = 0, UNIX_DOMAIN_SOCKET};
 
 #define LOCAL_PATHNAME "/var/tmp/stadsocket"
 
-/* VFS Functions identifier table. In protocol version 2, every vfs     */
-/* function is given a unique id.                                       */
-enum vfs_id {
-       /* care for the order here, required for compatibility  */
-       /* with protocol version 1.                             */
-        vfs_id_read,
-        vfs_id_pread,
-        vfs_id_write,
-        vfs_id_pwrite,
-       /* end of protocol version 1 identifiers.               */
-       vfs_id_mkdir,
-       vfs_id_rmdir,
-       vfs_id_rename,
-       vfs_id_chdir
-};
-
-/* Specific data sets for the VFS functions.                           */
-
-typedef struct mkdir_data {
-       const char *path;
-       mode_t mode;
-       int result;
-} t_mkdir;
-
-typedef struct rmdir_data {
-       const char *path;
-       int result;
-} t_rmdir;
-
-typedef struct rename_data {
-       const char *src;
-       const char *dst;
-       int result;
-} t_rename;
-
-typedef struct chdir_data {
-       const char *path;
-       int result;
-} t_chdir;
-
-/* rw_data used for read/write/pread/pwrite                            */
-struct rw_data {
-       char *filename;
-       size_t len;
-};
-
-
 static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
 
 static enum sock_type smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
@@ -91,7 +51,6 @@ static enum sock_type smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
 
 
 /* Connect to an internet socket */
-
 static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle,
                                        const char *name, uint16_t port)
 {
@@ -155,7 +114,6 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle,
 }
 
 /* Connect to a unix domain socket */
-
 static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle,
                                                const char *name)
 {
@@ -187,8 +145,7 @@ static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle,
        return sock;
 }
 
-/* Private data allowing shared connection sockets.    */
-
+/* Private data allowing shared connection sockets. */
 struct refcounted_sock {
        struct refcounted_sock *next, *prev;
        char *name;
@@ -198,30 +155,194 @@ struct refcounted_sock {
 };
 
 
-/* The marshaller for the protocol version 2.          */
-static char *smb_traffic_analyzer_create_string( struct tm *tm, \
-       int seconds, vfs_handle_struct *handle, \
-       char *username, int count, ... )
+/**
+ * Encryption of a data block with AES
+ * TALLOC_CTX *ctx     Talloc context to work on
+ * const char *akey    128bit key for the encryption
+ * const char *str     Data buffer to encrypt, \0 terminated
+ * int *len            Will be set to the length of the
+ *                     resulting data block
+ * The caller has to take care for the memory
+ * allocated on the context.
+ */
+static char *smb_traffic_analyzer_encrypt( TALLOC_CTX *ctx,
+       const char *akey, const char *str, size_t *len)
+{
+       int s1,s2,h,d;
+       AES_KEY key;
+       unsigned char filler[17]= "................";
+       char *output;
+       unsigned char crypted[18];
+       if (akey == NULL) return NULL;
+       samba_AES_set_encrypt_key((unsigned char *) akey, 128, &key);
+       s1 = strlen(str) / 16;
+       s2 = strlen(str) % 16;
+       for (h = 0; h < s2; h++) *(filler+h)=*(str+(s1*16)+h);
+       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created %s"
+               " as filling block.\n", filler));
+       output = talloc_array(ctx, char, (s1*16)+17 );
+       d=0;
+       for (h = 0; h < s1; h++) {
+               samba_AES_encrypt((unsigned char *) str+(16*h), crypted, &key);
+               for (d = 0; d<16; d++) output[d+(16*h)]=crypted[d];
+       }
+       samba_AES_encrypt( (unsigned char *) str+(16*h), filler, &key );
+       for (d = 0;d < 16; d++) output[d+(16*h)]=*(filler+d);
+       *len = (s1*16)+16;
+       return output;  
+}
+
+/**
+ * Create a v2 header.
+ * TALLLOC_CTX *ctx            Talloc context to work on
+ * const char *state_flags     State flag string
+ * int len                     length of the data block
+ */
+static char *smb_traffic_analyzer_create_header( TALLOC_CTX *ctx,
+       const char *state_flags, size_t data_len)
+{
+       char *header = talloc_asprintf( ctx, "V2.%s%017u",
+                                       state_flags, (unsigned int) data_len);
+       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created Header:\n"));
+       dump_data(10, (uint8_t *)header, strlen(header));
+       return header;
+}
+
+
+/**
+ * Actually send header and data over the network
+ * char *header        Header data
+ * char *data          Data Block
+ * int dlength         Length of data block
+ * int socket
+ */
+static void smb_traffic_analyzer_write_data( char *header, char *data,
+                       int dlength, int _socket)
+{
+               int len = strlen(header);
+               if (write_data( _socket, header, len) != len) {
+                       DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
+                                               "error sending the header"
+                                               " over the socket!\n"));
+                }
+               DEBUG(10,("smb_traffic_analyzer_write_data: sending data:\n"));
+               dump_data( 10, (uint8_t *)data, dlength);
+
+                if (write_data( _socket, data, dlength) != dlength) {
+                        DEBUG(1, ("smb_traffic_analyzer_write_data: "
+                                "error sending crypted data to socket!\n"));
+                }
+}
+
+
+/*
+ * Anonymize a string if required.
+ * TALLOC_CTX *ctx                     The talloc context to work on
+ * const char *str                     The string to anonymize
+ * vfs_handle_struct *handle           The handle struct to work on
+ *
+ * Returns a newly allocated string, either the anonymized one,
+ * or a copy of const char *str. The caller has to take care for
+ * freeing the allocated memory.
+ */
+static char *smb_traffic_analyzer_anonymize( TALLOC_CTX *ctx,
+                                       const char *str,
+                                       vfs_handle_struct *handle )
+{
+       const char *total_anonymization;
+       const char *anon_prefix;
+       char *output;
+       total_anonymization=lp_parm_const_string(SNUM(handle->conn),
+                                       "smb_traffic_analyzer",
+                                       "total_anonymization", NULL);
+
+       anon_prefix=lp_parm_const_string(SNUM(handle->conn),
+                                       "smb_traffic_analyzer",
+                                       "anonymize_prefix", NULL );
+       if (anon_prefix != NULL) {
+               if (total_anonymization != NULL) {
+                       output = talloc_asprintf(ctx, "%s",
+                                       anon_prefix);
+               } else {
+               output = talloc_asprintf(ctx, "%s%i", anon_prefix,
+                                               str_checksum(str));
+               }
+       } else {
+               output = talloc_asprintf(ctx, "%s", str);
+       }
+
+       return output;
+}
+
+
+/**
+ * The marshalling function for protocol v2.
+ * TALLOC_CTX *ctx             Talloc context to work on
+ * struct tm *tm               tm struct for the timestamp
+ * int seconds                 milliseconds of the timestamp
+ * vfs_handle_struct *handle   vfs_handle_struct
+ * char *username              Name of the user
+ * int vfs_operation           VFS operation identifier
+ * int count                   Number of the common data blocks
+ * [...] variable args         data blocks taken from the individual
+ *                             VFS data structures
+ *
+ * Returns the complete data block to send. The caller has to
+ * take care for freeing the allocated buffer.
+ */
+static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
+       struct tm *tm, int seconds, vfs_handle_struct *handle, \
+       char *username, int vfs_operation, int count, ... )
 {
        
        va_list ap;
        char *arg = NULL;
-       char *str = NULL;
        int len;
-       char *header = NULL;
-       char *buf = NULL;
+       char *common_data_count_str = NULL;
        char *timestr = NULL;
-
-       /* first create the data that is transfered with any VFS op     */
-       len = strlen( username );
-       buf = talloc_asprintf(talloc_tos(),"%04u%s", len, username);
-       len = strlen( handle->conn->connectpath );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, \
-               handle->conn->connectpath );
-       len = strlen( pdb_get_domain(handle->conn->server_info->sam_account) );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, \
-               pdb_get_domain(handle->conn->server_info->sam_account) );
-       timestr = talloc_asprintf(talloc_tos(), \
+       char *sidstr = NULL;
+       char *usersid = NULL;
+       char *buf = NULL;
+       char *vfs_operation_str = NULL;
+       const char *service_name = lp_const_servicename(handle->conn->params->service);
+
+       /*
+        * first create the data that is transfered with any VFS op
+        * These are, in the following order:
+        *(0) number of data to come [6 in v2.0]
+        * 1.vfs_operation identifier
+        * 2.username
+        * 3.user-SID
+        * 4.affected share
+        * 5.domain
+        * 6.timestamp
+        * 7.IP Addresss of client
+        */
+
+       /*
+        * number of common data blocks to come,
+        * this is a #define in vfs_smb_traffic_anaylzer.h,
+        * it's length is known at compile time
+        */
+       common_data_count_str = talloc_strdup( ctx, SMBTA_COMMON_DATA_COUNT);
+       /* vfs operation identifier */
+       vfs_operation_str = talloc_asprintf( common_data_count_str, "%i",
+                                                       vfs_operation);
+       /*
+        * Handle anonymization. In protocol v2, we have to anonymize
+        * both the SID and the username. The name is already
+        * anonymized if needed, by the calling function.
+        */
+       usersid = dom_sid_string( common_data_count_str,
+               &handle->conn->session_info->security_token->sids[0]);
+
+       sidstr = smb_traffic_analyzer_anonymize(
+               common_data_count_str,
+               usersid,
+               handle);
+       
+       /* time stamp */
+       timestr = talloc_asprintf( common_data_count_str, \
                "%04d-%02d-%02d %02d:%02d:%02d.%03d", \
                tm->tm_year+1900, \
                tm->tm_mon+1, \
@@ -231,25 +352,43 @@ static char *smb_traffic_analyzer_create_string( struct tm *tm, \
                tm->tm_sec, \
                (int)seconds);
        len = strlen( timestr );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, timestr);
-       
+       /* create the string of common data */
+       buf = talloc_asprintf(ctx,
+               "%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s",
+               common_data_count_str,
+               (unsigned int) strlen(vfs_operation_str),
+               vfs_operation_str,
+               (unsigned int) strlen(username),
+               username,
+               (unsigned int) strlen(sidstr),
+               sidstr,
+               (unsigned int) strlen(service_name),
+               service_name,
+               (unsigned int)
+               strlen(handle->conn->session_info->info3->base.domain.string),
+               handle->conn->session_info->info3->base.domain.string,
+               (unsigned int) strlen(timestr),
+               timestr,
+               (unsigned int) strlen(handle->conn->sconn->client_id.addr),
+               handle->conn->sconn->client_id.addr);
+
+       talloc_free(common_data_count_str);
+
+       /* data blocks depending on the VFS function */ 
        va_start( ap, count );
        while ( count-- ) {
                arg = va_arg( ap, char * );
-               /* protocol v2 sends a four byte string */
-               /* as a header to each block, including */
-               /* the numbers of bytes to come in the  */
-               /* next string.                         */
+               /*
+                *  protocol v2 sends a four byte string
+                * as a header to each block, including
+                * the numbers of bytes to come in the
+                * next string.
+                */
                len = strlen( arg );
                buf = talloc_asprintf_append( buf, "%04u%s", len, arg);
        }
        va_end( ap );
-
-       /* now create the protocol v2 header.   */
-       len = strlen( buf );
-       str = talloc_asprintf_append( str, "V2,%017u%s", len, buf);
-       DEBUG(10, ("smb_traffic_analyzer_create_string: %s\n",str));
-       return str;
+       return buf;
 }
 
 static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
@@ -263,11 +402,20 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
        int seconds;
        char *str = NULL;
        char *username = NULL;
-       const char *anon_prefix = NULL;
-       const char *total_anonymization = NULL;
+       char *header = NULL;
        const char *protocol_version = NULL;
        bool Write = false;
        size_t len;
+       size_t size;
+       char *akey, *output;
+
+       /*
+        * The state flags are part of the header
+        * and are descripted in the protocol description
+        * in vfs_smb_traffic_analyzer.h. They begin at byte
+        * 03 of the header.
+        */
+       char state_flags[9] = "000000\0";
 
        SMB_VFS_HANDLE_GET_DATA(handle, rf_sock, struct refcounted_sock, return);
 
@@ -278,53 +426,41 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
        }
 
        GetTimeOfDay(&tv);
-       tv_sec = convert_timespec_to_time_t(convert_timeval_to_timespec(tv));
+       tv_sec = tv.tv_sec;
        tm = localtime(&tv_sec);
        if (!tm) {
                return;
        }
        seconds=(float) (tv.tv_usec / 1000);
 
-       /* check if anonymization is required */
-
-       total_anonymization=lp_parm_const_string(SNUM(handle->conn),"smb_traffic_analyzer",
-                                       "total_anonymization", NULL);
-
-       anon_prefix=lp_parm_const_string(SNUM(handle->conn),"smb_traffic_analyzer",\
-                                       "anonymize_prefix", NULL );
-       if (anon_prefix!=NULL) {
-               if (total_anonymization!=NULL) {
-                       username = talloc_asprintf(talloc_tos(),
-                               "%s",
-                               anon_prefix);
-               } else {
-                       username = talloc_asprintf(talloc_tos(),
-                               "%s%i",
-                               anon_prefix,
-                               str_checksum(
-                                       handle->conn->server_info->sanitized_username ) ); 
-               }
-
-       } else {
-               username = handle->conn->server_info->sanitized_username;
-       }
+       /*
+        * Check if anonymization is required, and if yes do this only for
+        * the username here, needed vor protocol version 1. In v2 we
+        * additionally anonymize the SID, which is done in it's marshalling
+        * function.
+        */
+       username = smb_traffic_analyzer_anonymize( talloc_tos(),
+                       handle->conn->session_info->sanitized_username,
+                       handle);
 
        if (!username) {
                return;
        }
 
        protocol_version = lp_parm_const_string(SNUM(handle->conn),
-               "smb_traffic_analyzer",
-               "protocol_version", NULL );
+                                       "smb_traffic_analyzer",
+                                       "protocol_version", NULL );
+
 
        if ( protocol_version == NULL || strcmp( protocol_version,"V1") == 0) {
 
                struct rw_data *s_data = (struct rw_data *) data;
 
-               /* in case of protocol v1, ignore any vfs operations    */
-               /* except read,pread,write,pwrite, and set the "Write"  */
-               /* bool accordingly.                                    */
-
+               /*
+                * in case of protocol v1, ignore any vfs operations
+                * except read,pread,write,pwrite, and set the "Write"
+                * bool accordingly, send data and return.
+                */
                if ( vfs_operation > vfs_id_pwrite ) return;
 
                if ( vfs_operation <= vfs_id_pread ) Write=false;
@@ -335,7 +471,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        "\"%04d-%02d-%02d %02d:%02d:%02d.%03d\"\n",
                        (unsigned int) s_data->len,
                        username,
-                       pdb_get_domain(handle->conn->server_info->sam_account),
+                       handle->conn->session_info->info3->base.domain.string,
                        Write ? 'W' : 'R',
                        handle->conn->connectpath,
                        s_data->filename,
@@ -346,49 +482,84 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        tm->tm_min,
                        tm->tm_sec,
                        (int)seconds);
+               len = strlen(str);
+               if (write_data(rf_sock->sock, str, len) != len) {
+                       DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
+                       "error sending V1 protocol data to socket!\n"));
+               return;
+               }
+
        } else if ( strcmp( protocol_version, "V2") == 0) {
 
                switch( vfs_operation ) {
-                       case vfs_id_mkdir: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, \
-                                       3, ((t_mkdir *) data)->path, \
-                                       talloc_asprintf( talloc_tos(), "%u", \
-                                               ((t_mkdir *) data)->mode), \
-                                       talloc_asprintf( talloc_tos(), "%u", \
-                                               ((t_mkdir *) data)->result ));
-                               break;
-                       case vfs_id_rmdir: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, \
-                                       2, ((t_rmdir *) data)->path, \
-                                       talloc_asprintf( talloc_tos(), "%u", \
-                                               ((t_rmdir *) data)->result ));
-                               break;
-                       case vfs_id_rename: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, \
-                                       3, ((t_rename *) data)->src, \
-                                       ((t_rename *) data)->dst,
-                                       talloc_asprintf(talloc_tos(), "%u", \
-                                               ((t_rename *) data)->result));
-                               break;
-                       case vfs_id_chdir: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, \
-                                       2, ((t_chdir *) data)->path, \
-                                       talloc_asprintf(talloc_tos(), "%u", \
-                                               ((t_chdir *) data)->result));
-                               break;
-                       default:
-                               DEBUG(1, ("smb_traffic_analyzer: error! "
-                                       "wrong VFS operation id detected!\n"));
-                               return;
+               case vfs_id_open: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_open,
+                               3, ((struct open_data *) data)->filename,
+                               talloc_asprintf( talloc_tos(), "%u",
+                               ((struct open_data *) data)->mode),
+                               talloc_asprintf( talloc_tos(), "%u",
+                               ((struct open_data *) data)->result));
+                       break;
+               case vfs_id_close: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_close,
+                               2, ((struct close_data *) data)->filename,
+                               talloc_asprintf( talloc_tos(), "%u",
+                               ((struct close_data *) data)->result));
+                       break;
+               case vfs_id_mkdir: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_mkdir, \
+                               3, ((struct mkdir_data *) data)->path, \
+                               talloc_asprintf( talloc_tos(), "%u", \
+                               ((struct mkdir_data *) data)->mode), \
+                               talloc_asprintf( talloc_tos(), "%u", \
+                               ((struct mkdir_data *) data)->result ));
+                       break;
+               case vfs_id_rmdir: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_rmdir,
+                               2, ((struct rmdir_data *) data)->path, \
+                               talloc_asprintf( talloc_tos(), "%u", \
+                               ((struct rmdir_data *) data)->result ));
+                       break;
+               case vfs_id_rename: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_rename,
+                               3, ((struct rename_data *) data)->src, \
+                               ((struct rename_data *) data)->dst,
+                               talloc_asprintf(talloc_tos(), "%u", \
+                               ((struct rename_data *) data)->result));
+                       break;
+               case vfs_id_chdir: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_chdir,
+                               2, ((struct chdir_data *) data)->path, \
+                               talloc_asprintf(talloc_tos(), "%u", \
+                               ((struct chdir_data *) data)->result));
+                       break;
+
+               case vfs_id_write:
+               case vfs_id_pwrite:
+               case vfs_id_read:
+               case vfs_id_pread: ;
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_operation,
+                               2, ((struct rw_data *) data)->filename, \
+                               talloc_asprintf(talloc_tos(), "%u", \
+                               (unsigned int)
+                                       ((struct rw_data *) data)->len));
+                       break;
+               default:
+                       DEBUG(1, ("smb_traffic_analyzer: error! "
+                               "wrong VFS operation id detected!\n"));
+                       return;
                }
 
        } else {
                DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error, unkown protocol given!\n"));
+                       "error, unknown protocol given!\n"));
                return;
        }
 
@@ -398,15 +569,38 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                return;
        }
 
-       len = strlen(str);
 
-       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: sending %s\n",
-                       str));
-       if (write_data(rf_sock->sock, str, len) != len) {
-               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error sending data to socket!\n"));
-               return ;
+       /*
+        * If configured, optain the key and run AES encryption
+        * over the data.
+        */
+       become_root();
+       akey = (char *) secrets_fetch("smb_traffic_analyzer_key", &size);
+       unbecome_root();
+       if ( akey != NULL ) {
+               state_flags[2] = 'E';
+               DEBUG(10, ("smb_traffic_analyzer_send_data_socket: a key was"
+                       " found, encrypting data!\n"));
+               output = smb_traffic_analyzer_encrypt( talloc_tos(),
+                                               akey, str, &len);
+               SAFE_FREE(akey);
+               header = smb_traffic_analyzer_create_header( talloc_tos(),
+                                               state_flags, len);
+
+               DEBUG(10, ("smb_traffic_analyzer_send_data_socket:"
+                       " header created for crypted data: %s\n", header));
+               smb_traffic_analyzer_write_data(header, output, len,
+                                                       rf_sock->sock);
+               return;
+
        }
+
+        len = strlen(str);
+       header = smb_traffic_analyzer_create_header( talloc_tos(),
+                               state_flags, len);
+       smb_traffic_analyzer_write_data(header, str, strlen(str),
+                               rf_sock->sock);
+
 }
 
 static struct refcounted_sock *sock_list;
@@ -554,6 +748,44 @@ static int smb_traffic_analyzer_mkdir(vfs_handle_struct *handle, \
        return s_data.result;
 }
 
+static ssize_t smb_traffic_analyzer_sendfile(vfs_handle_struct *handle,
+                               int tofd,
+                               files_struct *fromfsp,
+                               const DATA_BLOB *hdr,
+                               SMB_OFF_T offset,
+                               size_t n)
+{
+       struct rw_data s_data;
+       s_data.len = SMB_VFS_NEXT_SENDFILE(handle,
+                       tofd, fromfsp, hdr, offset, n);
+       s_data.filename = fromfsp->fsp_name->base_name;
+       DEBUG(10, ("smb_traffic_analyzer_sendfile: sendfile(r): %s\n",
+               fsp_str_dbg(fromfsp)));
+       smb_traffic_analyzer_send_data(handle,
+               &s_data,
+               vfs_id_read);
+       return s_data.len;
+}
+
+static ssize_t smb_traffic_analyzer_recvfile(vfs_handle_struct *handle,
+                               int fromfd,
+                               files_struct *tofsp,
+                               SMB_OFF_T offset,
+                               size_t n)
+{
+       struct rw_data s_data;
+       s_data.len = SMB_VFS_NEXT_RECVFILE(handle,
+                       fromfd, tofsp, offset, n);
+       s_data.filename = tofsp->fsp_name->base_name;
+       DEBUG(10, ("smb_traffic_analyzer_recvfile: recvfile(w): %s\n",
+               fsp_str_dbg(tofsp)));
+       smb_traffic_analyzer_send_data(handle,
+               &s_data,
+               vfs_id_write);
+       return s_data.len;
+}
+
+
 static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \
                                files_struct *fsp, void *data, size_t n)
 {
@@ -619,6 +851,39 @@ static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \
        return s_data.len;
 }
 
+static int smb_traffic_analyzer_open(vfs_handle_struct *handle, \
+       struct smb_filename *smb_fname, files_struct *fsp,\
+       int flags, mode_t mode)
+{
+       struct open_data s_data;
+
+       s_data.result = SMB_VFS_NEXT_OPEN( handle, smb_fname, fsp,
+                       flags, mode);
+       DEBUG(10,("smb_traffic_analyzer_open: OPEN: %s\n",
+               fsp_str_dbg(fsp)));
+       s_data.filename = fsp->fsp_name->base_name;
+       s_data.mode = mode;
+       smb_traffic_analyzer_send_data(handle,
+                       &s_data,
+                       vfs_id_open);
+       return s_data.result;
+}
+
+static int smb_traffic_analyzer_close(vfs_handle_struct *handle, \
+       files_struct *fsp)
+{
+       struct close_data s_data;
+       s_data.result = SMB_VFS_NEXT_CLOSE(handle, fsp);
+       DEBUG(10,("smb_traffic_analyzer_close: CLOSE: %s\n",
+               fsp_str_dbg(fsp)));
+       s_data.filename = fsp->fsp_name->base_name;
+       smb_traffic_analyzer_send_data(handle,
+                       &s_data,
+                       vfs_id_close);
+       return s_data.result;
+}
+
+       
 static struct vfs_fn_pointers vfs_smb_traffic_analyzer_fns = {
         .connect_fn = smb_traffic_analyzer_connect,
        .vfs_read = smb_traffic_analyzer_read,
@@ -627,11 +892,15 @@ static struct vfs_fn_pointers vfs_smb_traffic_analyzer_fns = {
        .pwrite = smb_traffic_analyzer_pwrite,
        .mkdir = smb_traffic_analyzer_mkdir,
        .rename = smb_traffic_analyzer_rename,
-       .chdir = smb_traffic_analyzer_chdir
+       .chdir = smb_traffic_analyzer_chdir,
+       .open_fn = smb_traffic_analyzer_open,
+       .rmdir = smb_traffic_analyzer_rmdir,
+       .close_fn = smb_traffic_analyzer_close,
+       .sendfile = smb_traffic_analyzer_sendfile,
+       .recvfile = smb_traffic_analyzer_recvfile
 };
 
 /* Module initialization */
-
 NTSTATUS vfs_smb_traffic_analyzer_init(void)
 {
        NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,