1998-08-17 10:13:32 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-17 10:13:32 +04:00
Manage connections_struct structures
Copyright ( C ) Andrew Tridgell 1998
2002-08-17 19:27:10 +04:00
Copyright ( C ) Alexander Bokovoy 2002
1998-08-17 10:13:32 +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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2003-12-11 23:00:16 +03:00
/* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The
* maximum size of the bitmap is the largest positive integer , but you will hit
* the " max connections " limit , looong before that .
*/
# define BITMAP_BLOCK_SZ 128
1998-08-17 10:13:32 +04:00
static connection_struct * Connections ;
/* number of open connections */
static struct bitmap * bmap ;
static int num_open ;
/****************************************************************************
init the conn structures
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void conn_init ( void )
{
2003-12-11 23:00:16 +03:00
bmap = bitmap_allocate ( BITMAP_BLOCK_SZ ) ;
1998-08-17 10:13:32 +04:00
}
/****************************************************************************
return the number of open connections
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int conn_num_open ( void )
{
return num_open ;
}
/****************************************************************************
check if a snum is in use
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL conn_snum_used ( int snum )
{
connection_struct * conn ;
for ( conn = Connections ; conn ; conn = conn - > next ) {
if ( conn - > service = = snum ) {
return ( True ) ;
}
}
return ( False ) ;
}
/****************************************************************************
find a conn given a cnum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-01 10:25:53 +03:00
connection_struct * conn_find ( unsigned cnum )
1998-08-17 10:13:32 +04:00
{
1998-08-17 10:47:53 +04:00
int count = 0 ;
1998-08-17 10:13:32 +04:00
connection_struct * conn ;
1998-08-17 10:47:53 +04:00
for ( conn = Connections ; conn ; conn = conn - > next , count + + ) {
if ( conn - > cnum = = cnum ) {
if ( count > 10 ) {
DLIST_PROMOTE ( Connections , conn ) ;
}
return conn ;
}
1998-08-17 10:13:32 +04:00
}
return NULL ;
}
/****************************************************************************
find first available connection slot , starting from a random position .
The randomisation stops problems with the server dieing and clients
thinking the server is still available .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
connection_struct * conn_new ( void )
{
2003-05-12 03:34:18 +04:00
TALLOC_CTX * mem_ctx ;
1998-08-17 10:13:32 +04:00
connection_struct * conn ;
int i ;
2003-12-11 23:00:16 +03:00
int find_offset = 1 ;
1998-08-17 10:13:32 +04:00
2003-12-11 23:00:16 +03:00
find_again :
i = bitmap_find ( bmap , find_offset ) ;
1998-08-17 10:13:32 +04:00
if ( i = = - 1 ) {
2003-12-11 23:00:16 +03:00
/* Expand the connections bitmap. */
int oldsz = bmap - > n ;
int newsz = bmap - > n + BITMAP_BLOCK_SZ ;
struct bitmap * nbmap ;
if ( newsz < = 0 ) {
/* Integer wrap. */
DEBUG ( 0 , ( " ERROR! Out of connection structures \n " ) ) ;
return NULL ;
}
DEBUG ( 4 , ( " resizing connections bitmap from %d to %d \n " ,
oldsz , newsz ) ) ;
nbmap = bitmap_allocate ( newsz ) ;
bitmap_copy ( nbmap , bmap ) ;
bitmap_free ( bmap ) ;
bmap = nbmap ;
find_offset = oldsz ; /* Start next search in the new portion. */
goto find_again ;
1998-08-17 10:13:32 +04:00
}
2003-05-12 03:34:18 +04:00
if ( ( mem_ctx = talloc_init ( " connection_struct " ) ) = = NULL ) {
DEBUG ( 0 , ( " talloc_init(connection_struct) failed! \n " ) ) ;
return NULL ;
}
1998-08-17 10:13:32 +04:00
2003-05-12 03:34:18 +04:00
if ( ( conn = ( connection_struct * ) talloc_zero ( mem_ctx , sizeof ( * conn ) ) ) = = NULL ) {
DEBUG ( 0 , ( " talloc_zero() failed! \n " ) ) ;
return NULL ;
}
conn - > mem_ctx = mem_ctx ;
1998-08-17 10:13:32 +04:00
conn - > cnum = i ;
bitmap_set ( bmap , i ) ;
num_open + + ;
2000-01-16 14:18:04 +03:00
string_set ( & conn - > user , " " ) ;
string_set ( & conn - > dirpath , " " ) ;
string_set ( & conn - > connectpath , " " ) ;
string_set ( & conn - > origpath , " " ) ;
1998-08-17 10:13:32 +04:00
1998-08-17 10:47:53 +04:00
DLIST_ADD ( Connections , conn ) ;
1998-08-17 10:13:32 +04:00
return conn ;
}
/****************************************************************************
close all conn structures
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void conn_close_all ( void )
{
connection_struct * conn , * next ;
for ( conn = Connections ; conn ; conn = next ) {
next = conn - > next ;
2002-09-25 19:19:00 +04:00
close_cnum ( conn , conn - > vuid ) ;
1998-08-17 10:13:32 +04:00
}
}
/****************************************************************************
2003-01-17 09:34:22 +03:00
Idle inactive connections .
1998-08-17 10:13:32 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-17 09:34:22 +03:00
1998-08-17 10:13:32 +04:00
BOOL conn_idle_all ( time_t t , int deadtime )
{
2003-01-17 09:34:22 +03:00
pipes_struct * plist = NULL ;
1998-08-17 10:13:32 +04:00
BOOL allidle = True ;
connection_struct * conn , * next ;
for ( conn = Connections ; conn ; conn = next ) {
next = conn - > next ;
/* close dirptrs on connections that are idle */
if ( ( t - conn - > lastused ) > DPTR_IDLE_TIMEOUT )
dptr_idlecnum ( conn ) ;
if ( conn - > num_files_open > 0 | |
( t - conn - > lastused ) < deadtime )
allidle = False ;
}
2003-01-17 09:34:22 +03:00
/*
* Check all pipes for any open handles . We cannot
* idle with a handle open .
*/
for ( plist = get_first_internal_pipe ( ) ; plist ; plist = get_next_internal_pipe ( plist ) )
if ( plist - > pipe_handles & & plist - > pipe_handles - > count )
allidle = False ;
1998-08-17 10:13:32 +04:00
return allidle ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
clear a vuid out of the validity cache , and as the ' owner ' of a connection .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void conn_clear_vuid_cache ( uint16 vuid )
{
connection_struct * conn ;
2003-02-01 10:25:53 +03:00
unsigned int i ;
2002-09-25 19:19:00 +04:00
for ( conn = Connections ; conn ; conn = conn - > next ) {
if ( conn - > vuid = = vuid ) {
conn - > vuid = UID_FIELD_INVALID ;
}
for ( i = 0 ; i < conn - > vuid_cache . entries & & i < VUID_CACHE_SIZE ; i + + ) {
if ( conn - > vuid_cache . list [ i ] = = vuid ) {
conn - > vuid_cache . list [ i ] = UID_FIELD_INVALID ;
}
}
}
}
1998-08-17 10:13:32 +04:00
/****************************************************************************
2000-08-04 02:38:43 +04:00
Free a conn structure .
1998-08-17 10:13:32 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-08-04 02:38:43 +04:00
1998-08-17 10:13:32 +04:00
void conn_free ( connection_struct * conn )
{
2003-05-12 03:34:18 +04:00
vfs_handle_struct * handle = NULL , * thandle = NULL ;
TALLOC_CTX * mem_ctx = NULL ;
2002-08-17 19:27:10 +04:00
2000-04-29 01:09:26 +04:00
/* Free vfs_connection_struct */
2003-05-12 03:34:18 +04:00
handle = conn - > vfs_handles ;
2002-08-17 19:27:10 +04:00
while ( handle ) {
2003-05-12 03:34:18 +04:00
DLIST_REMOVE ( conn - > vfs_handles , handle ) ;
2002-08-17 19:27:10 +04:00
thandle = handle - > next ;
2003-05-12 03:34:18 +04:00
if ( handle - > free_data )
handle - > free_data ( & handle - > data ) ;
2002-08-17 19:27:10 +04:00
handle = thandle ;
2000-04-29 01:09:26 +04:00
}
1998-08-17 10:47:53 +04:00
DLIST_REMOVE ( Connections , conn ) ;
1998-08-17 10:13:32 +04:00
if ( conn - > ngroups & & conn - > groups ) {
2001-09-17 15:25:41 +04:00
SAFE_FREE ( conn - > groups ) ;
1998-08-17 10:13:32 +04:00
conn - > ngroups = 0 ;
}
free_namearray ( conn - > veto_list ) ;
free_namearray ( conn - > hide_list ) ;
free_namearray ( conn - > veto_oplock_list ) ;
string_free ( & conn - > user ) ;
string_free ( & conn - > dirpath ) ;
string_free ( & conn - > connectpath ) ;
string_free ( & conn - > origpath ) ;
bitmap_clear ( bmap , conn - > cnum ) ;
num_open - - ;
2003-05-12 03:34:18 +04:00
mem_ctx = conn - > mem_ctx ;
1998-09-05 17:24:20 +04:00
ZERO_STRUCTP ( conn ) ;
2003-05-12 03:34:18 +04:00
talloc_destroy ( mem_ctx ) ;
1998-08-17 10:13:32 +04:00
}
2001-06-20 07:05:09 +04:00
/****************************************************************************
receive a smbcontrol message to forcibly unmount a share
the message contains just a share name and all instances of that
share are unmounted
the special sharename ' * ' forces unmount of all shares
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void msg_force_tdis ( int msg_type , pid_t pid , void * buf , size_t len )
{
connection_struct * conn , * next ;
fstring sharename ;
fstrcpy ( sharename , buf ) ;
if ( strcmp ( sharename , " * " ) = = 0 ) {
DEBUG ( 1 , ( " Forcing close of all shares \n " ) ) ;
conn_close_all ( ) ;
return ;
}
for ( conn = Connections ; conn ; conn = next ) {
next = conn - > next ;
if ( strequal ( lp_servicename ( conn - > service ) , sharename ) ) {
DEBUG ( 1 , ( " Forcing close of share %s cnum=%d \n " ,
sharename , conn - > cnum ) ) ;
close_cnum ( conn , ( uint16 ) - 1 ) ;
}
}
}