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/>.
23 /* abstraction for the send_over_network function */
24 #define UNIX_DOMAIN_SOCKET 1
25 #define INTERNET_SOCKET 0
30 extern userdom_struct current_user_info
;
32 static int vfs_smb_traffic_analyzer_debug_level
= DBGC_VFS
;
34 /* create the timestamp in sqlite compatible format */
35 static void get_timestamp(fstring str
)
42 gettimeofday(&tv
, &tz
);
43 tm
=localtime(&tv
.tv_sec
);
44 seconds
=(float) (tv
.tv_usec
/ 1000);
46 fstr_sprintf(str
,"%04d-%02d-%02d %02d:%02d:%02d.%03d", \
47 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
, \
48 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
, (int)seconds
);
52 static int smb_traffic_analyzer_connMode(vfs_handle_struct
*handle
)
54 connection_struct
*conn
= handle
->conn
;
56 Mode
=lp_parm_const_string(SNUM(conn
), "smb_traffic_analyzer","mode", \
58 if (strstr(Mode
,"unix_domain_socket")) {
59 return UNIX_DOMAIN_SOCKET
;
61 return INTERNET_SOCKET
;
66 /* Connect to an internet socket */
68 static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct
*handle
)
70 /* Create a streaming Socket */
74 struct addrinfo hints
;
75 struct addrinfo
*ailist
= NULL
;
76 struct addrinfo
*res
= NULL
;
77 connection_struct
*conn
= handle
->conn
;
80 /* get port number, target system from the config parameters */
81 Hostname
=lp_parm_const_string(SNUM(conn
), "smb_traffic_analyzer",
85 /* By default make sure it supports TCP. */
86 hints
.ai_socktype
= SOCK_STREAM
;
87 hints
.ai_flags
= AI_ADDRCONFIG
;
89 ret
= getaddrinfo(Hostname
,
95 DEBUG(3,("smb_traffic_analyzer_connect_inet_socket: "
96 "getaddrinfo failed for name %s [%s]\n",
102 port
= atoi( lp_parm_const_string(SNUM(conn
),
103 "smb_traffic_analyzer", "port", "9430"));
105 DEBUG(3,("smb_traffic_analyzer: Internet socket mode. Hostname: %s,"
106 "Port: %i\n", Hostname
, port
));
108 for (res
= ailist
; res
; res
= res
->ai_next
) {
109 struct sockaddr_storage ss
;
111 if (!res
->ai_addr
|| res
->ai_addrlen
== 0) {
116 memcpy(&ss
, res
->ai_addr
, res
->ai_addrlen
);
118 sockfd
= open_socket_out(SOCK_STREAM
, &ss
, port
, 10000);
125 freeaddrinfo(ailist
);
129 DEBUG(1, ("smb_traffic_analyzer: unable to create "
130 "socket, error is %s",
138 /* Connect to a unix domain socket */
140 static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct
*handle
)
142 /* Create the socket to stad */
144 struct sockaddr_un remote
;
146 DEBUG(7, ("smb_traffic_analyzer_connect_unix_socket: "
147 "Unix domain socket mode. Using "
148 "/var/tmp/stadsocket\n"));
150 if ((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
151 DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
152 "Couldn't create socket, "
153 "make sure stad is running!\n"));
155 remote
.sun_family
= AF_UNIX
;
156 strlcpy(remote
.sun_path
, "/var/tmp/stadsocket",
157 sizeof(remote
.sun_path
));
158 len
=strlen(remote
.sun_path
) + sizeof(remote
.sun_family
);
159 if (connect(sock
, (struct sockaddr
*)&remote
, len
) == -1 ) {
160 DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
161 "Could not connect to "
162 "socket, make sure\nstad is running!\n"));
169 /* Send data over a socket */
171 static void smb_traffic_analyzer_send_data(vfs_handle_struct
*handle
,
173 const char *file_name
,
180 SMB_VFS_HANDLE_GET_DATA(handle
, psockfd
, int, return);
182 if (psockfd
== NULL
|| *psockfd
== -1) {
183 DEBUG(1, ("smb_traffic_analyzer_send_data: socket is "
188 strlcpy(Sender
, str
, sizeof(Sender
));
189 strlcat(Sender
, ",\"", sizeof(Sender
));
190 strlcat(Sender
, get_current_username(), sizeof(Sender
));
191 strlcat(Sender
, "\",\"", sizeof(Sender
));
192 strlcat(Sender
, current_user_info
.domain
, sizeof(Sender
));
193 strlcat(Sender
, "\",\"", sizeof(Sender
));
195 strlcat(Sender
, "W", sizeof(Sender
));
197 strlcat(Sender
, "R", sizeof(Sender
));
198 strlcat(Sender
, "\",\"", sizeof(Sender
));
199 strlcat(Sender
, handle
->conn
->connectpath
, sizeof(Sender
));
200 strlcat(Sender
, "\",\"", sizeof(Sender
) - 1);
201 strlcat(Sender
, file_name
, sizeof(Sender
) - 1);
202 strlcat(Sender
, "\",\"", sizeof(Sender
) - 1);
203 get_timestamp(TimeStamp
);
204 strlcat(Sender
, TimeStamp
, sizeof(Sender
) - 1);
205 strlcat(Sender
, "\");", sizeof(Sender
) - 1);
206 DEBUG(10, ("smb_traffic_analyzer_send_data_socket: sending %s\n",
208 if (send(*psockfd
, Sender
, strlen(Sender
), 0) == -1 ) {
209 DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
210 "error sending data to socket!\n"));
215 static void smb_traffic_analyzer_free_data(void **pptr
)
217 int *pfd
= *(int **)pptr
;
227 static int smb_traffic_analyzer_connect(struct vfs_handle_struct
*handle
,
231 int *pfd
= TALLOC_P(handle
, int);
238 if (smb_traffic_analyzer_connMode(handle
) == UNIX_DOMAIN_SOCKET
) {
239 *pfd
= smb_traffic_analyzer_connect_unix_socket(handle
);
241 *pfd
= smb_traffic_analyzer_connect_inet_socket(handle
);
247 /* Store the private data. */
248 SMB_VFS_HANDLE_SET_DATA(handle
, pfd
, smb_traffic_analyzer_free_data
,
250 return SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
253 /* VFS Functions: write, read, pread, pwrite for now */
255 static ssize_t
smb_traffic_analyzer_read(vfs_handle_struct
*handle
, \
256 files_struct
*fsp
, void *data
, size_t n
)
261 result
= SMB_VFS_NEXT_READ(handle
, fsp
, data
, n
);
262 DEBUG(10, ("smb_traffic_analyzer_read: READ: %s\n", fsp
->fsp_name
));
264 fstr_sprintf(Buffer
, "%u", (uint
) result
);
266 smb_traffic_analyzer_send_data(handle
,
274 static ssize_t
smb_traffic_analyzer_pread(vfs_handle_struct
*handle
, \
275 files_struct
*fsp
, void *data
, size_t n
, SMB_OFF_T offset
)
280 result
= SMB_VFS_NEXT_PREAD(handle
, fsp
, data
, n
, offset
);
282 DEBUG(10, ("smb_traffic_analyzer_pread: PREAD: %s\n", fsp
->fsp_name
));
284 fstr_sprintf(Buffer
,"%u", (uint
) result
);
285 smb_traffic_analyzer_send_data(handle
,
293 static ssize_t
smb_traffic_analyzer_write(vfs_handle_struct
*handle
, \
294 files_struct
*fsp
, const void *data
, size_t n
)
299 result
= SMB_VFS_NEXT_WRITE(handle
, fsp
, data
, n
);
301 DEBUG(10, ("smb_traffic_analyzer_write: WRITE: %s\n", fsp
->fsp_name
));
303 fstr_sprintf(Buffer
, "%u", (uint
) result
);
304 smb_traffic_analyzer_send_data(handle
,
311 static ssize_t
smb_traffic_analyzer_pwrite(vfs_handle_struct
*handle
, \
312 files_struct
*fsp
, const void *data
, size_t n
, SMB_OFF_T offset
)
317 result
= SMB_VFS_NEXT_PWRITE(handle
, fsp
, data
, n
, offset
);
319 DEBUG(10, ("smb_traffic_analyzer_pwrite: PWRITE: %s\n", fsp
->fsp_name
));
321 fstr_sprintf(Buffer
, "%u", (uint
) result
);
322 smb_traffic_analyzer_send_data(handle
,
329 /* VFS operations we use */
331 static vfs_op_tuple smb_traffic_analyzer_tuples
[] = {
333 {SMB_VFS_OP(smb_traffic_analyzer_connect
), SMB_VFS_OP_CONNECT
,
334 SMB_VFS_LAYER_LOGGER
},
335 {SMB_VFS_OP(smb_traffic_analyzer_read
), SMB_VFS_OP_READ
,
336 SMB_VFS_LAYER_LOGGER
},
337 {SMB_VFS_OP(smb_traffic_analyzer_pread
), SMB_VFS_OP_PREAD
,
338 SMB_VFS_LAYER_LOGGER
},
339 {SMB_VFS_OP(smb_traffic_analyzer_write
), SMB_VFS_OP_WRITE
,
340 SMB_VFS_LAYER_LOGGER
},
341 {SMB_VFS_OP(smb_traffic_analyzer_pwrite
), SMB_VFS_OP_PWRITE
,
342 SMB_VFS_LAYER_LOGGER
},
343 {SMB_VFS_OP(NULL
),SMB_VFS_OP_NOOP
,SMB_VFS_LAYER_NOOP
}
346 /* Module initialization */
348 NTSTATUS
vfs_smb_traffic_analyzer_init(void)
350 NTSTATUS ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, \
351 "smb_traffic_analyzer", smb_traffic_analyzer_tuples
);
353 if (!NT_STATUS_IS_OK(ret
)) {
357 vfs_smb_traffic_analyzer_debug_level
=
358 debug_add_class("smb_traffic_analyzer");
360 if (vfs_smb_traffic_analyzer_debug_level
== -1) {
361 vfs_smb_traffic_analyzer_debug_level
= DBGC_VFS
;
362 DEBUG(1, ("smb_traffic_analyzer_init: Couldn't register custom"
363 "debugging class!\n"));
365 DEBUG(3, ("smb_traffic_analyzer_init: Debug class number of"
366 "'smb_traffic_analyzer': %d\n", \
367 vfs_smb_traffic_analyzer_debug_level
));