Fix the new vfs_smb_traffic_analyzer build for static links
[Samba.git] / source / modules / vfs_smb_traffic_analyzer.c
blob237859182b57ad18feac76bfcd794942f7389868
1 /*
2 * traffic-analyzer VFS module. Measure the smb traffic users create
3 * on the net.
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/>.
21 #include "includes.h"
22 #include "safe_string.h"
23 #include <sys/socket.h>
24 #include <stdlib.h>
25 #include <sys/time.h>
28 /* abstraction for the send_over_network function */
29 #define UNIX_DOMAIN_SOCKET 1
30 #define INTERNET_SOCKET 0
33 /* Prototypes */
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,
49 SMB_OFF_T offset);
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))
80 return 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"));
89 } else {
90 DEBUG(3, ("smb_traffic_analyzer: Debug class number of"
91 "'smb_traffic_analyzer': %d\n", \
92 vfs_smb_traffic_analyzer_debug_level));
95 return ret;
98 /* create the timestamp in sqlite compatible format */
99 static void get_timestamp( char *String )
101 struct timeval tv;
102 struct timezone tz;
103 struct tm *tm;
104 int seconds;
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;
119 const char *Mode;
120 Mode=lp_parm_const_string(SNUM(conn), "smb_traffic_analyzer","mode", \
121 "internet_socket");
122 if (strstr(Mode,"unix_domain_socket")) {
123 return UNIX_DOMAIN_SOCKET;
124 } else {
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,
135 bool Write)
137 /* Create a streaming Socket */
138 const char *Hostname;
139 int sockfd, result;
140 int port;
141 struct sockaddr_in their_addr;
142 struct hostent *hp;
143 char Sender[200];
144 char TimeStamp[200];
145 int yes = 1;
146 connection_struct *conn;
148 if ((sockfd=socket(AF_INET, SOCK_STREAM,0)) == -1) {
149 DEBUG(1, ("unable to create socket, error is %s",
150 strerror(errno)));
151 return;
153 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, \
154 sizeof(int)) == -1) {
155 DEBUG(1, ("unable to set socket options, error is %s",
156 strerror(errno)));
157 return;
159 /* get port number, target system from the config parameters */
160 conn=handle->conn;
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);
169 if (hp == NULL) {
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));
183 if ( result < 0 ) {
184 DEBUG(1, ("smb_traffic_analyzer: Couldn't connect to inet"
185 "socket!\n"));
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);
193 if (Write)
194 safe_strcat(Sender, "W", sizeof(Sender) - 1);
195 else
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"));
208 return ;
211 /* one operation, close the socket */
212 close(sockfd);
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,
220 bool Write)
222 /* Create the socket to stad */
223 int len, sock;
224 struct sockaddr_un remote;
225 char Sender[200];
226 char TimeStamp[200];
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);
247 if (Write)
248 safe_strcat(Sender, "W", sizeof(Sender) - 1);
249 else
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"
263 "socket!\n"));
264 return;
267 /* one operation, close the socket */
268 close(sock);
270 return;
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);
280 } else {
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)
293 ssize_t result;
294 char Buffer[100];
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);
302 return result;
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)
309 ssize_t result;
310 char Buffer[100];
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);
319 return result;
322 static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle, \
323 files_struct *fsp, const void *data, size_t n)
325 ssize_t result;
326 char Buffer[100];
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, \
334 true, fsp );
335 return result;
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)
341 ssize_t result;
342 char Buffer[100];
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);
350 return result;