2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
2004-06-28 12:27:36 +04:00
Manage smbsrv_tcon structures
2003-08-13 05:53:07 +04:00
Copyright ( C ) Andrew Tridgell 1998
Copyright ( C ) Alexander Bokovoy 2002
2006-05-20 12:15:22 +04:00
Copyright ( C ) Stefan Metzmacher 2005 - 2006
2003-08-13 05:53:07 +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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-01-30 03:54:57 +03:00
# include "smbd/service_stream.h"
2010-04-27 17:45:12 +04:00
# include "lib/tsocket/tsocket.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2004-11-02 10:18:24 +03:00
2003-08-13 05:53:07 +04:00
/****************************************************************************
2004-06-28 12:27:36 +04:00
init the tcon structures
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-06 20:59:20 +03:00
static NTSTATUS smbsrv_init_tcons ( struct smbsrv_tcons_context * tcons_ctx , TALLOC_CTX * mem_ctx , uint32_t limit )
2003-08-13 05:53:07 +04:00
{
2005-11-18 15:38:39 +03:00
/*
* the idr_ * functions take ' int ' as limit ,
* and only work with a max limit 0x00FFFFFF
*/
limit & = 0x00FFFFFF ;
2005-12-06 20:59:20 +03:00
tcons_ctx - > idtree_tid = idr_init ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( tcons_ctx - > idtree_tid ) ;
tcons_ctx - > idtree_limit = limit ;
tcons_ctx - > list = NULL ;
2005-11-18 15:38:39 +03:00
2005-11-18 11:44:36 +03:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
2005-12-06 20:59:20 +03:00
NTSTATUS smbsrv_smb_init_tcons ( struct smbsrv_connection * smb_conn )
{
return smbsrv_init_tcons ( & smb_conn - > smb_tcons , smb_conn , UINT16_MAX ) ;
}
NTSTATUS smbsrv_smb2_init_tcons ( struct smbsrv_session * smb_sess )
{
return smbsrv_init_tcons ( & smb_sess - > smb2_tcons , smb_sess , UINT32_MAX ) ;
}
2003-08-13 05:53:07 +04:00
/****************************************************************************
2005-12-06 20:59:20 +03:00
find a tcon given a tid for SMB
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-26 15:32:27 +04:00
static struct smbsrv_tcon * smbsrv_tcon_find ( struct smbsrv_tcons_context * tcons_ctx ,
uint32_t tid , struct timeval request_time )
2003-08-13 05:53:07 +04:00
{
2005-11-18 15:38:39 +03:00
void * p ;
struct smbsrv_tcon * tcon ;
if ( tid = = 0 ) return NULL ;
2005-12-06 20:59:20 +03:00
if ( tid > tcons_ctx - > idtree_limit ) return NULL ;
2005-11-18 15:38:39 +03:00
2005-12-06 20:59:20 +03:00
p = idr_find ( tcons_ctx - > idtree_tid , tid ) ;
2005-11-18 15:38:39 +03:00
if ( ! p ) return NULL ;
tcon = talloc_get_type ( p , struct smbsrv_tcon ) ;
2006-03-26 15:32:27 +04:00
if ( ! tcon ) return NULL ;
tcon - > statistics . last_request_time = request_time ;
2005-11-18 15:38:39 +03:00
return tcon ;
2003-08-13 05:53:07 +04:00
}
2006-03-26 15:32:27 +04:00
struct smbsrv_tcon * smbsrv_smb_tcon_find ( struct smbsrv_connection * smb_conn ,
uint32_t tid , struct timeval request_time )
2005-12-06 20:59:20 +03:00
{
2006-03-26 15:32:27 +04:00
return smbsrv_tcon_find ( & smb_conn - > smb_tcons , tid , request_time ) ;
2005-12-06 20:59:20 +03:00
}
2006-03-26 15:32:27 +04:00
struct smbsrv_tcon * smbsrv_smb2_tcon_find ( struct smbsrv_session * smb_sess ,
uint32_t tid , struct timeval request_time )
2005-12-06 20:59:20 +03:00
{
if ( ! smb_sess ) return NULL ;
2006-03-26 15:32:27 +04:00
return smbsrv_tcon_find ( & smb_sess - > smb2_tcons , tid , request_time ) ;
2005-12-06 20:59:20 +03:00
}
2004-10-19 11:08:35 +04:00
/*
destroy a connection structure
*/
2006-05-24 11:35:06 +04:00
static int smbsrv_tcon_destructor ( struct smbsrv_tcon * tcon )
2004-10-19 11:08:35 +04:00
{
2005-12-06 20:59:20 +03:00
struct smbsrv_tcons_context * tcons_ctx ;
2010-04-27 17:45:12 +04:00
struct tsocket_address * client_addr ;
client_addr = tcon - > smb_conn - > connection - > remote_address ;
2006-03-15 20:28:46 +03:00
2005-01-13 21:49:10 +03:00
DEBUG ( 3 , ( " %s closed connection to service %s \n " ,
2010-04-27 17:45:12 +04:00
tsocket_address_string ( client_addr , tcon ) ,
2006-03-15 20:28:46 +03:00
tcon - > share_name ) ) ;
2005-01-13 21:49:10 +03:00
/* tell the ntvfs backend that we are disconnecting */
2006-03-15 20:28:46 +03:00
if ( tcon - > ntvfs ) {
ntvfs_disconnect ( tcon - > ntvfs ) ;
2006-05-20 12:15:22 +04:00
tcon - > ntvfs = NULL ;
2005-11-18 15:38:39 +03:00
}
2005-01-13 21:49:10 +03:00
2005-12-06 20:59:20 +03:00
if ( tcon - > smb2 . session ) {
tcons_ctx = & tcon - > smb2 . session - > smb2_tcons ;
} else {
tcons_ctx = & tcon - > smb_conn - > smb_tcons ;
}
idr_remove ( tcons_ctx - > idtree_tid , tcon - > tid ) ;
DLIST_REMOVE ( tcons_ctx - > list , tcon ) ;
2004-10-19 11:08:35 +04:00
return 0 ;
}
2003-08-13 05:53:07 +04:00
2004-10-19 11:08:35 +04:00
/*
find first available connection slot
*/
2006-03-15 20:28:46 +03:00
static struct smbsrv_tcon * smbsrv_tcon_new ( struct smbsrv_connection * smb_conn ,
struct smbsrv_session * smb_sess ,
const char * share_name )
2003-08-13 05:53:07 +04:00
{
2005-12-06 20:59:20 +03:00
TALLOC_CTX * mem_ctx ;
struct smbsrv_tcons_context * tcons_ctx ;
2007-05-21 21:12:49 +04:00
uint32_t handle_uint_max ;
2004-06-28 12:27:36 +04:00
struct smbsrv_tcon * tcon ;
2006-05-20 12:15:22 +04:00
NTSTATUS status ;
2003-08-13 05:53:07 +04:00
int i ;
2005-12-06 20:59:20 +03:00
if ( smb_sess ) {
mem_ctx = smb_sess ;
tcons_ctx = & smb_sess - > smb2_tcons ;
2007-05-21 21:12:49 +04:00
handle_uint_max = UINT32_MAX ;
2005-12-06 20:59:20 +03:00
} else {
mem_ctx = smb_conn ;
tcons_ctx = & smb_conn - > smb_tcons ;
2007-05-21 21:12:49 +04:00
handle_uint_max = UINT16_MAX ;
2005-12-06 20:59:20 +03:00
}
tcon = talloc_zero ( mem_ctx , struct smbsrv_tcon ) ;
2004-10-19 11:08:35 +04:00
if ( ! tcon ) return NULL ;
2005-12-06 20:59:20 +03:00
tcon - > smb_conn = smb_conn ;
tcon - > smb2 . session = smb_sess ;
2006-03-15 20:28:46 +03:00
tcon - > share_name = talloc_strdup ( tcon , share_name ) ;
if ( ! tcon - > share_name ) goto failed ;
2004-10-19 11:08:35 +04:00
2006-05-20 12:15:22 +04:00
/*
* the use - 1 here , because we don ' t want to give away the wildcard
* fnum used in SMBflush
*/
2007-05-21 21:12:49 +04:00
status = smbsrv_init_handles ( tcon , handle_uint_max - 1 ) ;
2006-05-20 12:15:22 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " ERROR! failed to init handles: %s \n " , nt_errstr ( status ) ) ) ;
goto failed ;
}
2005-12-06 20:59:20 +03:00
i = idr_get_new_random ( tcons_ctx - > idtree_tid , tcon , tcons_ctx - > idtree_limit ) ;
2003-08-13 05:53:07 +04:00
if ( i = = - 1 ) {
2005-12-06 20:59:20 +03:00
DEBUG ( 1 , ( " ERROR! Out of connection structures \n " ) ) ;
2006-03-15 20:28:46 +03:00
goto failed ;
2003-08-13 05:53:07 +04:00
}
2005-01-13 21:49:10 +03:00
tcon - > tid = i ;
2003-08-13 05:53:07 +04:00
2005-12-06 20:59:20 +03:00
DLIST_ADD ( tcons_ctx - > list , tcon ) ;
2005-01-13 21:49:10 +03:00
talloc_set_destructor ( tcon , smbsrv_tcon_destructor ) ;
2003-08-13 05:53:07 +04:00
2005-11-18 15:38:39 +03:00
/* now fill in some statistics */
tcon - > statistics . connect_time = timeval_current ( ) ;
2003-08-13 05:53:07 +04:00
2004-06-28 12:27:36 +04:00
return tcon ;
2006-03-15 20:28:46 +03:00
failed :
talloc_free ( tcon ) ;
return NULL ;
2003-08-13 05:53:07 +04:00
}
2005-12-06 20:59:20 +03:00
2006-03-15 20:28:46 +03:00
struct smbsrv_tcon * smbsrv_smb_tcon_new ( struct smbsrv_connection * smb_conn , const char * share_name )
2005-12-06 20:59:20 +03:00
{
2006-03-15 20:28:46 +03:00
return smbsrv_tcon_new ( smb_conn , NULL , share_name ) ;
2005-12-06 20:59:20 +03:00
}
2006-03-15 20:28:46 +03:00
struct smbsrv_tcon * smbsrv_smb2_tcon_new ( struct smbsrv_session * smb_sess , const char * share_name )
2005-12-06 20:59:20 +03:00
{
2006-03-15 20:28:46 +03:00
return smbsrv_tcon_new ( smb_sess - > smb_conn , smb_sess , share_name ) ;
2005-12-06 20:59:20 +03:00
}