2007-10-25 01:16:54 +04:00
/*
2002-08-16 04:25:48 +04:00
Unix SMB / CIFS implementation .
2003-01-04 11:48:15 +03:00
NetBIOS name cache module on top of gencache mechanism .
2007-10-25 01:16:54 +04:00
2003-01-04 11:48:15 +03:00
Copyright ( C ) Tim Potter 2002
Copyright ( C ) Rafal Szczesniak 2002
2007-10-25 01:16:54 +04:00
Copyright ( C ) Jeremy Allison 2007
2002-08-16 04:25:48 +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
2002-08-16 04:25:48 +04:00
( at your option ) any later version .
2007-10-25 01:16:54 +04:00
2002-08-16 04:25:48 +04: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 .
2007-10-25 01:16:54 +04:00
2002-08-16 04:25:48 +04:00
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/>.
2002-08-16 04:25:48 +04:00
*/
# include "includes.h"
2003-01-04 11:48:15 +03:00
# define NBTKEY_FMT "NBT / %s#%02X"
2002-08-16 04:25:48 +04:00
2003-01-04 11:48:15 +03:00
/**
* Generates a key for netbios name lookups on basis of
* netbios name and type .
* The caller must free returned key string when finished .
*
* @ param name netbios name string ( case insensitive )
* @ param name_type netbios type of the name being looked up
*
* @ return string consisted of uppercased name and appended
* type number
*/
2002-08-16 04:25:48 +04:00
2007-10-25 01:16:54 +04:00
static char * namecache_key ( const char * name ,
int name_type )
2003-01-04 11:48:15 +03:00
{
char * keystr ;
2007-11-24 19:27:54 +03:00
asprintf_strupper_m ( & keystr , NBTKEY_FMT , name , name_type ) ;
2002-08-16 04:25:48 +04:00
2003-01-04 11:48:15 +03:00
return keystr ;
2002-08-16 04:25:48 +04:00
}
2003-01-04 11:48:15 +03:00
/**
* Store a name ( s ) in the name cache
*
* @ param name netbios names array
* @ param name_type integer netbios name type
* @ param num_names number of names being stored
* @ param ip_list array of in_addr structures containing
* ip addresses being stored
* */
2007-10-25 01:16:54 +04:00
bool namecache_store ( const char * name ,
int name_type ,
int num_names ,
struct ip_service * ip_list )
2002-08-16 04:25:48 +04:00
{
time_t expiry ;
2003-01-04 11:48:15 +03:00
char * key , * value_string ;
2002-08-16 04:25:48 +04:00
int i ;
2007-10-19 04:40:25 +04:00
bool ret ;
2002-08-16 04:25:48 +04:00
2006-09-02 23:27:44 +04:00
if ( name_type > 255 ) {
return False ; /* Don't store non-real name types. */
}
2003-06-25 21:41:05 +04:00
if ( DEBUGLEVEL > = 5 ) {
2007-10-25 01:16:54 +04:00
TALLOC_CTX * ctx = talloc_stackframe ( ) ;
char * addr = NULL ;
2003-06-25 21:41:05 +04:00
DEBUG ( 5 , ( " namecache_store: storing %d address%s for %s#%02x: " ,
num_names , num_names = = 1 ? " " : " es " , name , name_type ) ) ;
2002-08-16 04:25:48 +04:00
2007-10-25 01:16:54 +04:00
for ( i = 0 ; i < num_names ; i + + ) {
addr = print_canonical_sockaddr ( ctx ,
& ip_list [ i ] . ss ) ;
if ( ! addr ) {
continue ;
}
DEBUGADD ( 5 , ( " %s%s " , addr ,
( i = = ( num_names - 1 ) ? " " : " , " ) ) ) ;
}
2003-06-25 21:41:05 +04:00
DEBUGADD ( 5 , ( " \n " ) ) ;
2007-10-25 01:16:54 +04:00
TALLOC_FREE ( ctx ) ;
2003-06-25 21:41:05 +04:00
}
2007-10-25 01:16:54 +04:00
2002-08-16 04:25:48 +04:00
key = namecache_key ( name , name_type ) ;
2006-10-11 22:54:40 +04:00
if ( ! key ) {
return False ;
}
2003-06-14 01:03:15 +04:00
expiry = time ( NULL ) + lp_name_cache_timeout ( ) ;
2002-08-16 04:25:48 +04:00
2003-01-04 11:48:15 +03:00
/*
* Generate string representation of ip addresses list
* First , store the number of ip addresses and then
* place each single ip
*/
2003-03-23 02:32:50 +03:00
if ( ! ipstr_list_make ( & value_string , ip_list , num_names ) ) {
SAFE_FREE ( key ) ;
SAFE_FREE ( value_string ) ;
2007-10-25 01:16:54 +04:00
return false ;
2003-03-23 02:32:50 +03:00
}
2007-10-25 01:16:54 +04:00
2003-01-04 11:48:15 +03:00
/* set the entry */
2003-03-23 02:32:50 +03:00
ret = gencache_set ( key , value_string , expiry ) ;
SAFE_FREE ( key ) ;
SAFE_FREE ( value_string ) ;
return ret ;
2002-08-16 04:25:48 +04:00
}
2003-01-04 11:48:15 +03:00
/**
* Look up a name in the cache .
*
* @ param name netbios name to look up for
* @ param name_type netbios name type of @ param name
* @ param ip_list mallocated list of IP addresses if found in the cache ,
* NULL otherwise
* @ param num_names number of entries found
*
* @ return true upon successful fetch or
* false if name isn ' t found in the cache or has expired
* */
2002-08-16 04:25:48 +04:00
2007-10-25 01:16:54 +04:00
bool namecache_fetch ( const char * name ,
int name_type ,
struct ip_service * * ip_list ,
int * num_names )
2002-08-16 04:25:48 +04:00
{
2003-01-04 11:48:15 +03:00
char * key , * value ;
2008-07-11 19:44:25 +04:00
time_t timeout ;
2002-08-16 04:25:48 +04:00
2003-01-04 11:48:15 +03:00
/* exit now if null pointers were passed as they're required further */
2007-10-25 01:16:54 +04:00
if ( ! ip_list | | ! num_names ) {
return False ;
}
2002-08-16 04:25:48 +04:00
2006-09-02 23:27:44 +04:00
if ( name_type > 255 ) {
return False ; /* Don't fetch non-real name types. */
}
2006-08-28 09:10:56 +04:00
* num_names = 0 ;
2007-10-25 01:16:54 +04:00
/*
2003-01-04 11:48:15 +03:00
* Use gencache interface - lookup the key
*/
2002-08-16 04:25:48 +04:00
key = namecache_key ( name , name_type ) ;
2006-10-11 22:54:40 +04:00
if ( ! key ) {
return False ;
}
2002-08-16 04:25:48 +04:00
2008-07-11 19:44:25 +04:00
if ( ! gencache_get ( key , & value , & timeout ) ) {
2003-01-04 11:48:15 +03:00
DEBUG ( 5 , ( " no entry for %s#%02X found. \n " , name , name_type ) ) ;
SAFE_FREE ( key ) ;
return False ;
2002-09-25 19:19:00 +04:00
}
2007-10-25 01:16:54 +04:00
2011-01-12 12:26:49 +03:00
DEBUG ( 5 , ( " name %s#%02X found. \n " , name , name_type ) ) ;
2003-01-04 11:48:15 +03:00
/*
* Split up the stored value into the list of IP adresses
*/
* num_names = ipstr_list_parse ( value , ip_list ) ;
2007-10-25 01:16:54 +04:00
2003-01-04 11:48:15 +03:00
SAFE_FREE ( key ) ;
2003-06-25 21:41:05 +04:00
SAFE_FREE ( value ) ;
2007-10-25 01:16:54 +04:00
return * num_names > 0 ; /* true only if some ip has been fetched */
2003-01-04 11:48:15 +03:00
}
2002-08-16 04:25:48 +04:00
2006-10-11 22:54:40 +04:00
/**
* Remove a namecache entry . Needed for site support .
*
* */
2007-10-19 04:40:25 +04:00
bool namecache_delete ( const char * name , int name_type )
2006-10-11 22:54:40 +04:00
{
2007-10-19 04:40:25 +04:00
bool ret ;
2006-10-11 22:54:40 +04:00
char * key ;
if ( name_type > 255 ) {
return False ; /* Don't fetch non-real name types. */
}
key = namecache_key ( name , name_type ) ;
if ( ! key ) {
return False ;
}
ret = gencache_del ( key ) ;
SAFE_FREE ( key ) ;
return ret ;
}
2002-08-16 04:25:48 +04:00
2003-01-04 11:48:15 +03:00
/**
* Delete single namecache entry . Look at the
* gencache_iterate definition .
*
* */
2002-08-16 04:25:48 +04:00
2007-10-25 01:16:54 +04:00
static void flush_netbios_name ( const char * key ,
const char * value ,
time_t timeout ,
void * dptr )
2003-01-04 11:48:15 +03:00
{
gencache_del ( key ) ;
DEBUG ( 5 , ( " Deleting entry %s \n " , key ) ) ;
2002-08-16 04:25:48 +04:00
}
2003-01-04 11:48:15 +03:00
/**
* Flush all names from the name cache .
* It ' s done by gencache_iterate ( )
*
2007-10-25 01:16:54 +04:00
* @ return true upon successful deletion or
* false in case of an error
2003-01-04 11:48:15 +03:00
* */
2002-08-16 04:25:48 +04:00
void namecache_flush ( void )
{
2007-10-25 01:16:54 +04:00
/*
2003-01-04 11:48:15 +03:00
* iterate through each NBT cache ' s entry and flush it
* by flush_netbios_name function
*/
gencache_iterate ( flush_netbios_name , NULL , " NBT/* " ) ;
DEBUG ( 5 , ( " Namecache flushed \n " ) ) ;
2002-08-16 04:25:48 +04:00
}
2003-01-04 11:48:15 +03:00
2003-06-14 01:03:15 +04:00
/* Construct a name status record key. */
2007-10-25 01:16:54 +04:00
static char * namecache_status_record_key ( const char * name ,
int name_type1 ,
int name_type2 ,
const struct sockaddr_storage * keyip )
2003-06-14 01:03:15 +04:00
{
2007-10-25 01:16:54 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2003-06-14 01:03:15 +04:00
char * keystr ;
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , keyip ) ;
2007-11-24 19:27:54 +03:00
asprintf_strupper_m ( & keystr , " NBT/%s#%02X.%02X.%s " , name ,
name_type1 , name_type2 , addr ) ;
2003-06-14 01:03:15 +04:00
return keystr ;
}
/* Store a name status record. */
2007-10-19 04:40:25 +04:00
bool namecache_status_store ( const char * keyname , int keyname_type ,
2007-10-25 01:16:54 +04:00
int name_type , const struct sockaddr_storage * keyip ,
2003-06-14 01:03:15 +04:00
const char * srvname )
{
char * key ;
time_t expiry ;
2007-10-19 04:40:25 +04:00
bool ret ;
2003-06-14 01:03:15 +04:00
2007-10-25 01:16:54 +04:00
key = namecache_status_record_key ( keyname , keyname_type ,
name_type , keyip ) ;
2003-06-14 01:03:15 +04:00
if ( ! key )
return False ;
expiry = time ( NULL ) + lp_name_cache_timeout ( ) ;
ret = gencache_set ( key , srvname , expiry ) ;
2007-10-25 01:16:54 +04:00
if ( ret ) {
DEBUG ( 5 , ( " namecache_status_store: entry %s -> %s \n " ,
key , srvname ) ) ;
} else {
DEBUG ( 5 , ( " namecache_status_store: entry %s store failed. \n " ,
key ) ) ;
}
2003-06-14 01:03:15 +04:00
SAFE_FREE ( key ) ;
return ret ;
}
/* Fetch a name status record. */
2007-10-25 01:16:54 +04:00
bool namecache_status_fetch ( const char * keyname ,
int keyname_type ,
int name_type ,
const struct sockaddr_storage * keyip ,
char * srvname_out )
2003-06-14 01:03:15 +04:00
{
char * key = NULL ;
char * value = NULL ;
2008-07-11 19:44:25 +04:00
time_t timeout ;
2003-06-14 01:03:15 +04:00
2007-10-25 01:16:54 +04:00
key = namecache_status_record_key ( keyname , keyname_type ,
name_type , keyip ) ;
2003-06-14 01:03:15 +04:00
if ( ! key )
return False ;
2008-07-11 19:44:25 +04:00
if ( ! gencache_get ( key , & value , & timeout ) ) {
2007-10-25 01:16:54 +04:00
DEBUG ( 5 , ( " namecache_status_fetch: no entry for %s found. \n " ,
key ) ) ;
2003-06-14 01:03:15 +04:00
SAFE_FREE ( key ) ;
return False ;
} else {
2007-10-25 01:16:54 +04:00
DEBUG ( 5 , ( " namecache_status_fetch: key %s -> %s \n " ,
key , value ) ) ;
2003-06-14 01:03:15 +04:00
}
strlcpy ( srvname_out , value , 16 ) ;
SAFE_FREE ( key ) ;
SAFE_FREE ( value ) ;
return True ;
}