2008-09-25 03:01:00 +04:00
/*
* traffic - analyzer VFS module . Measure the smb traffic users create
* on the net .
*
* Copyright ( C ) Holger Hetterich , 2008
2008-10-01 23:50:29 +04:00
* Copyright ( C ) Jeremy Allison , 2008
2008-09-25 03:01:00 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2009-12-14 22:43:15 +03:00
# include "../lib/crypto/crypto.h"
2008-09-25 03:01:00 +04:00
/* abstraction for the send_over_network function */
2008-10-01 23:50:29 +04:00
enum sock_type { INTERNET_SOCKET = 0 , UNIX_DOMAIN_SOCKET } ;
# define LOCAL_PATHNAME " / var / tmp / stadsocket"
2008-09-25 03:01:00 +04:00
2009-09-17 22:11:39 +04:00
/* VFS Functions identifier table. In protocol version 2, every vfs */
/* function is given a unique id. */
enum vfs_id {
/* care for the order here, required for compatibility */
/* with protocol version 1. */
vfs_id_read ,
vfs_id_pread ,
vfs_id_write ,
vfs_id_pwrite ,
/* end of protocol version 1 identifiers. */
2009-12-11 23:04:46 +03:00
vfs_id_mkdir ,
vfs_id_rmdir ,
vfs_id_rename ,
vfs_id_chdir
2009-09-17 22:11:39 +04:00
} ;
2009-09-21 17:33:21 +04:00
/* Specific data sets for the VFS functions. */
2010-01-22 01:16:58 +03:00
struct mkdir_data {
2009-09-21 17:33:21 +04:00
const char * path ;
mode_t mode ;
int result ;
2010-01-22 01:16:58 +03:00
} ;
2009-12-11 23:04:46 +03:00
2010-01-22 01:16:58 +03:00
struct rmdir_data {
2009-12-11 23:04:46 +03:00
const char * path ;
int result ;
2010-01-22 01:16:58 +03:00
} ;
2009-12-11 23:04:46 +03:00
2010-01-22 01:16:58 +03:00
struct rename_data {
2009-12-11 23:04:46 +03:00
const char * src ;
const char * dst ;
int result ;
2010-01-22 01:16:58 +03:00
} ;
2009-12-11 23:04:46 +03:00
2010-01-22 01:16:58 +03:00
struct chdir_data {
2009-12-11 23:04:46 +03:00
const char * path ;
int result ;
2010-01-22 01:16:58 +03:00
} ;
2010-01-22 00:31:09 +03:00
2009-09-21 17:33:21 +04:00
/* rw_data used for read/write/pread/pwrite */
2010-01-22 01:16:58 +03:00
struct rw_data {
2009-09-21 17:33:21 +04:00
char * filename ;
size_t len ;
2010-01-22 01:16:58 +03:00
} ;
2009-09-21 17:33:21 +04:00
2008-09-25 03:01:00 +04:00
static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS ;
2008-10-01 23:50:29 +04:00
static enum sock_type smb_traffic_analyzer_connMode ( vfs_handle_struct * handle )
2008-09-25 03:01:00 +04:00
{
connection_struct * conn = handle - > conn ;
const char * Mode ;
Mode = lp_parm_const_string ( SNUM ( conn ) , " smb_traffic_analyzer " , " mode " , \
" internet_socket " ) ;
if ( strstr ( Mode , " unix_domain_socket " ) ) {
return UNIX_DOMAIN_SOCKET ;
} else {
return INTERNET_SOCKET ;
}
}
2008-10-14 01:08:49 +04:00
2008-10-01 02:13:19 +04:00
/* Connect to an internet socket */
2008-10-01 23:50:29 +04:00
static int smb_traffic_analyzer_connect_inet_socket ( vfs_handle_struct * handle ,
const char * name , uint16_t port )
2008-09-25 03:01:00 +04:00
{
2008-09-25 23:02:22 +04:00
/* Create a streaming Socket */
int sockfd = - 1 ;
struct addrinfo hints ;
struct addrinfo * ailist = NULL ;
struct addrinfo * res = NULL ;
int ret ;
2008-09-25 03:01:00 +04:00
2008-09-25 23:02:22 +04:00
ZERO_STRUCT ( hints ) ;
/* By default make sure it supports TCP. */
hints . ai_socktype = SOCK_STREAM ;
hints . ai_flags = AI_ADDRCONFIG ;
2008-10-01 23:50:29 +04:00
ret = getaddrinfo ( name ,
2008-09-25 23:02:22 +04:00
NULL ,
& hints ,
& ailist ) ;
if ( ret ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 3 , ( " smb_traffic_analyzer_connect_inet_socket: "
2008-09-25 23:02:22 +04:00
" getaddrinfo failed for name %s [%s] \n " ,
2008-10-01 23:50:29 +04:00
name ,
2008-09-25 23:02:22 +04:00
gai_strerror ( ret ) ) ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
2008-09-25 23:02:22 +04:00
}
2008-09-25 03:01:00 +04:00
DEBUG ( 3 , ( " smb_traffic_analyzer: Internet socket mode. Hostname: %s, "
2008-10-01 23:50:29 +04:00
" Port: %i \n " , name , port ) ) ;
2008-09-25 03:01:00 +04:00
2008-09-25 23:02:22 +04:00
for ( res = ailist ; res ; res = res - > ai_next ) {
struct sockaddr_storage ss ;
2009-01-03 21:50:05 +03:00
NTSTATUS status ;
2008-09-25 23:02:22 +04:00
if ( ! res - > ai_addr | | res - > ai_addrlen = = 0 ) {
continue ;
}
ZERO_STRUCT ( ss ) ;
memcpy ( & ss , res - > ai_addr , res - > ai_addrlen ) ;
2009-01-03 21:50:05 +03:00
status = open_socket_out ( & ss , port , 10000 , & sockfd ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-09-25 23:02:22 +04:00
break ;
}
}
if ( ailist ) {
freeaddrinfo ( ailist ) ;
}
if ( sockfd = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer: unable to create "
" socket, error is %s " ,
2008-09-25 23:02:22 +04:00
strerror ( errno ) ) ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
2008-09-25 03:01:00 +04:00
}
2008-09-25 23:02:22 +04:00
2008-10-01 02:13:19 +04:00
return sockfd ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
/* Connect to a unix domain socket */
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
static int smb_traffic_analyzer_connect_unix_socket ( vfs_handle_struct * handle ,
const char * name )
2008-09-25 03:01:00 +04:00
{
/* Create the socket to stad */
int len , sock ;
struct sockaddr_un remote ;
2008-09-25 23:02:22 +04:00
2008-10-01 02:13:19 +04:00
DEBUG ( 7 , ( " smb_traffic_analyzer_connect_unix_socket: "
2008-10-01 23:50:29 +04:00
" Unix domain socket mode. Using %s \n " ,
name ) ) ;
2008-09-25 23:02:22 +04:00
2008-09-25 03:01:00 +04:00
if ( ( sock = socket ( AF_UNIX , SOCK_STREAM , 0 ) ) = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_connect_unix_socket: "
" Couldn't create socket, "
2008-09-25 03:01:00 +04:00
" make sure stad is running! \n " ) ) ;
2008-10-30 02:43:19 +03:00
return - 1 ;
2008-09-25 03:01:00 +04:00
}
remote . sun_family = AF_UNIX ;
2008-10-01 23:50:29 +04:00
strlcpy ( remote . sun_path , name ,
2008-09-25 23:02:22 +04:00
sizeof ( remote . sun_path ) ) ;
2008-09-25 03:01:00 +04:00
len = strlen ( remote . sun_path ) + sizeof ( remote . sun_family ) ;
if ( connect ( sock , ( struct sockaddr * ) & remote , len ) = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_connect_unix_socket: "
" Could not connect to "
2008-09-25 03:01:00 +04:00
" socket, make sure \n stad is running! \n " ) ) ;
2008-09-25 23:02:22 +04:00
close ( sock ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
}
return sock ;
}
2009-09-22 22:01:35 +04:00
/* Private data allowing shared connection sockets. */
2008-10-01 23:50:29 +04:00
struct refcounted_sock {
struct refcounted_sock * next , * prev ;
char * name ;
uint16_t port ;
int sock ;
unsigned int ref_count ;
} ;
2009-09-22 22:01:35 +04:00
/* The marshaller for the protocol version 2. */
static char * smb_traffic_analyzer_create_string ( struct tm * tm , \
int seconds , vfs_handle_struct * handle , \
2010-01-22 15:04:21 +03:00
char * username , int vfs_operation , int count , . . . )
2009-09-22 22:01:35 +04:00
{
va_list ap ;
char * arg = NULL ;
char * str = NULL ;
int len ;
char * header = NULL ;
char * buf = NULL ;
char * timestr = NULL ;
2010-01-22 15:04:21 +03:00
char * opstr = NULL ;
2010-01-22 16:55:33 +03:00
char * userSID = NULL ;
2009-09-22 22:01:35 +04:00
/* first create the data that is transfered with any VFS op */
2010-01-22 15:04:21 +03:00
opstr = talloc_asprintf ( talloc_tos ( ) , " %i " , vfs_operation ) ;
len = strlen ( opstr ) ;
buf = talloc_asprintf ( talloc_tos ( ) , " %04u%s " , len , opstr ) ;
2009-09-22 22:01:35 +04:00
len = strlen ( username ) ;
2010-01-22 15:04:21 +03:00
buf = talloc_asprintf_append ( buf , " %04u%s " , len , username ) ;
2010-01-22 16:55:33 +03:00
userSID = dom_sid_string ( talloc_tos ( ) ,
& handle - > conn - > server_info - > ptok - > user_sids [ 0 ] ) ;
len = strlen ( userSID ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , userSID ) ;
2009-09-22 22:01:35 +04:00
len = strlen ( handle - > conn - > connectpath ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , \
handle - > conn - > connectpath ) ;
len = strlen ( pdb_get_domain ( handle - > conn - > server_info - > sam_account ) ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , \
pdb_get_domain ( handle - > conn - > server_info - > sam_account ) ) ;
timestr = talloc_asprintf ( talloc_tos ( ) , \
" %04d-%02d-%02d %02d:%02d:%02d.%03d " , \
tm - > tm_year + 1900 , \
tm - > tm_mon + 1 , \
tm - > tm_mday , \
tm - > tm_hour , \
tm - > tm_min , \
tm - > tm_sec , \
( int ) seconds ) ;
len = strlen ( timestr ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , timestr ) ;
va_start ( ap , count ) ;
while ( count - - ) {
arg = va_arg ( ap , char * ) ;
/* protocol v2 sends a four byte string */
/* as a header to each block, including */
/* the numbers of bytes to come in the */
/* next string. */
len = strlen ( arg ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , arg ) ;
}
va_end ( ap ) ;
/* now create the protocol v2 header. */
len = strlen ( buf ) ;
str = talloc_asprintf_append ( str , " V2,%017u%s " , len , buf ) ;
DEBUG ( 10 , ( " smb_traffic_analyzer_create_string: %s \n " , str ) ) ;
return str ;
}
2008-10-01 02:13:19 +04:00
static void smb_traffic_analyzer_send_data ( vfs_handle_struct * handle ,
2009-09-21 17:33:21 +04:00
void * data ,
2009-09-17 22:11:39 +04:00
enum vfs_id vfs_operation )
2008-10-01 02:13:19 +04:00
{
2008-10-01 23:50:29 +04:00
struct refcounted_sock * rf_sock = NULL ;
2008-10-01 03:19:37 +04:00
struct timeval tv ;
2008-10-07 04:09:48 +04:00
time_t tv_sec ;
2008-10-01 03:19:37 +04:00
struct tm * tm = NULL ;
int seconds ;
char * str = NULL ;
2008-10-14 01:08:49 +04:00
char * username = NULL ;
const char * anon_prefix = NULL ;
2009-02-04 17:31:24 +03:00
const char * total_anonymization = NULL ;
2009-09-17 22:11:39 +04:00
const char * protocol_version = NULL ;
bool Write = false ;
2008-10-01 03:19:37 +04:00
size_t len ;
2008-10-01 02:13:19 +04:00
2008-10-01 23:50:29 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , rf_sock , struct refcounted_sock , return ) ;
2008-10-01 02:13:19 +04:00
2008-10-01 23:50:29 +04:00
if ( rf_sock = = NULL | | rf_sock - > sock = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data: socket is "
" closed \n " ) ) ;
2008-09-25 23:02:22 +04:00
return ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
2008-10-01 03:19:37 +04:00
GetTimeOfDay ( & tv ) ;
2008-10-07 04:09:48 +04:00
tv_sec = convert_timespec_to_time_t ( convert_timeval_to_timespec ( tv ) ) ;
tm = localtime ( & tv_sec ) ;
2008-10-01 03:19:37 +04:00
if ( ! tm ) {
return ;
}
seconds = ( float ) ( tv . tv_usec / 1000 ) ;
2008-10-14 01:08:49 +04:00
/* check if anonymization is required */
2008-10-14 01:12:43 +04:00
2009-02-04 17:31:24 +03:00
total_anonymization = lp_parm_const_string ( SNUM ( handle - > conn ) , " smb_traffic_analyzer " ,
" total_anonymization " , NULL ) ;
2008-10-14 01:08:49 +04:00
anon_prefix = lp_parm_const_string ( SNUM ( handle - > conn ) , " smb_traffic_analyzer " , \
" anonymize_prefix " , NULL ) ;
if ( anon_prefix ! = NULL ) {
2009-02-04 17:31:24 +03:00
if ( total_anonymization ! = NULL ) {
username = talloc_asprintf ( talloc_tos ( ) ,
" %s " ,
anon_prefix ) ;
} else {
username = talloc_asprintf ( talloc_tos ( ) ,
" %s%i " ,
anon_prefix ,
str_checksum (
handle - > conn - > server_info - > sanitized_username ) ) ;
}
2008-10-14 01:08:49 +04:00
} else {
2008-10-14 01:12:43 +04:00
username = handle - > conn - > server_info - > sanitized_username ;
}
2008-10-14 01:08:49 +04:00
if ( ! username ) {
return ;
2008-10-14 01:12:43 +04:00
}
2009-09-17 22:11:39 +04:00
protocol_version = lp_parm_const_string ( SNUM ( handle - > conn ) ,
" smb_traffic_analyzer " ,
" protocol_version " , NULL ) ;
if ( protocol_version = = NULL | | strcmp ( protocol_version , " V1 " ) = = 0 ) {
2009-09-21 17:33:21 +04:00
struct rw_data * s_data = ( struct rw_data * ) data ;
2009-09-17 22:11:39 +04:00
/* in case of protocol v1, ignore any vfs operations */
/* except read,pread,write,pwrite, and set the "Write" */
/* bool accordingly. */
if ( vfs_operation > vfs_id_pwrite ) return ;
if ( vfs_operation < = vfs_id_pread ) Write = false ;
else Write = true ;
str = talloc_asprintf ( talloc_tos ( ) ,
2008-10-01 23:50:29 +04:00
" V1,%u, \" %s \" , \" %s \" , \" %c \" , \" %s \" , \" %s \" , "
" \" %04d-%02d-%02d %02d:%02d:%02d.%03d \" \n " ,
2009-09-21 17:33:21 +04:00
( unsigned int ) s_data - > len ,
2008-10-14 01:08:49 +04:00
username ,
2008-10-01 03:19:37 +04:00
pdb_get_domain ( handle - > conn - > server_info - > sam_account ) ,
Write ? ' W ' : ' R ' ,
handle - > conn - > connectpath ,
2009-09-21 17:33:21 +04:00
s_data - > filename ,
2008-10-01 03:19:37 +04:00
tm - > tm_year + 1900 ,
tm - > tm_mon + 1 ,
tm - > tm_mday ,
tm - > tm_hour ,
tm - > tm_min ,
tm - > tm_sec ,
( int ) seconds ) ;
2009-09-17 22:11:39 +04:00
} else if ( strcmp ( protocol_version , " V2 " ) = = 0 ) {
2009-09-22 22:01:35 +04:00
switch ( vfs_operation ) {
2010-01-22 01:26:54 +03:00
case vfs_id_mkdir : ;
str = smb_traffic_analyzer_create_string ( tm , \
2010-01-22 15:04:21 +03:00
seconds , handle , username , vfs_id_mkdir , 3 , \
2010-01-22 01:26:54 +03:00
( ( struct mkdir_data * ) data ) - > path , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct mkdir_data * ) data ) - > mode ) , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct mkdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_rmdir : ;
str = smb_traffic_analyzer_create_string ( tm , \
2010-01-22 15:04:21 +03:00
seconds , handle , username , vfs_id_rmdir , 2 , \
2010-01-22 01:26:54 +03:00
( ( struct rmdir_data * ) data ) - > path , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct rmdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_rename : ;
str = smb_traffic_analyzer_create_string ( tm , \
2010-01-22 15:04:21 +03:00
seconds , handle , username , vfs_id_rename , 3 , \
2010-01-22 01:26:54 +03:00
( ( struct rename_data * ) data ) - > src , \
( ( struct rename_data * ) data ) - > dst ,
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct rename_data * ) data ) - > result ) ) ;
break ;
case vfs_id_chdir : ;
str = smb_traffic_analyzer_create_string ( tm , \
2010-01-22 15:04:21 +03:00
seconds , handle , username , vfs_id_chdir , 2 , \
2010-01-22 01:26:54 +03:00
( ( struct chdir_data * ) data ) - > path , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct chdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_write :
case vfs_id_pwrite :
case vfs_id_read :
case vfs_id_pread : ;
str = smb_traffic_analyzer_create_string ( tm , \
2010-01-22 15:04:21 +03:00
seconds , handle , username , vfs_operation , 2 , \
2010-01-22 01:26:54 +03:00
( ( struct rw_data * ) data ) - > filename , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct rw_data * ) data ) - > len ) ) ;
break ;
default :
DEBUG ( 1 , ( " smb_traffic_analyzer: error! "
" wrong VFS operation id detected! \n " ) ) ;
return ;
2009-09-22 22:01:35 +04:00
}
2009-09-17 22:11:39 +04:00
} else {
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data_socket: "
" error, unkown protocol given! \n " ) ) ;
return ;
}
2008-10-01 03:19:37 +04:00
if ( ! str ) {
2009-09-17 22:11:39 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data: "
" unable to create string to send! \n " ) ) ;
2008-10-01 03:19:37 +04:00
return ;
}
len = strlen ( str ) ;
2009-12-14 22:43:15 +03:00
DEBUG ( 10 , ( " smb_traffic_analyzer_send_data_socket: going to send "
" %s \n " , str ) ) ;
/* If configured, optain the key and run AES encryption */
/* over the data. */
size_t size ;
char * akey = secrets_fetch ( " smb_traffic_analyzer_key " , & size ) ;
if ( akey ! = NULL ) {
char * crypted ;
DEBUG ( 10 , ( " smb_traffic_analyzer: a key was found, encrypting "
" data! " ) ) ;
AES_KEY * key ;
samba_AES_set_encrypt_key ( akey , 128 , key ) ;
samba_AES_encrypt ( str , crypted , key ) ;
len = strlen ( crypted ) ;
if ( write_data ( rf_sock - > sock , crypted , len ) ! = len ) {
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data_socket: "
" error sending crypted data to socket! \n " ) ) ;
free ( crypted ) ;
return ;
}
}
2008-10-01 23:50:29 +04:00
if ( write_data ( rf_sock - > sock , str , len ) ! = len ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data_socket: "
" error sending data to socket! \n " ) ) ;
return ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
static struct refcounted_sock * sock_list ;
2008-10-01 02:13:19 +04:00
static void smb_traffic_analyzer_free_data ( void * * pptr )
{
2008-10-01 23:50:29 +04:00
struct refcounted_sock * rf_sock = * ( struct refcounted_sock * * ) pptr ;
if ( rf_sock = = NULL ) {
2008-10-01 02:13:19 +04:00
return ;
}
2008-10-01 23:50:29 +04:00
rf_sock - > ref_count - - ;
if ( rf_sock - > ref_count ! = 0 ) {
return ;
}
if ( rf_sock - > sock ! = - 1 ) {
close ( rf_sock - > sock ) ;
2008-10-01 02:13:19 +04:00
}
2008-10-01 23:50:29 +04:00
DLIST_REMOVE ( sock_list , rf_sock ) ;
TALLOC_FREE ( rf_sock ) ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
static int smb_traffic_analyzer_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
2008-09-25 03:01:00 +04:00
{
2008-10-01 23:50:29 +04:00
connection_struct * conn = handle - > conn ;
enum sock_type st = smb_traffic_analyzer_connMode ( handle ) ;
struct refcounted_sock * rf_sock = NULL ;
const char * name = ( st = = UNIX_DOMAIN_SOCKET ) ? LOCAL_PATHNAME :
lp_parm_const_string ( SNUM ( conn ) ,
" smb_traffic_analyzer " ,
" host " , " localhost " ) ;
uint16_t port = ( st = = UNIX_DOMAIN_SOCKET ) ? 0 :
atoi ( lp_parm_const_string ( SNUM ( conn ) ,
" smb_traffic_analyzer " , " port " , " 9430 " ) ) ;
2009-12-01 02:53:04 +03:00
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
/* Are we already connected ? */
for ( rf_sock = sock_list ; rf_sock ; rf_sock = rf_sock - > next ) {
if ( port = = rf_sock - > port & &
( strcmp ( name , rf_sock - > name ) = = 0 ) ) {
break ;
}
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
/* If we're connected already, just increase the
* reference count . */
if ( rf_sock ) {
rf_sock - > ref_count + + ;
2008-10-01 02:13:19 +04:00
} else {
2008-10-01 23:50:29 +04:00
/* New connection. */
rf_sock = TALLOC_ZERO_P ( NULL , struct refcounted_sock ) ;
if ( rf_sock = = NULL ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
errno = ENOMEM ;
return - 1 ;
}
rf_sock - > name = talloc_strdup ( rf_sock , name ) ;
if ( rf_sock - > name = = NULL ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
TALLOC_FREE ( rf_sock ) ;
errno = ENOMEM ;
return - 1 ;
}
rf_sock - > port = port ;
rf_sock - > ref_count = 1 ;
if ( st = = UNIX_DOMAIN_SOCKET ) {
rf_sock - > sock = smb_traffic_analyzer_connect_unix_socket ( handle ,
name ) ;
} else {
rf_sock - > sock = smb_traffic_analyzer_connect_inet_socket ( handle ,
name ,
port ) ;
}
if ( rf_sock - > sock = = - 1 ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
TALLOC_FREE ( rf_sock ) ;
return - 1 ;
}
DLIST_ADD ( sock_list , rf_sock ) ;
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
/* Store the private data. */
2008-10-01 23:50:29 +04:00
SMB_VFS_HANDLE_SET_DATA ( handle , rf_sock , smb_traffic_analyzer_free_data ,
struct refcounted_sock , return - 1 ) ;
2009-12-01 02:53:04 +03:00
return 0 ;
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2009-09-17 22:11:39 +04:00
/* VFS Functions */
2009-12-11 23:04:46 +03:00
static int smb_traffic_analyzer_chdir ( vfs_handle_struct * handle , \
const char * path )
{
struct chdir_data s_data ;
s_data . result = SMB_VFS_NEXT_CHDIR ( handle , path ) ;
s_data . path = path ;
DEBUG ( 10 , ( " smb_traffic_analyzer_chdir: CHDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_chdir ) ;
return s_data . result ;
}
static int smb_traffic_analyzer_rename ( vfs_handle_struct * handle , \
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
{
struct rename_data s_data ;
s_data . result = SMB_VFS_NEXT_RENAME ( handle , smb_fname_src , \
smb_fname_dst ) ;
s_data . src = smb_fname_src - > base_name ;
s_data . dst = smb_fname_dst - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_rename: RENAME: %s / %s \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_rename ) ;
return s_data . result ;
}
static int smb_traffic_analyzer_rmdir ( vfs_handle_struct * handle , \
const char * path )
{
struct rmdir_data s_data ;
s_data . result = SMB_VFS_NEXT_RMDIR ( handle , path ) ;
s_data . path = path ;
DEBUG ( 10 , ( " smb_traffic_analyzer_rmdir: RMDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_rmdir ) ;
return s_data . result ;
}
2009-09-17 22:11:39 +04:00
static int smb_traffic_analyzer_mkdir ( vfs_handle_struct * handle , \
const char * path , mode_t mode )
{
2009-09-21 17:33:21 +04:00
struct mkdir_data s_data ;
s_data . result = SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
s_data . path = path ;
s_data . mode = mode ;
2009-09-17 22:11:39 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_mkdir: MKDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_mkdir ) ;
2009-09-21 17:33:21 +04:00
return s_data . result ;
2009-09-17 22:11:39 +04:00
}
2008-09-25 03:01:00 +04:00
static ssize_t smb_traffic_analyzer_read ( vfs_handle_struct * handle , \
files_struct * fsp , void * data , size_t n )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_READ ( handle , fsp , data , n ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_read: READ: %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_read ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_pread ( vfs_handle_struct * handle , \
files_struct * fsp , void * data , size_t n , SMB_OFF_T offset )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_PREAD ( handle , fsp , data , n , offset ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_pread: PREAD: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_pread ) ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_write ( vfs_handle_struct * handle , \
files_struct * fsp , const void * data , size_t n )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_WRITE ( handle , fsp , data , n ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_write: WRITE: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_write ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_pwrite ( vfs_handle_struct * handle , \
files_struct * fsp , const void * data , size_t n , SMB_OFF_T offset )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_PWRITE ( handle , fsp , data , n , offset ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_pwrite: PWRITE: %s \n " , \
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_pwrite ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_smb_traffic_analyzer_fns = {
. connect_fn = smb_traffic_analyzer_connect ,
. vfs_read = smb_traffic_analyzer_read ,
. pread = smb_traffic_analyzer_pread ,
. write = smb_traffic_analyzer_write ,
. pwrite = smb_traffic_analyzer_pwrite ,
2009-12-11 23:04:46 +03:00
. mkdir = smb_traffic_analyzer_mkdir ,
. rename = smb_traffic_analyzer_rename ,
. chdir = smb_traffic_analyzer_chdir
2008-10-01 02:13:19 +04:00
} ;
/* Module initialization */
NTSTATUS vfs_smb_traffic_analyzer_init ( void )
{
2009-07-24 04:28:58 +04:00
NTSTATUS ret = smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" smb_traffic_analyzer " ,
& vfs_smb_traffic_analyzer_fns ) ;
2008-10-01 02:13:19 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
vfs_smb_traffic_analyzer_debug_level =
debug_add_class ( " smb_traffic_analyzer " ) ;
if ( vfs_smb_traffic_analyzer_debug_level = = - 1 ) {
vfs_smb_traffic_analyzer_debug_level = DBGC_VFS ;
DEBUG ( 1 , ( " smb_traffic_analyzer_init: Couldn't register custom "
" debugging class! \n " ) ) ;
} else {
DEBUG ( 3 , ( " smb_traffic_analyzer_init: Debug class number of "
" 'smb_traffic_analyzer': %d \n " , \
vfs_smb_traffic_analyzer_debug_level ) ) ;
}
return ret ;
}