1998-03-15 02:37:52 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1998-03-15 02:37:52 +00:00
connection claim routines
Copyright ( C ) Andrew Tridgell 1998
2008-10-10 17:50:09 +02:00
1998-03-15 02:37:52 +00: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-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
1998-03-15 02:37:52 +00:00
( at your option ) any later version .
2008-10-10 17:50:09 +02:00
1998-03-15 02:37:52 +00:00
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 .
2008-10-10 17:50:09 +02:00
1998-03-15 02:37:52 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-03-15 02:37:52 +00:00
*/
# include "includes.h"
2011-03-22 16:57:01 +01:00
# include "smbd/smbd.h"
2010-07-04 18:15:36 +02:00
# include "smbd/globals.h"
2011-07-07 17:42:08 +02:00
# include "dbwrap/dbwrap.h"
2011-03-24 13:46:20 +01:00
# include "auth.h"
2011-06-16 14:29:36 +02:00
# include "../lib/tsocket/tsocket.h"
2011-12-15 11:51:20 +01:00
# include "messages.h"
1998-03-15 02:37:52 +00:00
1999-12-21 04:54:30 +00:00
/****************************************************************************
2001-05-14 06:15:46 +00:00
Delete a connection record .
1999-12-21 04:54:30 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-14 06:15:46 +00:00
2007-10-18 17:40:25 -07:00
bool yield_connection ( connection_struct * conn , const char * name )
1999-12-21 04:54:30 +00:00
{
2007-05-28 11:38:42 +00:00
struct db_record * rec ;
NTSTATUS status ;
1998-03-15 02:37:52 +00:00
1999-12-21 04:54:30 +00:00
DEBUG ( 3 , ( " Yielding connection to %s \n " , name ) ) ;
1998-03-15 02:37:52 +00:00
2010-02-26 17:53:34 +01:00
rec = connections_fetch_entry ( talloc_tos ( ) , conn , name ) ;
if ( rec = = NULL ) {
2007-05-28 11:38:42 +00:00
DEBUG ( 0 , ( " connections_fetch_entry failed \n " ) ) ;
return False ;
}
1999-12-21 04:54:30 +00:00
2011-08-25 00:42:10 +02:00
status = dbwrap_record_delete ( rec ) ;
2007-05-28 11:38:42 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ? 3 : 0 ,
( " deleting connection record returned %s \n " ,
nt_errstr ( status ) ) ) ;
2001-06-08 20:26:46 +00:00
}
2000-01-12 03:09:17 +00:00
2007-05-29 18:14:54 +00:00
TALLOC_FREE ( rec ) ;
2007-05-28 11:38:42 +00:00
return NT_STATUS_IS_OK ( status ) ;
1998-03-15 02:37:52 +00:00
}
2001-05-14 06:15:46 +00:00
struct count_stat {
int curr_connections ;
2006-07-11 18:01:26 +00:00
const char * name ;
2007-10-18 17:40:25 -07:00
bool Clear ;
2001-05-14 06:15:46 +00:00
} ;
/****************************************************************************
Count the entries belonging to a service in the connection db .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-05-28 11:38:42 +00:00
static int count_fn ( struct db_record * rec ,
const struct connections_key * ckey ,
const struct connections_data * crec ,
void * udp )
2001-05-14 06:15:46 +00:00
{
struct count_stat * cs = ( struct count_stat * ) udp ;
2008-10-10 17:50:09 +02:00
2007-05-28 11:38:42 +00:00
if ( crec - > cnum = = - 1 ) {
2001-05-14 06:15:46 +00:00
return 0 ;
2007-04-20 21:09:44 +00:00
}
2001-05-14 06:15:46 +00:00
2001-05-17 00:24:34 +00:00
/* If the pid was not found delete the entry from connections.tdb */
2007-05-28 11:38:42 +00:00
if ( cs - > Clear & & ! process_exists ( crec - > pid ) & & ( errno = = ESRCH ) ) {
NTSTATUS status ;
2005-09-30 17:13:37 +00:00
DEBUG ( 2 , ( " pid %s doesn't exist - deleting connections %d [%s] \n " ,
2007-05-28 11:38:42 +00:00
procid_str_static ( & crec - > pid ) , crec - > cnum ,
crec - > servicename ) ) ;
2011-08-25 00:42:10 +02:00
status = dbwrap_record_delete ( rec ) ;
2007-05-28 11:38:42 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " count_fn: tdb_delete failed with error %s \n " ,
nt_errstr ( status ) ) ) ;
}
2001-05-14 06:15:46 +00:00
return 0 ;
}
2007-10-10 15:34:30 -05:00
if ( strequal ( crec - > servicename , cs - > name ) )
2001-05-14 06:15:46 +00:00
cs - > curr_connections + + ;
return 0 ;
}
1998-03-15 02:37:52 +00:00
1999-12-21 04:54:30 +00:00
/****************************************************************************
2001-05-14 06:15:46 +00:00
Claim an entry in the connections database .
1998-03-15 02:37:52 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-14 06:15:46 +00:00
2007-10-18 17:40:25 -07:00
int count_current_connections ( const char * sharename , bool clear )
1998-03-15 02:37:52 +00:00
{
2006-07-11 18:01:26 +00:00
struct count_stat cs ;
2011-06-14 17:50:41 +02:00
int ret ;
2002-09-25 15:19:00 +00:00
2006-07-11 18:01:26 +00:00
cs . curr_connections = 0 ;
cs . name = sharename ;
cs . Clear = clear ;
2001-05-14 06:15:46 +00:00
/*
2006-07-11 18:01:26 +00:00
* This has a race condition , but locking the chain before hand is worse
* as it leads to deadlock .
2001-05-14 06:15:46 +00:00
*/
2011-06-14 17:52:42 +02:00
/*
* become_root ( ) because we might have to open connections . tdb
* via ctdb , which is not possible without root .
*/
become_root ( ) ;
2011-06-14 17:50:41 +02:00
ret = connections_forall ( count_fn , & cs ) ;
2011-06-14 17:52:42 +02:00
unbecome_root ( ) ;
2011-06-20 18:40:31 +09:30
if ( ret < 0 ) {
2007-05-28 11:38:42 +00:00
DEBUG ( 0 , ( " count_current_connections: traverse of "
" connections.tdb failed \n " ) ) ;
2011-06-14 17:50:41 +02:00
return 0 ;
2006-07-11 18:01:26 +00:00
}
2007-04-20 21:09:44 +00:00
2006-07-11 18:01:26 +00:00
return cs . curr_connections ;
}
2001-05-14 06:15:46 +00:00
2011-12-13 12:18:01 +01:00
bool connections_snum_used ( struct smbd_server_connection * unused , int snum )
{
int active ;
active = count_current_connections ( lp_servicename ( snum ) , true ) ;
if ( active > 0 ) {
return true ;
}
return false ;
}
2006-07-11 18:01:26 +00:00
/****************************************************************************
Claim an entry in the connections database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-14 06:15:46 +00:00
2010-07-04 20:45:43 +02:00
bool claim_connection ( connection_struct * conn , const char * name )
2006-07-11 18:01:26 +00:00
{
2007-05-28 11:38:42 +00:00
struct db_record * rec ;
2006-07-11 18:01:26 +00:00
struct connections_data crec ;
2011-06-16 14:29:36 +02:00
char * raddr ;
2007-05-28 11:38:42 +00:00
TDB_DATA dbuf ;
NTSTATUS status ;
2001-09-19 07:06:34 +00:00
2007-05-28 11:38:42 +00:00
DEBUG ( 5 , ( " claiming [%s] \n " , name ) ) ;
2008-01-06 14:21:25 +01:00
if ( ! ( rec = connections_fetch_entry ( talloc_tos ( ) , conn , name ) ) ) {
2007-05-28 11:38:42 +00:00
DEBUG ( 0 , ( " connections_fetch_entry failed \n " ) ) ;
2007-05-08 13:44:36 +00:00
return False ;
2006-07-11 18:01:26 +00:00
}
1998-03-15 02:37:52 +00:00
2011-07-15 14:59:14 +10:00
/* Make clear that we require the optional unix_token in the source3 code */
SMB_ASSERT ( conn - > session_info - > unix_token ) ;
1998-03-15 02:37:52 +00:00
/* fill in the crec */
1999-12-21 04:54:30 +00:00
ZERO_STRUCT ( crec ) ;
1998-03-15 02:37:52 +00:00
crec . magic = 0x280267 ;
2011-12-15 11:51:20 +01:00
crec . pid = messaging_server_id ( conn - > sconn - > msg_ctx ) ;
2010-07-04 18:12:24 +02:00
crec . cnum = conn - > cnum ;
2011-07-15 14:59:14 +10:00
crec . uid = conn - > session_info - > unix_token - > uid ;
crec . gid = conn - > session_info - > unix_token - > gid ;
2010-07-04 18:12:24 +02:00
strlcpy ( crec . servicename , lp_servicename ( SNUM ( conn ) ) ,
sizeof ( crec . servicename ) ) ;
1998-03-15 02:37:52 +00:00
crec . start = time ( NULL ) ;
2008-10-10 17:50:09 +02:00
2011-06-16 14:29:36 +02:00
raddr = tsocket_address_inet_addr_string ( conn - > sconn - > remote_address ,
talloc_tos ( ) ) ;
if ( raddr = = NULL ) {
return false ;
}
2007-05-28 11:38:42 +00:00
strlcpy ( crec . machine , get_remote_machine_name ( ) , sizeof ( crec . machine ) ) ;
2011-06-16 14:29:36 +02:00
strlcpy ( crec . addr , raddr , sizeof ( crec . addr ) ) ;
1998-03-15 02:37:52 +00:00
2007-03-29 09:35:51 +00:00
dbuf . dptr = ( uint8 * ) & crec ;
1999-12-21 04:54:30 +00:00
dbuf . dsize = sizeof ( crec ) ;
2011-08-25 00:42:10 +02:00
status = dbwrap_record_store ( rec , dbuf , TDB_REPLACE ) ;
2007-05-28 11:38:42 +00:00
TALLOC_FREE ( rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2001-05-23 21:33:43 +00:00
DEBUG ( 0 , ( " claim_connection: tdb_store failed with error %s. \n " ,
2007-05-28 11:38:42 +00:00
nt_errstr ( status ) ) ) ;
2001-09-19 07:06:34 +00:00
return False ;
2001-05-23 21:33:43 +00:00
}
1999-12-21 04:54:30 +00:00
2001-09-19 07:06:34 +00:00
return True ;
2001-05-14 18:43:49 +00:00
}