bf7b4138d061b60f293cf5356757098612bf4661
[nivanova/samba-autobuild/.git] / source3 / modules / vfs_smb_traffic_analyzer.c
1 /*
2  * traffic-analyzer VFS module. Measure the smb traffic users create
3  * on the net.
4  *
5  * Copyright (C) Holger Hetterich, 2008-2010
6  * Copyright (C) Jeremy Allison, 2008
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "../lib/crypto/crypto.h"
24 #include "vfs_smb_traffic_analyzer.h"
25 #include "../libcli/security/dom_sid.h"
26
27 /* abstraction for the send_over_network function */
28 enum sock_type {INTERNET_SOCKET = 0, UNIX_DOMAIN_SOCKET};
29
30 #define LOCAL_PATHNAME "/var/tmp/stadsocket"
31
32 static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
33
34 static enum sock_type smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
35 {
36         connection_struct *conn = handle->conn;
37         const char *Mode;
38         Mode=lp_parm_const_string(SNUM(conn), "smb_traffic_analyzer","mode", \
39                         "internet_socket");
40         if (strstr(Mode,"unix_domain_socket")) {
41                 return UNIX_DOMAIN_SOCKET;
42         } else {
43                 return INTERNET_SOCKET;
44         }
45 }
46
47
48 /* Connect to an internet socket */
49 static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle,
50                                         const char *name, uint16_t port)
51 {
52         /* Create a streaming Socket */
53         int sockfd = -1;
54         struct addrinfo hints;
55         struct addrinfo *ailist = NULL;
56         struct addrinfo *res = NULL;
57         int ret;
58
59         ZERO_STRUCT(hints);
60         /* By default make sure it supports TCP. */
61         hints.ai_socktype = SOCK_STREAM;
62         hints.ai_flags = AI_ADDRCONFIG;
63
64         ret = getaddrinfo(name,
65                         NULL,
66                         &hints,
67                         &ailist);
68
69         if (ret) {
70                 DEBUG(3,("smb_traffic_analyzer_connect_inet_socket: "
71                         "getaddrinfo failed for name %s [%s]\n",
72                         name,
73                         gai_strerror(ret) ));
74                 return -1;
75         }
76
77         DEBUG(3,("smb_traffic_analyzer: Internet socket mode. Hostname: %s,"
78                 "Port: %i\n", name, port));
79
80         for (res = ailist; res; res = res->ai_next) {
81                 struct sockaddr_storage ss;
82                 NTSTATUS status;
83
84                 if (!res->ai_addr || res->ai_addrlen == 0) {
85                         continue;
86                 }
87
88                 ZERO_STRUCT(ss);
89                 memcpy(&ss, res->ai_addr, res->ai_addrlen);
90
91                 status = open_socket_out(&ss, port, 10000, &sockfd);
92                 if (NT_STATUS_IS_OK(status)) {
93                         break;
94                 }
95         }
96
97         if (ailist) {
98                 freeaddrinfo(ailist);
99         }
100
101         if (sockfd == -1) {
102                 DEBUG(1, ("smb_traffic_analyzer: unable to create "
103                         "socket, error is %s",
104                         strerror(errno)));
105                 return -1;
106         }
107
108         return sockfd;
109 }
110
111 /* Connect to a unix domain socket */
112 static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle,
113                                                 const char *name)
114 {
115         /* Create the socket to stad */
116         int len, sock;
117         struct sockaddr_un remote;
118
119         DEBUG(7, ("smb_traffic_analyzer_connect_unix_socket: "
120                         "Unix domain socket mode. Using %s\n",
121                         name ));
122
123         if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
124                 DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
125                         "Couldn't create socket, "
126                         "make sure stad is running!\n"));
127                 return -1;
128         }
129         remote.sun_family = AF_UNIX;
130         strlcpy(remote.sun_path, name,
131                     sizeof(remote.sun_path));
132         len=strlen(remote.sun_path) + sizeof(remote.sun_family);
133         if (connect(sock, (struct sockaddr *)&remote, len) == -1 ) {
134                 DEBUG(1, ("smb_traffic_analyzer_connect_unix_socket: "
135                         "Could not connect to "
136                         "socket, make sure\nstad is running!\n"));
137                 close(sock);
138                 return -1;
139         }
140         return sock;
141 }
142
143 /* Private data allowing shared connection sockets. */
144 struct refcounted_sock {
145         struct refcounted_sock *next, *prev;
146         char *name;
147         uint16_t port;
148         int sock;
149         unsigned int ref_count;
150 };
151
152
153 /**
154  * Encryption of a data block with AES
155  * TALLOC_CTX *ctx      Talloc context to work on
156  * const char *akey     128bit key for the encryption
157  * const char *str      Data buffer to encrypt, \0 terminated
158  * int *len             Will be set to the length of the
159  *                      resulting data block
160  * The caller has to take care for the memory
161  * allocated on the context.
162  */
163 static char *smb_traffic_analyzer_encrypt( TALLOC_CTX *ctx,
164         const char *akey, const char *str, size_t *len)
165 {
166         int s1,s2,h,d;
167         AES_KEY key;
168         unsigned char filler[17]= "................";
169         char *output;
170         unsigned char crypted[18];
171         if (akey == NULL) return NULL;
172         samba_AES_set_encrypt_key((unsigned char *) akey, 128, &key);
173         s1 = strlen(str) / 16;
174         s2 = strlen(str) % 16;
175         for (h = 0; h < s2; h++) *(filler+h)=*(str+(s1*16)+h);
176         DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created %s"
177                 " as filling block.\n", filler));
178         output = talloc_array(ctx, char, (s1*16)+17 );
179         d=0;
180         for (h = 0; h < s1; h++) {
181                 samba_AES_encrypt((unsigned char *) str+(16*h), crypted, &key);
182                 for (d = 0; d<16; d++) output[d+(16*h)]=crypted[d];
183         }
184         samba_AES_encrypt( (unsigned char *) str+(16*h), filler, &key );
185         for (d = 0;d < 16; d++) output[d+(16*h)]=*(filler+d);
186         *len = (s1*16)+16;
187         return output;  
188 }
189
190 /**
191  * Create a v2 header.
192  * TALLLOC_CTX *ctx             Talloc context to work on
193  * const char *state_flags      State flag string
194  * int len                      length of the data block
195  */
196 static char *smb_traffic_analyzer_create_header( TALLOC_CTX *ctx,
197         const char *state_flags, size_t data_len)
198 {
199         char *header = talloc_asprintf( ctx, "V2.%s%017u",
200                                         state_flags, (unsigned int) data_len);
201         DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created Header:\n"));
202         dump_data(10, (uint8_t *)header, strlen(header));
203         return header;
204 }
205
206
207 /**
208  * Actually send header and data over the network
209  * char *header         Header data
210  * char *data           Data Block
211  * int dlength          Length of data block
212  * int socket
213  */
214 static void smb_traffic_analyzer_write_data( char *header, char *data,
215                         int dlength, int _socket)
216 {
217                 int len = strlen(header);
218                 if (write_data( _socket, header, len) != len) {
219                         DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
220                                                 "error sending the header"
221                                                 " over the socket!\n"));
222                 }
223                 DEBUG(10,("smb_traffic_analyzer_write_data: sending data:\n"));
224                 dump_data( 10, (uint8_t *)data, dlength);
225
226                 if (write_data( _socket, data, dlength) != dlength) {
227                         DEBUG(1, ("smb_traffic_analyzer_write_data: "
228                                 "error sending crypted data to socket!\n"));
229                 }
230 }
231
232
233 /*
234  * Anonymize a string if required.
235  * TALLOC_CTX *ctx                      The talloc context to work on
236  * const char *str                      The string to anonymize
237  * vfs_handle_struct *handle            The handle struct to work on
238  *
239  * Returns a newly allocated string, either the anonymized one,
240  * or a copy of const char *str. The caller has to take care for
241  * freeing the allocated memory.
242  */
243 static char *smb_traffic_analyzer_anonymize( TALLOC_CTX *ctx,
244                                         const char *str,
245                                         vfs_handle_struct *handle )
246 {
247         const char *total_anonymization;
248         const char *anon_prefix;
249         char *output;
250         total_anonymization=lp_parm_const_string(SNUM(handle->conn),
251                                         "smb_traffic_analyzer",
252                                         "total_anonymization", NULL);
253
254         anon_prefix=lp_parm_const_string(SNUM(handle->conn),
255                                         "smb_traffic_analyzer",
256                                         "anonymize_prefix", NULL );
257         if (anon_prefix != NULL) {
258                 if (total_anonymization != NULL) {
259                         output = talloc_asprintf(ctx, "%s",
260                                         anon_prefix);
261                 } else {
262                 output = talloc_asprintf(ctx, "%s%i", anon_prefix,
263                                                 str_checksum(str));
264                 }
265         } else {
266                 output = talloc_asprintf(ctx, "%s", str);
267         }
268
269         return output;
270 }
271
272
273 /**
274  * The marshalling function for protocol v2.
275  * TALLOC_CTX *ctx              Talloc context to work on
276  * struct tm *tm                tm struct for the timestamp
277  * int seconds                  milliseconds of the timestamp
278  * vfs_handle_struct *handle    vfs_handle_struct
279  * char *username               Name of the user
280  * int vfs_operation            VFS operation identifier
281  * int count                    Number of the common data blocks
282  * [...] variable args          data blocks taken from the individual
283  *                              VFS data structures
284  *
285  * Returns the complete data block to send. The caller has to
286  * take care for freeing the allocated buffer.
287  */
288 static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
289         struct tm *tm, int seconds, vfs_handle_struct *handle, \
290         char *username, int vfs_operation, int count, ... )
291 {
292         
293         va_list ap;
294         char *arg = NULL;
295         int len;
296         char *common_data_count_str = NULL;
297         char *timestr = NULL;
298         char *sidstr = NULL;
299         char *usersid = NULL;
300         char *buf = NULL;
301         char *vfs_operation_str = NULL;
302         const char *service_name = lp_const_servicename(handle->conn->params->service);
303
304         /*
305          * first create the data that is transfered with any VFS op
306          * These are, in the following order:
307          *(0) number of data to come [6 in v2.0]
308          * 1.vfs_operation identifier
309          * 2.username
310          * 3.user-SID
311          * 4.affected share
312          * 5.domain
313          * 6.timestamp
314          */
315
316         /*
317          * number of common data blocks to come,
318          * this is a #define in vfs_smb_traffic_anaylzer.h,
319          * it's length is known at compile time
320          */
321         common_data_count_str = talloc_strdup( ctx, SMBTA_COMMON_DATA_COUNT);
322         /* vfs operation identifier */
323         vfs_operation_str = talloc_asprintf( common_data_count_str, "%i",
324                                                         vfs_operation);
325         /*
326          * Handle anonymization. In protocol v2, we have to anonymize
327          * both the SID and the username. The name is already
328          * anonymized if needed, by the calling function.
329          */
330         usersid = dom_sid_string( common_data_count_str,
331                 &handle->conn->server_info->ptok->user_sids[0]);
332
333         sidstr = smb_traffic_analyzer_anonymize(
334                 common_data_count_str,
335                 usersid,
336                 handle);
337         
338         /* time stamp */
339         timestr = talloc_asprintf( common_data_count_str, \
340                 "%04d-%02d-%02d %02d:%02d:%02d.%03d", \
341                 tm->tm_year+1900, \
342                 tm->tm_mon+1, \
343                 tm->tm_mday, \
344                 tm->tm_hour, \
345                 tm->tm_min, \
346                 tm->tm_sec, \
347                 (int)seconds);
348         len = strlen( timestr );
349
350         /* create the string of common data */
351         buf = talloc_asprintf(ctx,
352                 "%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s",
353                 common_data_count_str,
354                 (unsigned int) strlen(vfs_operation_str),
355                 vfs_operation_str,
356                 (unsigned int) strlen(username),
357                 username,
358                 (unsigned int) strlen(sidstr),
359                 sidstr,
360                 (unsigned int) strlen(service_name),
361                 service_name,
362                 (unsigned int)
363                 strlen(handle->conn->server_info->info3->base.domain.string),
364                 handle->conn->server_info->info3->base.domain.string,
365                 (unsigned int) strlen(timestr),
366                 timestr);
367
368         talloc_free(common_data_count_str);
369
370         /* data blocks depending on the VFS function */ 
371         va_start( ap, count );
372         while ( count-- ) {
373                 arg = va_arg( ap, char * );
374                 /*
375                  *  protocol v2 sends a four byte string
376                  * as a header to each block, including
377                  * the numbers of bytes to come in the
378                  * next string.
379                  */
380                 len = strlen( arg );
381                 buf = talloc_asprintf_append( buf, "%04u%s", len, arg);
382         }
383         va_end( ap );
384         return buf;
385 }
386
387 static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
388                                         void *data,
389                                         enum vfs_id vfs_operation )
390 {
391         struct refcounted_sock *rf_sock = NULL;
392         struct timeval tv;
393         time_t tv_sec;
394         struct tm *tm = NULL;
395         int seconds;
396         char *str = NULL;
397         char *username = NULL;
398         char *header = NULL;
399         const char *protocol_version = NULL;
400         bool Write = false;
401         size_t len;
402         size_t size;
403         char *akey, *output;
404
405         /*
406          * The state flags are part of the header
407          * and are descripted in the protocol description
408          * in vfs_smb_traffic_analyzer.h. They begin at byte
409          * 03 of the header.
410          */
411         char state_flags[9] = "000000\0";
412
413         SMB_VFS_HANDLE_GET_DATA(handle, rf_sock, struct refcounted_sock, return);
414
415         if (rf_sock == NULL || rf_sock->sock == -1) {
416                 DEBUG(1, ("smb_traffic_analyzer_send_data: socket is "
417                         "closed\n"));
418                 return;
419         }
420
421         GetTimeOfDay(&tv);
422         tv_sec = convert_timespec_to_time_t(convert_timeval_to_timespec(tv));
423         tm = localtime(&tv_sec);
424         if (!tm) {
425                 return;
426         }
427         seconds=(float) (tv.tv_usec / 1000);
428
429         /*
430          * Check if anonymization is required, and if yes do this only for
431          * the username here, needed vor protocol version 1. In v2 we
432          * additionally anonymize the SID, which is done in it's marshalling
433          * function.
434          */
435         username = smb_traffic_analyzer_anonymize( talloc_tos(),
436                         handle->conn->server_info->sanitized_username,
437                         handle);
438
439         if (!username) {
440                 return;
441         }
442
443         protocol_version = lp_parm_const_string(SNUM(handle->conn),
444                                         "smb_traffic_analyzer",
445                                         "protocol_version", NULL );
446
447
448         if ( protocol_version == NULL || strcmp( protocol_version,"V1") == 0) {
449
450                 struct rw_data *s_data = (struct rw_data *) data;
451
452                 /*
453                  * in case of protocol v1, ignore any vfs operations
454                  * except read,pread,write,pwrite, and set the "Write"
455                  * bool accordingly, send data and return.
456                  */
457                 if ( vfs_operation > vfs_id_pwrite ) return;
458
459                 if ( vfs_operation <= vfs_id_pread ) Write=false;
460                         else Write=true;
461
462                 str = talloc_asprintf(talloc_tos(),
463                         "V1,%u,\"%s\",\"%s\",\"%c\",\"%s\",\"%s\","
464                         "\"%04d-%02d-%02d %02d:%02d:%02d.%03d\"\n",
465                         (unsigned int) s_data->len,
466                         username,
467                         handle->conn->server_info->info3->base.domain.string,
468                         Write ? 'W' : 'R',
469                         handle->conn->connectpath,
470                         s_data->filename,
471                         tm->tm_year+1900,
472                         tm->tm_mon+1,
473                         tm->tm_mday,
474                         tm->tm_hour,
475                         tm->tm_min,
476                         tm->tm_sec,
477                         (int)seconds);
478                 len = strlen(str);
479                 if (write_data(rf_sock->sock, str, len) != len) {
480                         DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
481                         "error sending V1 protocol data to socket!\n"));
482                 return;
483                 }
484
485         } else if ( strcmp( protocol_version, "V2") == 0) {
486
487                 switch( vfs_operation ) {
488                 case vfs_id_open: ;
489                         str = smb_traffic_analyzer_create_string( talloc_tos(),
490                                 tm, seconds, handle, username, vfs_id_open,
491                                 3, ((struct open_data *) data)->filename,
492                                 talloc_asprintf( talloc_tos(), "%u",
493                                 ((struct open_data *) data)->mode),
494                                 talloc_asprintf( talloc_tos(), "%u",
495                                 ((struct open_data *) data)->result));
496                         break;
497                 case vfs_id_close: ;
498                         str = smb_traffic_analyzer_create_string( talloc_tos(),
499                                 tm, seconds, handle, username, vfs_id_close,
500                                 2, ((struct close_data *) data)->filename,
501                                 talloc_asprintf( talloc_tos(), "%u",
502                                 ((struct close_data *) data)->result));
503                         break;
504                 case vfs_id_mkdir: ;
505                         str = smb_traffic_analyzer_create_string( talloc_tos(),
506                                 tm, seconds, handle, username, vfs_id_mkdir, \
507                                 3, ((struct mkdir_data *) data)->path, \
508                                 talloc_asprintf( talloc_tos(), "%u", \
509                                 ((struct mkdir_data *) data)->mode), \
510                                 talloc_asprintf( talloc_tos(), "%u", \
511                                 ((struct mkdir_data *) data)->result ));
512                         break;
513                 case vfs_id_rmdir: ;
514                         str = smb_traffic_analyzer_create_string( talloc_tos(),
515                                 tm, seconds, handle, username, vfs_id_rmdir,
516                                 2, ((struct rmdir_data *) data)->path, \
517                                 talloc_asprintf( talloc_tos(), "%u", \
518                                 ((struct rmdir_data *) data)->result ));
519                         break;
520                 case vfs_id_rename: ;
521                         str = smb_traffic_analyzer_create_string( talloc_tos(),
522                                 tm, seconds, handle, username, vfs_id_rename,
523                                 3, ((struct rename_data *) data)->src, \
524                                 ((struct rename_data *) data)->dst,
525                                 talloc_asprintf(talloc_tos(), "%u", \
526                                 ((struct rename_data *) data)->result));
527                         break;
528                 case vfs_id_chdir: ;
529                         str = smb_traffic_analyzer_create_string( talloc_tos(),
530                                 tm, seconds, handle, username, vfs_id_chdir,
531                                 2, ((struct chdir_data *) data)->path, \
532                                 talloc_asprintf(talloc_tos(), "%u", \
533                                 ((struct chdir_data *) data)->result));
534                         break;
535
536                 case vfs_id_write:
537                 case vfs_id_pwrite:
538                 case vfs_id_read:
539                 case vfs_id_pread: ;
540                         str = smb_traffic_analyzer_create_string( talloc_tos(),
541                                 tm, seconds, handle, username, vfs_operation,
542                                 2, ((struct rw_data *) data)->filename, \
543                                 talloc_asprintf(talloc_tos(), "%u", \
544                                 (unsigned int)
545                                         ((struct rw_data *) data)->len));
546                         break;
547                 default:
548                         DEBUG(1, ("smb_traffic_analyzer: error! "
549                                 "wrong VFS operation id detected!\n"));
550                         return;
551                 }
552
553         } else {
554                 DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
555                         "error, unkown protocol given!\n"));
556                 return;
557         }
558
559         if (!str) {
560                 DEBUG(1, ("smb_traffic_analyzer_send_data: "
561                         "unable to create string to send!\n"));
562                 return;
563         }
564
565
566         /*
567          * If configured, optain the key and run AES encryption
568          * over the data.
569          */
570         become_root();
571         akey = (char *) secrets_fetch("smb_traffic_analyzer_key", &size);
572         unbecome_root();
573         if ( akey != NULL ) {
574                 state_flags[2] = 'E';
575                 DEBUG(10, ("smb_traffic_analyzer_send_data_socket: a key was"
576                         " found, encrypting data!\n"));
577                 output = smb_traffic_analyzer_encrypt( talloc_tos(),
578                                                 akey, str, &len);
579                 header = smb_traffic_analyzer_create_header( talloc_tos(),
580                                                 state_flags, len);
581
582                 DEBUG(10, ("smb_traffic_analyzer_send_data_socket:"
583                         " header created for crypted data: %s\n", header));
584                 smb_traffic_analyzer_write_data(header, output, len,
585                                                         rf_sock->sock);
586                 return;
587
588         }
589
590         len = strlen(str);
591         header = smb_traffic_analyzer_create_header( talloc_tos(),
592                                 state_flags, len);
593         smb_traffic_analyzer_write_data(header, str, strlen(str),
594                                 rf_sock->sock);
595
596 }
597
598 static struct refcounted_sock *sock_list;
599
600 static void smb_traffic_analyzer_free_data(void **pptr)
601 {
602         struct refcounted_sock *rf_sock = *(struct refcounted_sock **)pptr;
603         if (rf_sock == NULL) {
604                 return;
605         }
606         rf_sock->ref_count--;
607         if (rf_sock->ref_count != 0) {
608                 return;
609         }
610         if (rf_sock->sock != -1) {
611                 close(rf_sock->sock);
612         }
613         DLIST_REMOVE(sock_list, rf_sock);
614         TALLOC_FREE(rf_sock);
615 }
616
617 static int smb_traffic_analyzer_connect(struct vfs_handle_struct *handle,
618                          const char *service,
619                          const char *user)
620 {
621         connection_struct *conn = handle->conn;
622         enum sock_type st = smb_traffic_analyzer_connMode(handle);
623         struct refcounted_sock *rf_sock = NULL;
624         const char *name = (st == UNIX_DOMAIN_SOCKET) ? LOCAL_PATHNAME :
625                                 lp_parm_const_string(SNUM(conn),
626                                         "smb_traffic_analyzer",
627                                 "host", "localhost");
628         uint16_t port = (st == UNIX_DOMAIN_SOCKET) ? 0 :
629                                 atoi( lp_parm_const_string(SNUM(conn),
630                                 "smb_traffic_analyzer", "port", "9430"));
631         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
632
633         if (ret < 0) {
634                 return ret;
635         }
636
637         /* Are we already connected ? */
638         for (rf_sock = sock_list; rf_sock; rf_sock = rf_sock->next) {
639                 if (port == rf_sock->port &&
640                                 (strcmp(name, rf_sock->name) == 0)) {
641                         break;
642                 }
643         }
644
645         /* If we're connected already, just increase the
646          * reference count. */
647         if (rf_sock) {
648                 rf_sock->ref_count++;
649         } else {
650                 /* New connection. */
651                 rf_sock = TALLOC_ZERO_P(NULL, struct refcounted_sock);
652                 if (rf_sock == NULL) {
653                         SMB_VFS_NEXT_DISCONNECT(handle);
654                         errno = ENOMEM;
655                         return -1;
656                 }
657                 rf_sock->name = talloc_strdup(rf_sock, name);
658                 if (rf_sock->name == NULL) {
659                         SMB_VFS_NEXT_DISCONNECT(handle);
660                         TALLOC_FREE(rf_sock);
661                         errno = ENOMEM;
662                         return -1;
663                 }
664                 rf_sock->port = port;
665                 rf_sock->ref_count = 1;
666
667                 if (st == UNIX_DOMAIN_SOCKET) {
668                         rf_sock->sock = smb_traffic_analyzer_connect_unix_socket(handle,
669                                                         name);
670                 } else {
671
672                         rf_sock->sock = smb_traffic_analyzer_connect_inet_socket(handle,
673                                                         name,
674                                                         port);
675                 }
676                 if (rf_sock->sock == -1) {
677                         SMB_VFS_NEXT_DISCONNECT(handle);
678                         TALLOC_FREE(rf_sock);
679                         return -1;
680                 }
681                 DLIST_ADD(sock_list, rf_sock);
682         }
683
684         /* Store the private data. */
685         SMB_VFS_HANDLE_SET_DATA(handle, rf_sock, smb_traffic_analyzer_free_data,
686                                 struct refcounted_sock, return -1);
687         return 0;
688 }
689
690 /* VFS Functions */
691 static int smb_traffic_analyzer_chdir(vfs_handle_struct *handle, \
692                         const char *path)
693 {
694         struct chdir_data s_data;
695         s_data.result = SMB_VFS_NEXT_CHDIR(handle, path);
696         s_data.path = path;
697         DEBUG(10, ("smb_traffic_analyzer_chdir: CHDIR: %s\n", path));
698         smb_traffic_analyzer_send_data(handle, &s_data, vfs_id_chdir);
699         return s_data.result;
700 }
701
702 static int smb_traffic_analyzer_rename(vfs_handle_struct *handle, \
703                 const struct smb_filename *smb_fname_src,
704                 const struct smb_filename *smb_fname_dst)
705 {
706         struct rename_data s_data;
707         s_data.result = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, \
708                 smb_fname_dst);
709         s_data.src = smb_fname_src->base_name;
710         s_data.dst = smb_fname_dst->base_name;
711         DEBUG(10, ("smb_traffic_analyzer_rename: RENAME: %s / %s\n",
712                 smb_fname_src->base_name,
713                 smb_fname_dst->base_name));
714         smb_traffic_analyzer_send_data(handle, &s_data, vfs_id_rename);
715         return s_data.result;
716 }
717
718 static int smb_traffic_analyzer_rmdir(vfs_handle_struct *handle, \
719                         const char *path)
720 {
721         struct rmdir_data s_data;
722         s_data.result = SMB_VFS_NEXT_RMDIR(handle, path);
723         s_data.path = path;
724         DEBUG(10, ("smb_traffic_analyzer_rmdir: RMDIR: %s\n", path));
725         smb_traffic_analyzer_send_data(handle, &s_data, vfs_id_rmdir);
726         return s_data.result;
727 }
728
729 static int smb_traffic_analyzer_mkdir(vfs_handle_struct *handle, \
730                         const char *path, mode_t mode)
731 {
732         struct mkdir_data s_data;
733         s_data.result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
734         s_data.path = path;
735         s_data.mode = mode;
736         DEBUG(10, ("smb_traffic_analyzer_mkdir: MKDIR: %s\n", path));
737         smb_traffic_analyzer_send_data(handle,
738                         &s_data,
739                         vfs_id_mkdir);
740         return s_data.result;
741 }
742
743 static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \
744                                 files_struct *fsp, void *data, size_t n)
745 {
746         struct rw_data s_data;
747
748         s_data.len = SMB_VFS_NEXT_READ(handle, fsp, data, n);
749         s_data.filename = fsp->fsp_name->base_name;
750         DEBUG(10, ("smb_traffic_analyzer_read: READ: %s\n", fsp_str_dbg(fsp)));
751
752         smb_traffic_analyzer_send_data(handle,
753                         &s_data,
754                         vfs_id_read);
755         return s_data.len;
756 }
757
758
759 static ssize_t smb_traffic_analyzer_pread(vfs_handle_struct *handle, \
760                 files_struct *fsp, void *data, size_t n, SMB_OFF_T offset)
761 {
762         struct rw_data s_data;
763
764         s_data.len = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
765         s_data.filename = fsp->fsp_name->base_name;
766         DEBUG(10, ("smb_traffic_analyzer_pread: PREAD: %s\n",
767                    fsp_str_dbg(fsp)));
768
769         smb_traffic_analyzer_send_data(handle,
770                         &s_data,
771                         vfs_id_pread);
772
773         return s_data.len;
774 }
775
776 static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle, \
777                         files_struct *fsp, const void *data, size_t n)
778 {
779         struct rw_data s_data;
780
781         s_data.len = SMB_VFS_NEXT_WRITE(handle, fsp, data, n);
782         s_data.filename = fsp->fsp_name->base_name;
783         DEBUG(10, ("smb_traffic_analyzer_write: WRITE: %s\n",
784                    fsp_str_dbg(fsp)));
785
786         smb_traffic_analyzer_send_data(handle,
787                         &s_data,
788                         vfs_id_write);
789         return s_data.len;
790 }
791
792 static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \
793              files_struct *fsp, const void *data, size_t n, SMB_OFF_T offset)
794 {
795         struct rw_data s_data;
796
797         s_data.len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
798         s_data.filename = fsp->fsp_name->base_name;
799         DEBUG(10, ("smb_traffic_analyzer_pwrite: PWRITE: %s\n", \
800                 fsp_str_dbg(fsp)));
801
802         smb_traffic_analyzer_send_data(handle,
803                         &s_data,
804                         vfs_id_pwrite);
805         return s_data.len;
806 }
807
808 static int smb_traffic_analyzer_open(vfs_handle_struct *handle, \
809         struct smb_filename *smb_fname, files_struct *fsp,\
810         int flags, mode_t mode)
811 {
812         struct open_data s_data;
813
814         s_data.result = SMB_VFS_NEXT_OPEN( handle, smb_fname, fsp,
815                         flags, mode);
816         DEBUG(10,("smb_traffic_analyzer_open: OPEN: %s\n",
817                 fsp_str_dbg(fsp)));
818         s_data.filename = fsp->fsp_name->base_name;
819         s_data.mode = mode;
820         smb_traffic_analyzer_send_data(handle,
821                         &s_data,
822                         vfs_id_open);
823         return s_data.result;
824 }
825
826 static int smb_traffic_analyzer_close(vfs_handle_struct *handle, \
827         files_struct *fsp)
828 {
829         struct close_data s_data;
830         s_data.result = SMB_VFS_NEXT_CLOSE(handle, fsp);
831         DEBUG(10,("smb_traffic_analyzer_close: CLOSE: %s\n",
832                 fsp_str_dbg(fsp)));
833         s_data.filename = fsp->fsp_name->base_name;
834         smb_traffic_analyzer_send_data(handle,
835                         &s_data,
836                         vfs_id_close);
837         return s_data.result;
838 }
839
840         
841 static struct vfs_fn_pointers vfs_smb_traffic_analyzer_fns = {
842         .connect_fn = smb_traffic_analyzer_connect,
843         .vfs_read = smb_traffic_analyzer_read,
844         .pread = smb_traffic_analyzer_pread,
845         .write = smb_traffic_analyzer_write,
846         .pwrite = smb_traffic_analyzer_pwrite,
847         .mkdir = smb_traffic_analyzer_mkdir,
848         .rename = smb_traffic_analyzer_rename,
849         .chdir = smb_traffic_analyzer_chdir,
850         .open = smb_traffic_analyzer_open,
851         .rmdir = smb_traffic_analyzer_rmdir,
852         .close_fn = smb_traffic_analyzer_close
853 };
854
855 /* Module initialization */
856 NTSTATUS vfs_smb_traffic_analyzer_init(void)
857 {
858         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
859                                         "smb_traffic_analyzer",
860                                         &vfs_smb_traffic_analyzer_fns);
861
862         if (!NT_STATUS_IS_OK(ret)) {
863                 return ret;
864         }
865
866         vfs_smb_traffic_analyzer_debug_level =
867                 debug_add_class("smb_traffic_analyzer");
868
869         if (vfs_smb_traffic_analyzer_debug_level == -1) {
870                 vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
871                 DEBUG(1, ("smb_traffic_analyzer_init: Couldn't register custom"
872                          "debugging class!\n"));
873         } else {
874                 DEBUG(3, ("smb_traffic_analyzer_init: Debug class number of"
875                         "'smb_traffic_analyzer': %d\n", \
876                         vfs_smb_traffic_analyzer_debug_level));
877         }
878
879         return ret;
880 }