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-01-12 06:09:17 +03:00
# 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
1999-12-21 07:54:30 +03:00
/****************************************************************************
delete a connection record
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ( ) ;
1999-12-21 07:54:30 +03:00
if ( conn ) key . cnum = conn - > cnum ;
fstrcpy ( key . name , name ) ;
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
# ifdef WITH_UTMP
if ( conn )
utmp_yield ( key . pid , conn ) ;
# endif
1998-03-15 05:37:52 +03:00
return ( True ) ;
}
1999-12-21 07:54:30 +03:00
/****************************************************************************
claim an entry in the connections database
1998-03-15 05:37:52 +03: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 ;
TDB_DATA kbuf , dbuf ;
1998-03-15 05:37:52 +03:00
if ( max_connections < = 0 )
return ( True ) ;
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 ) ;
}
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 ( 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 ) ;
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 ) ;
if ( tdb_store ( tdb , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) return False ;
2000-01-12 06:09:17 +03:00
# ifdef WITH_UTMP
if ( conn )
utmp_claim ( & crec , conn ) ;
# endif
1999-12-21 07:54:30 +03:00
return True ;
1998-03-15 05:37:52 +03:00
}
2000-01-12 06:09:17 +03:00
# 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 ) ;
}
2000-03-25 04:37:08 +03:00
/* Default path (if possible) */
# ifdef HAVE_UTMPX_H
# ifdef UTMPX_FILE
static char * ut_pathname = UTMPX_FILE ;
# else
static char * ut_pathname = " " ;
# endif
# ifdef WTMPX_FILE
static char * wt_pathname = WTMPX_FILE ;
# else
static char * wt_pathname = " " ;
# endif
# else /* HAVE_UTMPX_H */
# ifdef UTMP_FILE
static char * ut_pathname = UTMP_FILE ;
# else
static char * ut_pathname = " " ;
# endif
# ifdef WTMP_FILE
static char * wt_pathname = WTMP_FILE ;
# else
static char * wt_pathname = " " ;
# endif
# endif /* HAVE_UTMPX_H */
static void uw_pathname ( pstring fname , const char * uw_name )
{
pstring dirname ;
pstrcpy ( dirname , lp_utmpdir ( ) ) ;
trim_string ( dirname , " " , " / " ) ;
/* Given directory: use it */
if ( dirname ! = 0 & & strlen ( dirname ) ! = 0 ) {
pstrcpy ( fname , dirname ) ;
pstrcat ( fname , " / " ) ;
pstrcat ( fname , uw_name ) ;
return ;
}
/* No given directory: attempt to use default paths */
if ( uw_name [ 0 ] = = ' u ' ) {
pstrcpy ( fname , ut_pathname ) ;
return ;
}
if ( uw_name [ 0 ] = = ' w ' ) {
pstrcpy ( fname , wt_pathname ) ;
return ;
}
pstrcpy ( fname , " " ) ;
}
static void utmp_update ( const struct utmp * u , const char * host )
2000-01-12 06:09:17 +03:00
{
pstring fname ;
# ifdef HAVE_UTMPX_H
struct utmpx ux , * uxrc ;
getutmpx ( u , & ux ) ;
if ( host ) {
2000-03-22 22:03:12 +03:00
# if defined(HAVE_UX_UT_SYSLEN)
2000-01-12 06:09:17 +03:00
ux . ut_syslen = strlen ( host ) ;
2000-03-22 22:03:12 +03:00
# endif /* defined(HAVE_UX_UT_SYSLEN) */
2000-01-12 06:09:17 +03:00
pstrcpy ( ux . ut_host , host ) ;
}
2000-03-25 04:37:08 +03:00
uw_pathname ( fname , " utmpx " ) ;
DEBUG ( 2 , ( " utmp_update: fname:%s \n " , fname ) ) ;
if ( strlen ( fname ) ! = 0 ) {
utmpxname ( fname ) ;
}
2000-01-12 06:09:17 +03:00
uxrc = pututxline ( & ux ) ;
if ( uxrc = = NULL ) {
DEBUG ( 2 , ( " utmp_update: pututxline() failed \n " ) ) ;
return ;
}
2000-03-25 04:37:08 +03:00
uw_pathname ( fname , " wtmpx " ) ;
DEBUG ( 2 , ( " utmp_update: fname:%s \n " , fname ) ) ;
if ( strlen ( fname ) ! = 0 ) {
updwtmpx ( fname , & ux ) ;
}
2000-01-12 06:09:17 +03:00
# else
2000-03-25 04:37:08 +03:00
uw_pathname ( fname , " utmp " ) ;
DEBUG ( 2 , ( " utmp_update: fname:%s \n " , fname ) ) ;
if ( strlen ( fname ) ! = 0 ) {
utmpname ( fname ) ;
}
2000-01-12 06:09:17 +03:00
pututline ( u ) ;
2000-03-25 04:37:08 +03:00
uw_pathname ( fname , " wtmp " ) ;
2000-01-12 06:09:17 +03:00
2000-03-25 04:37:08 +03:00
/* *** Hmmm. Appending wtmp (as distinct from overwriting utmp) has
2000-01-12 06:09:17 +03:00
me baffled . How is it to be done ? * * * */
# endif
}
2000-03-25 04:37:08 +03:00
static void utmp_yield ( pid_t pid , const connection_struct * conn )
2000-01-12 06:09:17 +03:00
{
struct utmp u ;
if ( ! lp_utmp ( SNUM ( conn ) ) ) {
DEBUG ( 2 , ( " utmp_yield: lp_utmp() NULL \n " ) ) ;
return ;
}
2000-04-10 06:44:06 +04:00
DEBUG ( 2 , ( " utmp_yield: conn: user:%s cnum:%d \n " ,
conn - > user , conn - > cnum ) ) ;
2000-01-12 06:09:17 +03:00
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 ) {
2000-03-25 04:37:08 +03:00
utmp_update ( & u , NULL ) ;
2000-01-12 06:09:17 +03:00
}
}
2000-03-25 04:37:08 +03:00
static void utmp_claim ( const struct connect_record * crec , const connection_struct * conn )
2000-01-12 06:09:17 +03:00
{
struct utmp u ;
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 ;
}
2000-03-25 04:37:08 +03:00
DEBUG ( 2 , ( " utmp_claim: conn: user:%s cnum:%d i:%d \n " ,
conn - > user , conn - > cnum , i ) ) ;
2000-01-12 06:09:17 +03:00
DEBUG ( 2 , ( " utmp_claim: crec: pid:%d, cnum:%d name:%s addr:%s mach:%s DNS:%s \n " ,
2000-04-11 17:55:53 +04:00
crec - > pid , crec - > cnum , crec - > name , crec - > addr , crec - > machine , client_name ( ) ) ) ;
2000-01-12 06:09:17 +03:00
memset ( ( char * ) & u , ' \0 ' , sizeof ( struct utmp ) ) ;
u . ut_type = USER_PROCESS ;
if ( utmp_fill ( & u , conn , crec - > pid , conn - > cnum ) = = 0 ) {
2000-03-25 04:37:08 +03:00
utmp_update ( & u , crec - > machine ) ;
2000-01-12 06:09:17 +03:00
}
}
# endif