1998-03-15 05:37:52 +03:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
connection claim routines
Copyright ( C ) Andrew Tridgell 1998
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"
extern fstring remote_machine ;
2000-01-03 02:00:27 +03:00
static TDB_CONTEXT * tdb ;
1998-03-15 05:37:52 +03:00
extern int DEBUGLEVEL ;
2000-12-15 04:02:11 +03:00
/****************************************************************************
Return the connection tdb context ( used for message send all ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TDB_CONTEXT * conn_tdb_ctx ( void )
{
return tdb ;
}
1999-12-21 07:54:30 +03:00
/****************************************************************************
2001-05-14 10:15:46 +04:00
Delete a connection record .
1999-12-21 07:54:30 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-14 10:15:46 +04:00
1999-12-21 07:54:30 +03:00
BOOL yield_connection ( connection_struct * conn , char * name , int max_connections )
{
struct connections_key key ;
TDB_DATA kbuf ;
1998-03-15 05:37:52 +03:00
1999-12-21 12:25:59 +03:00
if ( ! tdb ) return False ;
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
DEBUG ( 3 , ( " Yielding connection to %s \n " , name ) ) ;
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
ZERO_STRUCT ( key ) ;
2000-05-02 06:23:41 +04:00
key . pid = sys_getpid ( ) ;
2001-01-09 00:19:15 +03:00
key . cnum = conn ? conn - > cnum : - 1 ;
1999-12-21 07:54:30 +03:00
fstrcpy ( key . name , name ) ;
2001-01-11 23:41:19 +03:00
dos_to_unix ( key . name , True ) ; /* Convert key to unix-codepage */
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
kbuf . dptr = ( char * ) & key ;
kbuf . dsize = sizeof ( key ) ;
tdb_delete ( tdb , kbuf ) ;
2000-01-12 06:09:17 +03:00
1998-03-15 05:37:52 +03:00
return ( True ) ;
}
2001-05-14 10:15:46 +04:00
struct count_stat {
pid_t mypid ;
int curr_connections ;
char * name ;
2001-05-15 04:53:15 +04:00
BOOL Clear ;
2001-05-14 10:15:46 +04:00
} ;
/****************************************************************************
Count the entries belonging to a service in the connection db .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int count_fn ( TDB_CONTEXT * the_tdb , TDB_DATA kbuf , TDB_DATA dbuf , void * udp )
{
struct connections_data crec ;
struct count_stat * cs = ( struct count_stat * ) udp ;
2001-05-15 22:12:02 +04:00
if ( dbuf . dsize ! = sizeof ( crec ) )
return 0 ;
2001-05-14 10:15:46 +04:00
memcpy ( & crec , dbuf . dptr , sizeof ( crec ) ) ;
2001-05-17 04:24:34 +04:00
if ( crec . cnum = = - 1 )
2001-05-14 10:15:46 +04:00
return 0 ;
2001-05-17 04:24:34 +04:00
/* If the pid was not found delete the entry from connections.tdb */
if ( cs - > Clear & & ! process_exists ( crec . pid ) & & ( errno = = ESRCH ) ) {
2001-05-14 10:15:46 +04:00
DEBUG ( 2 , ( " pid %u doesn't exist - deleting connections %d [%s] \n " ,
( unsigned int ) crec . pid , crec . cnum , crec . name ) ) ;
tdb_delete ( the_tdb , kbuf ) ;
return 0 ;
}
2001-05-17 04:24:34 +04:00
if ( strequal ( crec . name , cs - > name ) )
2001-05-14 10:15:46 +04:00
cs - > curr_connections + + ;
return 0 ;
}
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
/****************************************************************************
2001-05-14 10:15:46 +04:00
Claim an entry in the connections database .
1998-03-15 05:37:52 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-14 10:15:46 +04:00
1998-08-14 21:38:29 +04:00
BOOL claim_connection ( connection_struct * conn , char * name , int max_connections , BOOL Clear )
1998-03-15 05:37:52 +03:00
{
1999-12-21 07:54:30 +03:00
struct connections_key key ;
struct connections_data crec ;
2001-05-17 04:24:34 +04:00
TDB_DATA kbuf , dbuf , lockkey ;
BOOL rec_locked = False ;
BOOL ret = True ;
1999-12-21 07:54:30 +03:00
2000-01-03 02:00:27 +03:00
if ( ! tdb ) {
tdb = tdb_open ( lock_path ( " connections.tdb " ) , 0 , TDB_CLEAR_IF_FIRST ,
O_RDWR | O_CREAT , 0644 ) ;
}
2001-05-14 10:15:46 +04:00
if ( ! tdb )
return False ;
/*
* Enforce the max connections parameter .
*/
if ( max_connections > 0 ) {
struct count_stat cs ;
cs . mypid = sys_getpid ( ) ;
cs . curr_connections = 0 ;
cs . name = lp_servicename ( SNUM ( conn ) ) ;
2001-05-15 04:53:15 +04:00
cs . Clear = Clear ;
2001-05-14 10:15:46 +04:00
2001-05-17 04:24:34 +04:00
lockkey . dptr = cs . name ;
lockkey . dsize = strlen ( cs . name ) + 1 ;
2001-05-14 10:15:46 +04:00
/*
2001-05-17 04:24:34 +04:00
* Go through and count the connections with hash chain representing the service name
* locked . This is slow but removes race conditions . JRA .
2001-05-14 10:15:46 +04:00
*/
2001-05-17 04:24:34 +04:00
if ( tdb_chainlock ( tdb , lockkey ) )
return False ;
rec_locked = True ;
2001-05-14 22:43:49 +04:00
if ( tdb_traverse ( tdb , count_fn , & cs ) = = - 1 ) {
DEBUG ( 0 , ( " claim_connection: traverse of connections.tdb failed. \n " ) ) ;
2001-05-17 04:24:34 +04:00
ret = False ;
goto out ;
2001-05-14 10:15:46 +04:00
}
if ( cs . curr_connections > = max_connections ) {
DEBUG ( 1 , ( " claim_connection: Max connections (%d) exceeded for %s \n " ,
max_connections , name ) ) ;
2001-05-17 04:24:34 +04:00
ret = False ;
goto out ;
2001-05-14 10:15:46 +04:00
}
}
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
DEBUG ( 5 , ( " claiming %s %d \n " , name , max_connections ) ) ;
ZERO_STRUCT ( key ) ;
2000-05-02 06:23:41 +04:00
key . pid = sys_getpid ( ) ;
1999-12-21 07:54:30 +03:00
key . cnum = conn ? conn - > cnum : - 1 ;
fstrcpy ( key . name , name ) ;
2001-01-11 23:41:19 +03:00
dos_to_unix ( key . name , True ) ; /* Convert key to unix-codepage */
1999-12-21 07:54:30 +03:00
kbuf . dptr = ( char * ) & key ;
kbuf . dsize = sizeof ( key ) ;
1998-03-15 05:37:52 +03:00
/* fill in the crec */
1999-12-21 07:54:30 +03:00
ZERO_STRUCT ( crec ) ;
1998-03-15 05:37:52 +03:00
crec . magic = 0x280267 ;
2000-05-02 06:23:41 +04:00
crec . pid = sys_getpid ( ) ;
1999-12-21 07:54:30 +03:00
crec . cnum = conn ? conn - > cnum : - 1 ;
1998-08-14 21:38:29 +04:00
if ( conn ) {
crec . uid = conn - > uid ;
crec . gid = conn - > gid ;
StrnCpy ( crec . name ,
lp_servicename ( SNUM ( conn ) ) , sizeof ( crec . name ) - 1 ) ;
1998-03-15 05:37:52 +03:00
}
crec . start = time ( NULL ) ;
StrnCpy ( crec . machine , remote_machine , sizeof ( crec . machine ) - 1 ) ;
2000-04-11 17:55:53 +04:00
StrnCpy ( crec . addr , conn ? conn - > client_address : client_addr ( ) , sizeof ( crec . addr ) - 1 ) ;
1998-03-15 05:37:52 +03:00
1999-12-21 07:54:30 +03:00
dbuf . dptr = ( char * ) & crec ;
dbuf . dsize = sizeof ( crec ) ;
2001-05-14 10:15:46 +04:00
if ( tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ! = 0 )
2001-05-17 04:24:34 +04:00
ret = False ;
1999-12-21 07:54:30 +03:00
2001-05-17 04:24:34 +04:00
out :
2000-01-12 06:09:17 +03:00
2001-05-17 04:24:34 +04:00
if ( rec_locked )
tdb_chainunlock ( tdb , lockkey ) ;
2001-05-14 22:43:49 +04:00
2001-05-17 04:24:34 +04:00
return ret ;
2001-05-14 22:43:49 +04:00
}