Restructure the module so it connects to the remote data sink
authorJeremy Allison <jra@samba.org>
Tue, 30 Sep 2008 22:13:19 +0000 (15:13 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 30 Sep 2008 22:13:19 +0000 (15:13 -0700)
on connect, and closes the socket on client disconnect. This should
make it much more efficient. Store the remote fd in a private data
pointer off the handle. Finally we need to remove the fstrings and
convert to allocated buffer storage.
Jeremy.

source3/modules/vfs_smb_traffic_analyzer.c

index 9e4cf816385d3bdb99d55d618c31d2c5dbe46516..cd843e6ad4e7fb3c6bd347fcc17a4152f8f1e7b7 100644 (file)
@@ -31,67 +31,8 @@ extern userdom_struct current_user_info;
 
 static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
 
-NTSTATUS vfs_smb_traffic_analyzer_init(void);
-
-static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle,
-               files_struct *fsp, const void *data, size_t n);
-
-static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle,
-               files_struct *fsp, void *data, size_t n);
-
-static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle,
-               files_struct *fsp, const void *data, size_t n,
-               SMB_OFF_T offset);
-
-static ssize_t smb_traffic_analyzer_pread(vfs_handle_struct *handle,
-               files_struct *fsp, void *data, size_t n, SMB_OFF_T offset);
-
-
-/* VFS operations we use */
-
-static vfs_op_tuple smb_traffic_analyzer_tuples[] = {
-
-       {SMB_VFS_OP(smb_traffic_analyzer_read), SMB_VFS_OP_READ,
-        SMB_VFS_LAYER_LOGGER},
-       {SMB_VFS_OP(smb_traffic_analyzer_pread), SMB_VFS_OP_PREAD,
-        SMB_VFS_LAYER_LOGGER},
-       {SMB_VFS_OP(smb_traffic_analyzer_write), SMB_VFS_OP_WRITE,
-        SMB_VFS_LAYER_LOGGER},
-       {SMB_VFS_OP(smb_traffic_analyzer_pwrite), SMB_VFS_OP_PWRITE,
-        SMB_VFS_LAYER_LOGGER},
-               {SMB_VFS_OP(NULL),SMB_VFS_OP_NOOP,SMB_VFS_LAYER_NOOP}
-
-       };
-
-
-/* Module initialization */
-
-NTSTATUS vfs_smb_traffic_analyzer_init(void)
-{
-       NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, \
-               "smb_traffic_analyzer", smb_traffic_analyzer_tuples);
-
-       if (!NT_STATUS_IS_OK(ret))
-               return ret;
-
-       vfs_smb_traffic_analyzer_debug_level =
-               debug_add_class("smb_traffic_analyzer");
-
-       if (vfs_smb_traffic_analyzer_debug_level == -1) {
-               vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
-               DEBUG(1, ("smb_traffic_analyzer: Couldn't register custom"
-                        "debugging class!\n"));
-       } else {
-               DEBUG(3, ("smb_traffic_analyzer: Debug class number of"
-                       "'smb_traffic_analyzer': %d\n", \
-                       vfs_smb_traffic_analyzer_debug_level));
-       }
-
-       return ret;
-}
-
 /* create the timestamp in sqlite compatible format */
-static void get_timestamp( char *String )
+static void get_timestamp(fstring str)
 {
        struct timeval tv;
        struct timezone tz;
@@ -102,13 +43,13 @@ static void get_timestamp( char *String )
        tm=localtime(&tv.tv_sec);
        seconds=(float) (tv.tv_usec / 1000);
 
-       fstr_sprintf(String,"%04d-%02d-%02d %02d:%02d:%02d.%03d", \
+       fstr_sprintf(str,"%04d-%02d-%02d %02d:%02d:%02d.%03d", \
                        tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, \
                        tm->tm_hour, tm->tm_min, tm->tm_sec, (int)seconds);
 
 }
 
-static int smb_traffic_analyzer_connMode( vfs_handle_struct *handle)
+static int smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
 {
        connection_struct *conn = handle->conn;
         const char *Mode;
@@ -122,10 +63,9 @@ static int smb_traffic_analyzer_connMode( vfs_handle_struct *handle)
 
 }
 
-/* Send data over a internet socket */
-static void smb_traffic_analyzer_send_data_inet_socket( char *String,
-                       vfs_handle_struct *handle, const char *file_name,
-                       bool Write)
+/* Connect to an internet socket */
+
+static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle)
 {
        /* Create a streaming Socket */
        const char *Hostname;
@@ -134,13 +74,11 @@ static void smb_traffic_analyzer_send_data_inet_socket( char *String,
        struct addrinfo hints;
        struct addrinfo *ailist = NULL;
        struct addrinfo *res = NULL;
-       char Sender[200];
-       char TimeStamp[200];
        connection_struct *conn = handle->conn;
        int ret;
 
        /* get port number, target system from the config parameters */
-       Hostname=lp_parm_const_string(SNUM(conn), "smb_traffic_analyzer", 
+       Hostname=lp_parm_const_string(SNUM(conn), "smb_traffic_analyzer",
                                "host", "localhost");
 
        ZERO_STRUCT(hints);
@@ -154,14 +92,14 @@ static void smb_traffic_analyzer_send_data_inet_socket( char *String,
                        &ailist);
 
         if (ret) {
-               DEBUG(3,("smb_traffic_analyzer_send_data_inet_socket: "
+               DEBUG(3,("smb_traffic_analyzer_connect_inet_socket: "
                        "getaddrinfo failed for name %s [%s]\n",
                         Hostname,
                         gai_strerror(ret) ));
-               return;
+               return -1;
         }
 
-       port = atoi( lp_parm_const_string(SNUM(conn), 
+       port = atoi( lp_parm_const_string(SNUM(conn),
                                "smb_traffic_analyzer", "port", "9430"));
 
        DEBUG(3,("smb_traffic_analyzer: Internet socket mode. Hostname: %s,"
@@ -188,116 +126,129 @@ static void smb_traffic_analyzer_send_data_inet_socket( char *String,
        }
 
         if (sockfd == -1) {
-               DEBUG(1, ("smb_traffic_analyzer: unable to create socket, error is %s", 
+               DEBUG(1, ("smb_traffic_analyzer: unable to create "
+                       "socket, error is %s",
                        strerror(errno)));
-               return;
+               return -1;
        }
 
-       strlcpy(Sender, String, sizeof(Sender));
-       strlcat(Sender, ",\"", sizeof(Sender));
-       strlcat(Sender, get_current_username(), sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender));
-       strlcat(Sender, current_user_info.domain, sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender));
-        if (Write)
-               strlcat(Sender, "W", sizeof(Sender));
-       else
-               strlcat(Sender, "R", sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender));
-       strlcat(Sender, handle->conn->connectpath, sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender) - 1);
-       strlcat(Sender, file_name, sizeof(Sender) - 1);
-       strlcat(Sender, "\",\"", sizeof(Sender) - 1);
-        get_timestamp(TimeStamp);
-       strlcat(Sender, TimeStamp, sizeof(Sender) - 1);
-       strlcat(Sender, "\");", sizeof(Sender) - 1);
-        DEBUG(10, ("smb_traffic_analyzer: sending %s\n", Sender));
-        if ( send(sockfd, Sender, strlen(Sender), 0) == -1 ) {
-                DEBUG(1, ("smb_traffic_analyzer: error sending data to socket!\n"));
-               close(sockfd);
-                return ;
-        }
-
-        /* one operation, close the socket */
-        close(sockfd);
+       return sockfd;
 }
 
+/* Connect to a unix domain socket */
 
-
-/* Send data over a unix domain socket */
-static void smb_traffic_analyzer_send_data_unix_socket( char *String ,
-                       vfs_handle_struct *handle, const char *file_name, 
-                       bool Write)
+static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle)
 {
        /* Create the socket to stad */
        int len, sock;
        struct sockaddr_un remote;
-        char Sender[200];
-        char TimeStamp[200];
 
-       DEBUG(7, ("smb_traffic_analyzer: Unix domain socket mode. Using "
+       DEBUG(7, ("smb_traffic_analyzer_connect_unix_socket: "
+                       "Unix domain socket mode. Using "
                        "/var/tmp/stadsocket\n"));
 
        if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-               DEBUG(1, ("smb_traffic_analyzer: Couldn create socket,"
+               DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
+                       "Couldn't create socket, "
                        "make sure stad is running!\n"));
        }
        remote.sun_family = AF_UNIX;
-       strlcpy(remote.sun_path, "/var/tmp/stadsocket", 
+       strlcpy(remote.sun_path, "/var/tmp/stadsocket",
                    sizeof(remote.sun_path));
        len=strlen(remote.sun_path) + sizeof(remote.sun_family);
        if (connect(sock, (struct sockaddr *)&remote, len) == -1 ) {
-               DEBUG(1, ("smb_traffic_analyzer: Could not connect to"
+               DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
+                       "Could not connect to "
                        "socket, make sure\nstad is running!\n"));
                close(sock);
+               return -1;
+       }
+       return sock;
+}
+
+/* Send data over a socket */
+
+static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
+                                       char *str,
+                                       const char *file_name,
+                                       bool Write)
+{
+       int *psockfd = NULL;
+       char Sender[200];
+       char TimeStamp[200];
+
+       SMB_VFS_HANDLE_GET_DATA(handle, psockfd, int, return);
+
+       if (psockfd == NULL || *psockfd == -1) {
+               DEBUG(1, ("smb_traffic_analyzer_send_data: socket is "
+                       "closed\n"));
                return;
        }
-       strlcpy(Sender, String, sizeof(Sender));
+
+       strlcpy(Sender, str, sizeof(Sender));
        strlcat(Sender, ",\"", sizeof(Sender));
        strlcat(Sender, get_current_username(), sizeof(Sender));
-       strlcat(Sender,"\",\"",sizeof(Sender));
+       strlcat(Sender, "\",\"", sizeof(Sender));
        strlcat(Sender, current_user_info.domain, sizeof(Sender));
        strlcat(Sender, "\",\"", sizeof(Sender));
-       if (Write)
+        if (Write)
                strlcat(Sender, "W", sizeof(Sender));
        else
                strlcat(Sender, "R", sizeof(Sender));
        strlcat(Sender, "\",\"", sizeof(Sender));
        strlcat(Sender, handle->conn->connectpath, sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender));
-       strlcat(Sender, file_name, sizeof(Sender));
-       strlcat(Sender, "\",\"", sizeof(Sender));
-       get_timestamp(TimeStamp);
-       strlcat(Sender, TimeStamp, sizeof(Sender));
-       strlcat(Sender, "\");", sizeof(Sender));
-
-       DEBUG(10, ("smb_traffic_analyzer: sending %s\n", Sender));
-       if ( send(sock, Sender, strlen(Sender), 0) == -1 ) {
-               DEBUG(1, ("smb_traffic_analyzer: error sending data to"
-                       "socket!\n"));
-               close(sock);
-               return;
+       strlcat(Sender, "\",\"", sizeof(Sender) - 1);
+       strlcat(Sender, file_name, sizeof(Sender) - 1);
+       strlcat(Sender, "\",\"", sizeof(Sender) - 1);
+        get_timestamp(TimeStamp);
+       strlcat(Sender, TimeStamp, sizeof(Sender) - 1);
+       strlcat(Sender, "\");", sizeof(Sender) - 1);
+       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: sending %s\n",
+                       Sender));
+       if (send(*psockfd, Sender, strlen(Sender), 0) == -1 ) {
+               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
+                       "error sending data to socket!\n"));
+               return ;
        }
+}
 
-       /* one operation, close the socket */
-       close(sock);
-       return;
+static void smb_traffic_analyzer_free_data(void **pptr)
+{
+       int *pfd = *(int **)pptr;
+       if(!pfd) {
+               return;
+       }
+       if (*pfd != -1) {
+               close(*pfd);
+       }
+       TALLOC_FREE(pfd);
 }
 
-static void smb_traffic_analyzer_send_data( char *Buffer , vfs_handle_struct \
-                       *handle, char *file_name, bool Write, files_struct *fsp)
+static int smb_traffic_analyzer_connect(struct vfs_handle_struct *handle,
+                         const char *service,
+                         const char *user)
 {
+       int *pfd = TALLOC_P(handle, int);
 
-        if (smb_traffic_analyzer_connMode(handle) == UNIX_DOMAIN_SOCKET) {
-                smb_traffic_analyzer_send_data_unix_socket(Buffer, handle, \
-                                                       fsp->fsp_name, Write);
-        } else {
-                smb_traffic_analyzer_send_data_inet_socket(Buffer, handle, \
-                                                       fsp->fsp_name, Write);
-        }
-}
+       if (!pfd) {
+               errno = ENOMEM;
+               return -1;
+       }
 
+       if (smb_traffic_analyzer_connMode(handle) == UNIX_DOMAIN_SOCKET) {
+               *pfd = smb_traffic_analyzer_connect_unix_socket(handle);
+       } else {
+               *pfd = smb_traffic_analyzer_connect_inet_socket(handle);
+       }
+       if (*pfd == -1) {
+               return -1;
+       }
 
+       /* Store the private data. */
+       SMB_VFS_HANDLE_SET_DATA(handle, pfd, smb_traffic_analyzer_free_data,
+                               int, return -1);
+       return SMB_VFS_NEXT_CONNECT(handle, service, user);
+}
 
 /* VFS Functions: write, read, pread, pwrite for now */
 
@@ -308,11 +259,14 @@ static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \
         fstring Buffer;
 
        result = SMB_VFS_NEXT_READ(handle, fsp, data, n);
-       DEBUG(10, ("smb_traffic_analyzer: READ: %s\n", fsp->fsp_name ));
+       DEBUG(10, ("smb_traffic_analyzer_read: READ: %s\n", fsp->fsp_name ));
 
        fstr_sprintf(Buffer, "%u", (uint) result);
 
-       smb_traffic_analyzer_send_data(Buffer, handle, fsp->fsp_name, false, fsp);
+       smb_traffic_analyzer_send_data(handle,
+                       Buffer,
+                       fsp->fsp_name,
+                       false);
        return result;
 }
 
@@ -325,10 +279,13 @@ static ssize_t smb_traffic_analyzer_pread(vfs_handle_struct *handle, \
 
        result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
 
-       DEBUG(10, ("smb_traffic_analyzerREAD: %s\n", fsp->fsp_name ));
+       DEBUG(10, ("smb_traffic_analyzer_pread: PREAD: %s\n", fsp->fsp_name ));
 
        fstr_sprintf(Buffer,"%u", (uint) result);
-       smb_traffic_analyzer_send_data(Buffer, handle, fsp->fsp_name, false, fsp);
+       smb_traffic_analyzer_send_data(handle,
+                       Buffer,
+                       fsp->fsp_name,
+                       false);
 
        return result;
 }
@@ -341,11 +298,13 @@ static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle, \
 
        result = SMB_VFS_NEXT_WRITE(handle, fsp, data, n);
 
-       DEBUG(10, ("smb_traffic_analyzer: WRITE: %s\n", fsp->fsp_name ));
+       DEBUG(10, ("smb_traffic_analyzer_write: WRITE: %s\n", fsp->fsp_name ));
 
        fstr_sprintf(Buffer, "%u", (uint) result);
-       smb_traffic_analyzer_send_data(Buffer, handle, fsp->fsp_name, \
-                                                               true, fsp );
+       smb_traffic_analyzer_send_data(handle,
+                       Buffer,
+                       fsp->fsp_name,
+                       true);
        return result;
 }
 
@@ -357,9 +316,56 @@ static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \
 
        result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
 
-       DEBUG(10, ("smb_traffic_analyzer: PWRITE: %s\n", fsp->fsp_name ));
+       DEBUG(10, ("smb_traffic_analyzer_pwrite: PWRITE: %s\n", fsp->fsp_name ));
 
        fstr_sprintf(Buffer, "%u", (uint) result);
-       smb_traffic_analyzer_send_data(Buffer, handle, fsp->fsp_name, true, fsp);
+       smb_traffic_analyzer_send_data(handle,
+                       Buffer,
+                       fsp->fsp_name,
+                       true);
        return result;
 }
+
+/* VFS operations we use */
+
+static vfs_op_tuple smb_traffic_analyzer_tuples[] = {
+
+        {SMB_VFS_OP(smb_traffic_analyzer_connect), SMB_VFS_OP_CONNECT,
+         SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_traffic_analyzer_read), SMB_VFS_OP_READ,
+        SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_traffic_analyzer_pread), SMB_VFS_OP_PREAD,
+        SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_traffic_analyzer_write), SMB_VFS_OP_WRITE,
+        SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_traffic_analyzer_pwrite), SMB_VFS_OP_PWRITE,
+        SMB_VFS_LAYER_LOGGER},
+               {SMB_VFS_OP(NULL),SMB_VFS_OP_NOOP,SMB_VFS_LAYER_NOOP}
+};
+
+/* Module initialization */
+
+NTSTATUS vfs_smb_traffic_analyzer_init(void)
+{
+       NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, \
+               "smb_traffic_analyzer", smb_traffic_analyzer_tuples);
+
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+
+       vfs_smb_traffic_analyzer_debug_level =
+               debug_add_class("smb_traffic_analyzer");
+
+       if (vfs_smb_traffic_analyzer_debug_level == -1) {
+               vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
+               DEBUG(1, ("smb_traffic_analyzer_init: Couldn't register custom"
+                        "debugging class!\n"));
+       } else {
+               DEBUG(3, ("smb_traffic_analyzer_init: Debug class number of"
+                       "'smb_traffic_analyzer': %d\n", \
+                       vfs_smb_traffic_analyzer_debug_level));
+       }
+
+       return ret;
+}