2003-06-25 22:08:00 +04:00
/*
Unix SMB / CIFS implementation .
Winbind daemon connection manager
Copyright ( C ) Tim Potter 2001
Copyright ( C ) Andrew Bartlett 2002
Copyright ( C ) Gerald ( Jerry ) Carter 2003
2008-06-05 02:22:50 +04:00
Copyright ( C ) Marc VanHeyningen 2008
2003-06-25 22:08:00 +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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-06-25 22:08:00 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-06-25 22:08:00 +04:00
*/
# include "includes.h"
2008-06-05 02:22:50 +04:00
/**
* @ file
* Negative connection cache implemented in terms of gencache API
*
* The negative connection cache stores names of servers which have
* been unresponsive so that we don ' t waste time repeatedly trying
* to contact them . It used to use an in - memory linked list , but
* this limited its utility to a single process
*/
/**
* prefix used for all entries put into the general cache
*/
static const char NEGATIVE_CONN_CACHE_PREFIX [ ] = " NEG_CONN_CACHE " ;
/**
* Marshalls the domain and server name into the key for the gencache
* record
*
* @ param [ in ] domain required
* @ param [ in ] server may be a FQDN or an IP address
* @ return the resulting string , which the caller is responsible for
* SAFE_FREE ( ) ing
* @ retval NULL returned on error
*/
static char * negative_conn_cache_keystr ( const char * domain , const char * server )
2003-06-25 22:08:00 +04:00
{
2008-06-05 02:22:50 +04:00
const char NEGATIVE_CONN_CACHE_KEY_FMT [ ] = " %s/%s,%s " ;
char * keystr = NULL ;
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
SMB_ASSERT ( domain ! = NULL ) ;
if ( server = = NULL )
server = " " ;
2008-06-05 11:00:37 +04:00
keystr = talloc_asprintf ( talloc_tos ( ) , NEGATIVE_CONN_CACHE_KEY_FMT ,
NEGATIVE_CONN_CACHE_PREFIX , domain , server ) ;
if ( keystr = = NULL ) {
2008-06-05 02:22:50 +04:00
DEBUG ( 0 , ( " negative_conn_cache_keystr: malloc error \n " ) ) ;
2008-06-05 11:00:37 +04:00
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
return keystr ;
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
/**
* Marshalls the NT status into a printable value field for the gencache
* record
*
* @ param [ in ] status
* @ return the resulting string , which the caller is responsible for
* SAFE_FREE ( ) ing
* @ retval NULL returned on error
*/
static char * negative_conn_cache_valuestr ( NTSTATUS status )
{
char * valuestr = NULL ;
2003-06-25 22:08:00 +04:00
2008-06-05 11:00:37 +04:00
valuestr = talloc_asprintf ( talloc_tos ( ) , " %x " , NT_STATUS_V ( status ) ) ;
if ( valuestr = = NULL ) {
2008-06-05 02:22:50 +04:00
DEBUG ( 0 , ( " negative_conn_cache_valuestr: malloc error \n " ) ) ;
2008-06-05 11:00:37 +04:00
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
return valuestr ;
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
/**
* Un - marshalls the NT status from a printable field for the gencache
* record
*
* @ param [ in ] value The value field from the record
* @ return the decoded NT status
* @ retval NT_STATUS_OK returned on error
*/
static NTSTATUS negative_conn_cache_valuedecode ( const char * value )
{
NTSTATUS result = NT_STATUS_OK ;
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
SMB_ASSERT ( value ! = NULL ) ;
if ( sscanf ( value , " %x " , & ( NT_STATUS_V ( result ) ) ) ! = 1 )
DEBUG ( 0 , ( " negative_conn_cache_valuestr: unable to parse "
" value field '%s' \n " , value ) ) ;
return result ;
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
/**
* Function passed to gencache_iterate to remove any matching items
* from the list
*
* @ param [ in ] key Key to the record found and to be deleted
* @ param [ in ] value Value to the record ( ignored )
* @ param [ in ] timeout Timeout remaining for the record ( ignored )
* @ param [ in ] dptr Handle for passing additional data ( ignored )
*/
static void delete_matches ( const char * key , const char * value ,
time_t timeout , void * dptr )
{
gencache_del ( key ) ;
2003-06-25 22:08:00 +04:00
}
2008-06-05 02:22:50 +04:00
/**
* Checks for a given domain / server record in the negative cache
*
* @ param [ in ] domain
* @ param [ in ] server may be either a FQDN or an IP address
* @ return The cached failure status
* @ retval NT_STATUS_OK returned if no record is found or an error occurs
*/
2006-02-04 01:19:41 +03:00
NTSTATUS check_negative_conn_cache ( const char * domain , const char * server )
{
2008-06-05 02:22:50 +04:00
NTSTATUS result = NT_STATUS_OK ;
char * key = NULL ;
char * value = NULL ;
key = negative_conn_cache_keystr ( domain , server ) ;
if ( key = = NULL )
goto done ;
if ( gencache_get ( key , & value , ( time_t * ) NULL ) )
result = negative_conn_cache_valuedecode ( value ) ;
done :
DEBUG ( 9 , ( " check_negative_conn_cache returning result %d for domain %s "
" server %s \n " , NT_STATUS_V ( result ) , domain , server ) ) ;
2008-06-05 11:00:37 +04:00
TALLOC_FREE ( key ) ;
2008-06-05 02:22:50 +04:00
SAFE_FREE ( value ) ;
return result ;
2006-02-04 01:19:41 +03:00
}
2008-06-05 02:22:50 +04:00
/**
* Delete any negative cache entry for the given domain / server
*
* @ param [ in ] domain
* @ param [ in ] server may be either a FQDN or an IP address
*/
void delete_negative_conn_cache ( const char * domain , const char * server )
2003-06-25 22:08:00 +04:00
{
2008-06-05 02:22:50 +04:00
char * key = NULL ;
key = negative_conn_cache_keystr ( domain , server ) ;
if ( key = = NULL )
goto done ;
gencache_del ( key ) ;
DEBUG ( 9 , ( " delete_negative_conn_cache removing domain %s server %s \n " ,
domain , server ) ) ;
done :
2008-06-05 11:00:37 +04:00
TALLOC_FREE ( key ) ;
2008-06-05 02:22:50 +04:00
return ;
}
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
/**
2008-09-04 02:31:39 +04:00
* Add an entry to the failed connection cache
2008-06-05 02:22:50 +04:00
*
* @ param [ in ] domain
* @ param [ in ] server may be a FQDN or an IP addr in printable form
* @ param [ in ] result error to cache ; must not be NT_STATUS_OK
*/
void add_failed_connection_entry ( const char * domain , const char * server ,
NTSTATUS result )
{
char * key = NULL ;
char * value = NULL ;
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
SMB_ASSERT ( ! NT_STATUS_IS_OK ( result ) ) ;
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
key = negative_conn_cache_keystr ( domain , server ) ;
if ( key = = NULL ) {
DEBUG ( 0 , ( " add_failed_connection_entry: key creation error \n " ) ) ;
goto done ;
2003-06-25 22:08:00 +04:00
}
2008-06-05 11:00:37 +04:00
2008-06-05 02:22:50 +04:00
value = negative_conn_cache_valuestr ( result ) ;
if ( value = = NULL ) {
DEBUG ( 0 , ( " add_failed_connection_entry: value creation error \n " ) ) ;
goto done ;
}
2008-06-05 11:00:37 +04:00
2008-06-05 02:22:50 +04:00
if ( gencache_set ( key , value ,
2008-06-05 11:36:34 +04:00
time ( ( time_t * ) NULL )
+ FAILED_CONNECTION_CACHE_TIMEOUT ) )
2008-06-05 02:22:50 +04:00
DEBUG ( 9 , ( " add_failed_connection_entry: added domain %s (%s) "
" to failed conn cache \n " , domain , server ) ) ;
else
DEBUG ( 1 , ( " add_failed_connection_entry: failed to add "
" domain %s (%s) to failed conn cache \n " ,
domain , server ) ) ;
2003-06-25 22:08:00 +04:00
2008-06-05 02:22:50 +04:00
done :
2008-06-05 11:00:37 +04:00
TALLOC_FREE ( key ) ;
TALLOC_FREE ( value ) ;
2008-06-05 02:22:50 +04:00
return ;
2003-06-25 22:08:00 +04:00
}
2008-06-05 02:22:50 +04:00
/**
* Deletes all records from the negative connection cache in all domains
*/
2003-06-25 22:08:00 +04:00
void flush_negative_conn_cache ( void )
{
2008-06-05 02:22:50 +04:00
flush_negative_conn_cache_for_domain ( " * " ) ;
2003-06-25 22:08:00 +04:00
}
2006-09-14 20:37:13 +04:00
2008-06-05 02:22:50 +04:00
/**
* Deletes all records for a specified domain from the negative connection
* cache
*
* @ param [ in ] domain String to match against domain portion of keys , or " * "
* to match all domains
*/
2006-09-14 20:37:13 +04:00
void flush_negative_conn_cache_for_domain ( const char * domain )
{
2008-06-05 02:22:50 +04:00
char * key_pattern = NULL ;
2006-09-14 20:37:13 +04:00
2008-06-05 02:22:50 +04:00
key_pattern = negative_conn_cache_keystr ( domain , " * " ) ;
if ( key_pattern = = NULL ) {
DEBUG ( 0 , ( " flush_negative_conn_cache_for_domain: "
" key creation error \n " ) ) ;
goto done ;
2006-09-14 20:37:13 +04:00
}
2008-06-05 02:22:50 +04:00
gencache_iterate ( delete_matches , ( void * ) NULL , key_pattern ) ;
DEBUG ( 8 , ( " flush_negative_conn_cache_for_domain: flushed domain %s \n " ,
domain ) ) ;
done :
2008-06-05 11:00:37 +04:00
TALLOC_FREE ( key_pattern ) ;
2008-06-05 02:22:50 +04:00
return ;
2006-09-14 20:37:13 +04:00
}