0001-01-01 02:30:17 +02:30
/*
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 ;
0001-01-01 02:30:17 +02:30
static TDB_CONTEXT * tdb ;
0001-01-01 02:30:17 +02:30
extern int DEBUGLEVEL ;
0001-01-01 02:30:17 +02:30
# ifdef WITH_UTMP
static void utmp_yield ( pid_t pid , const connection_struct * conn ) ;
static void utmp_claim ( const struct connections_data * crec , const connection_struct * conn ) ;
# endif
0001-01-01 02:30:17 +02:30
/****************************************************************************
delete a connection record
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL yield_connection ( connection_struct * conn , char * name , int max_connections )
{
struct connections_key key ;
TDB_DATA kbuf ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! tdb ) return False ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " Yielding connection to %s \n " , name ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( key ) ;
key . pid = getpid ( ) ;
if ( conn ) key . cnum = conn - > cnum ;
fstrcpy ( key . name , name ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
kbuf . dptr = ( char * ) & key ;
kbuf . dsize = sizeof ( key ) ;
tdb_delete ( tdb , kbuf ) ;
0001-01-01 02:30:17 +02:30
# ifdef WITH_UTMP
if ( conn )
utmp_yield ( key . pid , conn ) ;
# endif
0001-01-01 02:30:17 +02:30
return ( True ) ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************
claim an entry in the connections database
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
BOOL claim_connection ( connection_struct * conn , char * name , int max_connections , BOOL Clear )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
struct connections_key key ;
struct connections_data crec ;
TDB_DATA kbuf , dbuf ;
0001-01-01 02:30:17 +02:30
extern int Client ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( max_connections < = 0 )
return ( True ) ;
0001-01-01 02:30:17 +02:30
if ( ! tdb ) {
tdb = tdb_open ( lock_path ( " connections.tdb " ) , 0 , TDB_CLEAR_IF_FIRST ,
O_RDWR | O_CREAT , 0644 ) ;
}
0001-01-01 02:30:17 +02:30
if ( ! tdb ) return False ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " claiming %s %d \n " , name , max_connections ) ) ;
ZERO_STRUCT ( key ) ;
key . pid = getpid ( ) ;
key . cnum = conn ? conn - > cnum : - 1 ;
fstrcpy ( key . name , name ) ;
kbuf . dptr = ( char * ) & key ;
kbuf . dsize = sizeof ( key ) ;
0001-01-01 02:30:17 +02:30
/* fill in the crec */
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( crec ) ;
0001-01-01 02:30:17 +02:30
crec . magic = 0x280267 ;
crec . pid = getpid ( ) ;
0001-01-01 02:30:17 +02:30
crec . cnum = conn ? conn - > cnum : - 1 ;
0001-01-01 02:30:17 +02:30
if ( conn ) {
crec . uid = conn - > uid ;
crec . gid = conn - > gid ;
StrnCpy ( crec . name ,
lp_servicename ( SNUM ( conn ) ) , sizeof ( crec . name ) - 1 ) ;
0001-01-01 02:30:17 +02:30
}
crec . start = time ( NULL ) ;
StrnCpy ( crec . machine , remote_machine , sizeof ( crec . machine ) - 1 ) ;
0001-01-01 02:30:17 +02:30
StrnCpy ( crec . addr , conn ? conn - > client_address : client_addr ( Client ) , sizeof ( crec . addr ) - 1 ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
dbuf . dptr = ( char * ) & crec ;
dbuf . dsize = sizeof ( crec ) ;
if ( tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) return False ;
0001-01-01 02:30:17 +02:30
# ifdef WITH_UTMP
if ( conn )
utmp_claim ( & crec , conn ) ;
# endif
0001-01-01 02:30:17 +02:30
return True ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
# ifdef WITH_UTMP
/****************************************************************************
Reflect connection status in utmp / wtmp files .
T . D . Lee @ durham . ac . uk September 1999
Hints for porting :
o Always attempt to use programmatic interface ( pututline ( ) etc . )
o The " x " ( utmpx / wtmpx ; HAVE_UTMPX_H ) seems preferable .
OS status :
Solaris 2. x : Tested on 2.6 and 2.7 ; should be OK on other flavours .
T . D . Lee @ durham . ac . uk
HPUX 9. x : Not tested . Appears not to have " x " .
IRIX 6.5 : Not tested . Appears to have " x " .
Notes :
The 4 byte ' ut_id ' component is vital to distinguish connections ,
of which there could be several hundered or even thousand .
Entries seem to be printable characters , with optional NULL pads .
We need to be distinct from other entries in utmp / wtmp .
Observed things : therefore avoid them . Add to this list please .
From Solaris 2. x ( because that ' s what I have ) :
' sN ' : run - levels ; N : [ 0 - 9 ]
' co ' : console
' CC ' : arbitrary things ; C : [ a - z ]
' rXNN ' : rlogin ; N : [ 0 - 9 ] ; X : [ 0 - 9 a - z ]
' tXNN ' : rlogin ; N : [ 0 - 9 ] ; X : [ 0 - 9 a - z ]
' / NNN ' : Solaris CDE
' ftpZ ' : ftp ( Z is the number 255 , aka 0377 , aka 0xff )
Mostly a record uses the same ' ut_id ' in both " utmp " and " wtmp " ,
but differences have been seen .
Arbitrarily I have chosen to use a distinctive ' SM ' for the
first two bytes .
The remaining two encode the connection number used in samba locking
functions " claim_connection() and " yield_connection ( ) " . This seems
to be a " nicely behaved " number : starting from 0 then working up
looking for an available slot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <utmp.h>
# ifdef HAVE_UTMPX_H
# include <utmpx.h>
# endif
static const char * ut_id_encstr =
" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
static
int
ut_id_encode ( int i , char * fourbyte )
{
int nbase ;
fourbyte [ 0 ] = ' S ' ;
fourbyte [ 1 ] = ' M ' ;
/*
* Encode remaining 2 bytes from ' i ' .
* ' ut_id_encstr ' is the character set on which modulo arithmetic is done .
* Example : digits would produce the base - 10 numbers from ' 001 ' .
*/
nbase = strlen ( ut_id_encstr ) ;
fourbyte [ 3 ] = ut_id_encstr [ i % nbase ] ;
i / = nbase ;
fourbyte [ 2 ] = ut_id_encstr [ i % nbase ] ;
i / = nbase ;
return ( i ) ; /* 0: good; else overflow */
}
static int utmp_fill ( struct utmp * u , const connection_struct * conn , pid_t pid , int i )
{
struct timeval timeval ;
int rc ;
pstrcpy ( u - > ut_user , conn - > user ) ;
rc = ut_id_encode ( i , u - > ut_id ) ;
slprintf ( u - > ut_line , 12 , " smb/%d " , i ) ;
u - > ut_pid = pid ;
gettimeofday ( & timeval , NULL ) ;
u - > ut_time = timeval . tv_sec ;
return ( rc ) ;
}
static void utmp_update ( const pstring dirname , const struct utmp * u , const char * host )
{
pstring fname ;
# ifdef HAVE_UTMPX_H
struct utmpx ux , * uxrc ;
getutmpx ( u , & ux ) ;
if ( host ) {
ux . ut_syslen = strlen ( host ) ;
pstrcpy ( ux . ut_host , host ) ;
}
pstrcpy ( fname , dirname ) ;
pstrcat ( fname , " utmpx " ) ;
utmpxname ( fname ) ;
uxrc = pututxline ( & ux ) ;
if ( uxrc = = NULL ) {
DEBUG ( 2 , ( " utmp_update: pututxline() failed \n " ) ) ;
return ;
}
pstrcpy ( fname , dirname ) ;
pstrcat ( fname , " wtmpx " ) ;
updwtmpx ( fname , & ux ) ;
# else
pstrcpy ( fname , dirname ) ;
pstrcat ( fname , " utmp " ) ;
utmpname ( fname ) ;
pututline ( u ) ;
pstrcpy ( fname , dirname ) ;
pstrcat ( fname , " wtmp " ) ;
/* *** OK. Appending wtmp (as distinct from overwriting utmp) has
me baffled . How is it to be done ? * * * */
# endif
}
static void utmp_yield ( int pid , const connection_struct * conn )
{
struct utmp u ;
pstring dirname ;
if ( ! lp_utmp ( SNUM ( conn ) ) ) {
DEBUG ( 2 , ( " utmp_yield: lp_utmp() NULL \n " ) ) ;
return ;
}
pstrcpy ( dirname , lp_utmpdir ( ) ) ;
trim_string ( dirname , " " , " / " ) ;
pstrcat ( dirname , " / " ) ;
DEBUG ( 2 , ( " utmp_yield: dir:%s conn: user:%s cnum:%d i:%d \n " ,
dirname , conn - > user , conn - > cnum , conn - > cnum ) ) ;
memset ( ( char * ) & u , ' \0 ' , sizeof ( struct utmp ) ) ;
u . ut_type = DEAD_PROCESS ;
u . ut_exit . e_termination = 0 ;
u . ut_exit . e_exit = 0 ;
if ( utmp_fill ( & u , conn , pid , conn - > cnum ) = = 0 ) {
utmp_update ( dirname , & u , NULL ) ;
}
}
static void utmp_claim ( const struct connections_data * crec , const connection_struct * conn )
{
extern int Client ;
struct utmp u ;
pstring dirname ;
if ( conn = = NULL ) {
DEBUG ( 2 , ( " utmp_claim: conn NULL \n " ) ) ;
return ;
}
if ( ! lp_utmp ( SNUM ( conn ) ) ) {
DEBUG ( 2 , ( " utmp_claim: lp_utmp() NULL \n " ) ) ;
return ;
}
pstrcpy ( dirname , lp_utmpdir ( ) ) ;
trim_string ( dirname , " " , " / " ) ;
pstrcat ( dirname , " / " ) ;
DEBUG ( 2 , ( " utmp_claim: dir:%s conn: user:%s cnum:%d i:%d \n " ,
dirname , conn - > user , conn - > cnum , conn - > cnum ) ) ;
DEBUG ( 2 , ( " utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s \n " ,
crec - > pid , crec - > cnum , crec - > name , crec - > addr , crec - > machine , client_name ( Client ) ) ) ;
memset ( ( char * ) & u , ' \0 ' , sizeof ( struct utmp ) ) ;
u . ut_type = USER_PROCESS ;
if ( utmp_fill ( & u , conn , crec - > pid , conn - > cnum ) = = 0 ) {
utmp_update ( dirname , & u , crec - > machine ) ;
}
}
# endif