2 * traffic-analyzer VFS module. Measure the smb traffic users create
5 * Copyright (C) Holger Hetterich, 2008
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.
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.
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/>.
22 #include "safe_string.h"
23 #include <sys/socket.h>
28 /* abstraction for the send_over_network function */
29 #define UNIX_DOMAIN_SOCKET 1
30 #define INTERNET_SOCKET 0
35 extern userdom_struct current_user_info
;
37 static int vfs_smb_traffic_analyzer_debug_level
= DBGC_VFS
;
39 NTSTATUS
vfs_smb_traffic_analyzer_init(void);
41 static ssize_t
smb_traffic_analyzer_write(vfs_handle_struct
*handle
,
42 files_struct
*fsp
, const void *data
, size_t n
);
44 static ssize_t
smb_traffic_analyzer_read(vfs_handle_struct
*handle
,
45 files_struct
*fsp
, void *data
, size_t n
);
47 static ssize_t
smb_traffic_analyzer_pwrite(vfs_handle_struct
*handle
,
48 files_struct
*fsp
, const void *data
, size_t n
,
51 static ssize_t
smb_traffic_analyzer_pread(vfs_handle_struct
*handle
,
52 files_struct
*fsp
, void *data
, size_t n
, SMB_OFF_T offset
);
55 /* VFS operations we use */
57 static vfs_op_tuple smb_traffic_analyzer_tuples
[] = {
59 {SMB_VFS_OP(smb_traffic_analyzer_read
), SMB_VFS_OP_READ
,
60 SMB_VFS_LAYER_LOGGER
},
61 {SMB_VFS_OP(smb_traffic_analyzer_pread
), SMB_VFS_OP_PREAD
,
62 SMB_VFS_LAYER_LOGGER
},
63 {SMB_VFS_OP(smb_traffic_analyzer_write
), SMB_VFS_OP_WRITE
,
64 SMB_VFS_LAYER_LOGGER
},
65 {SMB_VFS_OP(smb_traffic_analyzer_pwrite
), SMB_VFS_OP_PWRITE
,
66 SMB_VFS_LAYER_LOGGER
},
67 {SMB_VFS_OP(NULL
),SMB_VFS_OP_NOOP
,SMB_VFS_LAYER_NOOP
}
72 /* Module initialization */
74 NTSTATUS
vfs_smb_traffic_analyzer_init(void)
76 NTSTATUS ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, \
77 "smb_traffic_analyzer", smb_traffic_analyzer_tuples
);
79 if (!NT_STATUS_IS_OK(ret
))
82 vfs_smb_traffic_analyzer_debug_level
=
83 debug_add_class("smb_traffic_analyzer");
85 if (vfs_smb_traffic_analyzer_debug_level
== -1) {
86 vfs_smb_traffic_analyzer_debug_level
= DBGC_VFS
;
87 DEBUG(1, ("smb_traffic_analyzer: Couldn't register custom"
88 "debugging class!\n"));
90 DEBUG(3, ("smb_traffic_analyzer: Debug class number of"
91 "'smb_traffic_analyzer': %d\n", \
92 vfs_smb_traffic_analyzer_debug_level
));
98 /* create the timestamp in sqlite compatible format */
99 static void get_timestamp( char *String
)
106 gettimeofday(&tv
, &tz
);
107 tm
=localtime(&tv
.tv_sec
);
108 seconds
=(float) (tv
.tv_usec
/ 1000);
110 fstr_sprintf(String
,"%04d-%02d-%02d %02d:%02d:%02d.%03d", \
111 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
, \
112 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
, (int)seconds
);
116 static int smb_traffic_analyzer_connMode( vfs_handle_struct
*handle
)
118 connection_struct
*conn
= handle
->conn
;
120 Mode
=lp_parm_const_string(SNUM(conn
), "smb_traffic_analyzer","mode", \
122 if (strstr(Mode
,"unix_domain_socket")) {
123 return UNIX_DOMAIN_SOCKET
;
125 return INTERNET_SOCKET
;
132 /* Send data over a internet socket */
133 static void smb_traffic_analyzer_send_data_inet_socket( char *String
,
134 vfs_handle_struct
*handle
, const char *file_name
,
137 /* Create a streaming Socket */
138 const char *Hostname
;
141 struct sockaddr_in their_addr
;
146 connection_struct
*conn
;
148 if ((sockfd
=socket(AF_INET
, SOCK_STREAM
,0)) == -1) {
149 DEBUG(1, ("unable to create socket, error is %s",
153 if (setsockopt(sockfd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, \
154 sizeof(int)) == -1) {
155 DEBUG(1, ("unable to set socket options, error is %s",
159 /* get port number, target system from the config parameters */
162 Hostname
=lp_parm_const_string(SNUM(conn
), "smb_traffic_analyzer",
163 "host", "localhost");
165 port
= atoi( lp_parm_const_string(SNUM(conn
),
166 "smb_traffic_analyzer", "port", "9430"));
168 hp
= gethostbyname(Hostname
);
170 DEBUG(1, ("smb_traffic_analyzer: Unkown Hostname of"
171 "target system!\n"));
173 DEBUG(3,("smb_traffic_analyzer: Internet socket mode. Hostname: %s,"
174 "Port: %i\n", Hostname
, port
));
176 their_addr
.sin_family
= AF_INET
;
177 their_addr
.sin_port
= htons(port
);
178 their_addr
.sin_addr
.s_addr
= INADDR_ANY
;
179 memset(their_addr
.sin_zero
, '\0', sizeof(their_addr
.sin_zero
));
180 memcpy(hp
->h_addr
, &their_addr
.sin_addr
, hp
->h_length
);
181 their_addr
.sin_port
=htons(port
);
182 result
=connect( sockfd
, &their_addr
, sizeof( struct sockaddr_in
));
184 DEBUG(1, ("smb_traffic_analyzer: Couldn't connect to inet"
187 safe_strcpy(Sender
, String
, sizeof(Sender
) - 1);
188 safe_strcat(Sender
, ",\"", sizeof(Sender
) - 1);
189 safe_strcat(Sender
, get_current_username(), sizeof(Sender
) - 1);
190 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
191 safe_strcat(Sender
, current_user_info
.domain
, sizeof(Sender
) - 1);
192 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
194 safe_strcat(Sender
, "W", sizeof(Sender
) - 1);
196 safe_strcat(Sender
, "R", sizeof(Sender
) - 1);
197 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
198 safe_strcat(Sender
, handle
->conn
->connectpath
, sizeof(Sender
) - 1);
199 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
200 safe_strcat(Sender
, file_name
, sizeof(Sender
) - 1);
201 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
202 get_timestamp(TimeStamp
);
203 safe_strcat(Sender
, TimeStamp
, sizeof(Sender
) - 1);
204 safe_strcat(Sender
, "\");", sizeof(Sender
) - 1);
205 DEBUG(10, ("smb_traffic_analyzer: sending %s\n", Sender
));
206 if ( send(sockfd
, Sender
, strlen(Sender
), 0) == -1 ) {
207 DEBUG(1, ("smb_traffic_analyzer: error sending data to socket!\n"));
211 /* one operation, close the socket */
217 /* Send data over a unix domain socket */
218 static void smb_traffic_analyzer_send_data_unix_socket( char *String
,
219 vfs_handle_struct
*handle
, const char *file_name
,
222 /* Create the socket to stad */
224 struct sockaddr_un remote
;
227 DEBUG(7, ("smb_traffic_analyzer: Unix domain socket mode. Using "
228 "/var/tmp/stadsocket\n"));
229 if ((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
230 DEBUG(1, ("smb_traffic_analyzer: Couldn create socket,"
231 "make sure stad is running!\n"));
233 remote
.sun_family
= AF_UNIX
;
234 safe_strcpy(remote
.sun_path
, "/var/tmp/stadsocket",
235 sizeof(remote
.sun_path
) - 1);
236 len
=strlen(remote
.sun_path
) + sizeof(remote
.sun_family
);
237 if (connect(sock
, (struct sockaddr
*)&remote
, len
) == -1 ) {
238 DEBUG(1, ("smb_traffic_analyzer: Could not connect to"
239 "socket, make sure\nstad is running!\n"));
241 safe_strcpy(Sender
, String
, sizeof(Sender
) - 1);
242 safe_strcat(Sender
, ",\"", sizeof(Sender
) - 1);
243 safe_strcat(Sender
, get_current_username(), sizeof(Sender
) - 1);
244 safe_strcat(Sender
,"\",\"",sizeof(Sender
) - 1);
245 safe_strcat(Sender
, current_user_info
.domain
, sizeof(Sender
) - 1);
246 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
248 safe_strcat(Sender
, "W", sizeof(Sender
) - 1);
250 safe_strcat(Sender
, "R", sizeof(Sender
) - 1);
251 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
252 safe_strcat(Sender
, handle
->conn
->connectpath
, sizeof(Sender
) - 1);
253 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
254 safe_strcat(Sender
, file_name
, sizeof(Sender
) - 1);
255 safe_strcat(Sender
, "\",\"", sizeof(Sender
) - 1);
256 get_timestamp(TimeStamp
);
257 safe_strcat(Sender
, TimeStamp
, sizeof(Sender
) - 1);
258 safe_strcat(Sender
, "\");", sizeof(Sender
) - 1);
260 DEBUG(10, ("smb_traffic_analyzer: sending %s\n", Sender
));
261 if ( send(sock
, Sender
, strlen(Sender
), 0) == -1 ) {
262 DEBUG(1, ("smb_traffic_analyzer: error sending data to"
267 /* one operation, close the socket */
273 static void smb_traffic_analyzer_send_data( char *Buffer
, vfs_handle_struct \
274 *handle
, char *file_name
, bool Write
, files_struct
*fsp
)
277 if (smb_traffic_analyzer_connMode(handle
) == UNIX_DOMAIN_SOCKET
) {
278 smb_traffic_analyzer_send_data_unix_socket(Buffer
, handle
, \
279 fsp
->fsp_name
, Write
);
281 smb_traffic_analyzer_send_data_inet_socket(Buffer
, handle
, \
282 fsp
->fsp_name
, Write
);
288 /* VFS Functions: write, read, pread, pwrite for now */
290 static ssize_t
smb_traffic_analyzer_read(vfs_handle_struct
*handle
, \
291 files_struct
*fsp
, void *data
, size_t n
)
296 result
= SMB_VFS_NEXT_READ(handle
, fsp
, data
, n
);
297 DEBUG(10, ("smb_traffic_analyzer: READ: %s\n", fsp
->fsp_name
));
299 fstr_sprintf(Buffer
, "%u", (uint
) result
);
301 smb_traffic_analyzer_send_data(Buffer
, handle
, fsp
->fsp_name
, false, fsp
);
306 static ssize_t
smb_traffic_analyzer_pread(vfs_handle_struct
*handle
, \
307 files_struct
*fsp
, void *data
, size_t n
, SMB_OFF_T offset
)
312 result
= SMB_VFS_NEXT_PREAD(handle
, fsp
, data
, n
, offset
);
314 DEBUG(10, ("smb_traffic_analyzer: READ: %s\n", fsp
->fsp_name
));
316 fstr_sprintf(Buffer
,"%u", (uint
) result
);
317 smb_traffic_analyzer_send_data(Buffer
, handle
, fsp
->fsp_name
, false, fsp
);
322 static ssize_t
smb_traffic_analyzer_write(vfs_handle_struct
*handle
, \
323 files_struct
*fsp
, const void *data
, size_t n
)
328 result
= SMB_VFS_NEXT_WRITE(handle
, fsp
, data
, n
);
330 DEBUG(10, ("smb_traffic_analyzer: WRITE: %s\n", fsp
->fsp_name
));
332 fstr_sprintf(Buffer
, "%u", (uint
) result
);
333 smb_traffic_analyzer_send_data(Buffer
, handle
, fsp
->fsp_name
, \
338 static ssize_t
smb_traffic_analyzer_pwrite(vfs_handle_struct
*handle
, \
339 files_struct
*fsp
, const void *data
, size_t n
, SMB_OFF_T offset
)
344 result
= SMB_VFS_NEXT_PWRITE(handle
, fsp
, data
, n
, offset
);
346 DEBUG(10, ("smb_traffic_analyzer: PWRITE: %s\n", fsp
->fsp_name
));
348 fstr_sprintf(Buffer
, "%u", (uint
) result
);
349 smb_traffic_analyzer_send_data(Buffer
, handle
, fsp
->fsp_name
, true, fsp
);