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