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