1997-12-13 17:16:07 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1997-12-13 17:16:07 +03:00
NBT netbios routines and daemon - version 2
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1994 - 1998
2003-08-27 05:25:01 +04:00
Copyright ( C ) Jeremy Allison 1994 - 2003
1997-12-13 17:16:07 +03: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
1997-12-13 17:16:07 +03: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/>.
1997-12-13 17:16:07 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-08-18 17:22:09 +04:00
# include "nmbd/nmbd.h"
1997-12-13 17:16:07 +03:00
uint16 samba_nb_type = 0 ; /* samba's NetBIOS name type */
2003-08-27 05:25:01 +04:00
/**************************************************************************
Set Samba ' s NetBIOS name type .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
void set_samba_nb_type ( void )
2003-08-27 05:25:01 +04:00
{
2011-07-01 09:14:08 +04:00
if ( lp_we_are_a_wins_server ( ) | | wins_srv_count ( ) ) {
2003-08-27 05:25:01 +04:00
samba_nb_type = NB_HFLAG ; /* samba is a 'hybrid' node type. */
2005-12-07 02:06:38 +03:00
} else {
2003-08-27 05:25:01 +04:00
samba_nb_type = NB_BFLAG ; /* samba is broadcast-only node type. */
2005-12-07 02:06:38 +03:00
}
2003-08-27 05:25:01 +04:00
}
/***************************************************************************
Convert a NetBIOS name to upper case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-08-09 02:35:28 +04:00
static bool upcase_name ( struct nmb_name * target , const struct nmb_name * source )
2003-08-27 05:25:01 +04:00
{
int i ;
2004-03-16 00:45:45 +03:00
unstring targ ;
2003-08-27 05:25:01 +04:00
fstring scope ;
2005-12-07 02:06:38 +03:00
if ( NULL ! = source ) {
2003-08-27 05:25:01 +04:00
memcpy ( target , source , sizeof ( struct nmb_name ) ) ;
2005-12-07 02:06:38 +03:00
}
2003-08-27 05:25:01 +04:00
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( targ , sizeof ( targ ) , target - > name ) ;
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( targ ) ) {
return false ;
}
2003-08-27 05:25:01 +04:00
push_ascii_nstring ( target - > name , targ ) ;
pull_ascii ( scope , target - > scope , 64 , - 1 , STR_TERMINATE ) ;
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( scope ) ) {
return false ;
}
2003-08-27 05:25:01 +04:00
push_ascii ( target - > scope , scope , 64 , STR_TERMINATE ) ;
/* fudge... We're using a byte-by-byte compare, so we must be sure that
* unused space doesn ' t have garbage in it .
*/
2005-12-07 02:06:38 +03:00
for ( i = strlen ( target - > name ) ; i < sizeof ( target - > name ) ; i + + ) {
2003-08-27 05:25:01 +04:00
target - > name [ i ] = ' \0 ' ;
2005-12-07 02:06:38 +03:00
}
for ( i = strlen ( target - > scope ) ; i < sizeof ( target - > scope ) ; i + + ) {
2003-08-27 05:25:01 +04:00
target - > scope [ i ] = ' \0 ' ;
}
2012-08-09 02:35:28 +04:00
return true ;
2003-08-27 05:25:01 +04:00
}
1998-08-30 08:27:26 +04:00
2003-08-27 05:25:01 +04:00
/**************************************************************************
Remove a name from the namelist .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-07 02:06:38 +03:00
void remove_name_from_namelist ( struct subnet_record * subrec ,
struct name_record * namerec )
2003-08-27 05:25:01 +04:00
{
2006-01-23 17:02:17 +03:00
if ( subrec = = wins_server_subnet )
2005-12-07 02:06:38 +03:00
remove_name_from_wins_namelist ( namerec ) ;
2006-01-23 17:02:17 +03:00
else {
subrec - > namelist_changed = True ;
DLIST_REMOVE ( subrec - > namelist , namerec ) ;
}
2006-01-15 15:30:36 +03:00
2003-08-27 05:25:01 +04:00
SAFE_FREE ( namerec - > data . ip ) ;
ZERO_STRUCTP ( namerec ) ;
SAFE_FREE ( namerec ) ;
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/**************************************************************************
Find a name in a subnet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-10 23:51:58 +04:00
2005-12-07 02:06:38 +03:00
struct name_record * find_name_on_subnet ( struct subnet_record * subrec ,
const struct nmb_name * nmbname ,
2007-10-19 04:40:25 +04:00
bool self_only )
2003-08-27 05:25:01 +04:00
{
2005-12-07 02:06:38 +03:00
struct nmb_name uc_name ;
2003-08-27 05:25:01 +04:00
struct name_record * name_ret ;
2012-08-09 02:35:28 +04:00
if ( ! upcase_name ( & uc_name , nmbname ) ) {
return NULL ;
}
2005-12-07 02:06:38 +03:00
if ( subrec = = wins_server_subnet ) {
return find_name_on_wins_subnet ( & uc_name , self_only ) ;
}
for ( name_ret = subrec - > namelist ; name_ret ; name_ret = name_ret - > next ) {
if ( memcmp ( & uc_name , & name_ret - > name , sizeof ( struct nmb_name ) ) = = 0 ) {
break ;
}
}
2003-08-27 05:25:01 +04:00
if ( name_ret ) {
/* Self names only - these include permanent names. */
if ( self_only & & ( name_ret - > data . source ! = SELF_NAME ) & & ( name_ret - > data . source ! = PERMANENT_NAME ) ) {
DEBUG ( 9 , ( " find_name_on_subnet: on subnet %s - self name %s NOT FOUND \n " ,
subrec - > subnet_name , nmb_namestr ( nmbname ) ) ) ;
2006-06-29 04:48:44 +04:00
return NULL ;
2003-08-27 05:25:01 +04:00
}
DEBUG ( 9 , ( " find_name_on_subnet: on subnet %s - found name %s source=%d \n " ,
subrec - > subnet_name , nmb_namestr ( nmbname ) , name_ret - > data . source ) ) ;
2005-12-07 02:06:38 +03:00
return name_ret ;
2003-08-27 05:25:01 +04:00
}
DEBUG ( 9 , ( " find_name_on_subnet: on subnet %s - name %s NOT FOUND \n " ,
subrec - > subnet_name , nmb_namestr ( nmbname ) ) ) ;
2005-12-07 02:06:38 +03:00
return NULL ;
2003-08-27 05:25:01 +04:00
}
/**************************************************************************
Find a name over all known broadcast subnets .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-07 02:06:38 +03:00
struct name_record * find_name_for_remote_broadcast_subnet ( struct nmb_name * nmbname ,
2007-10-19 04:40:25 +04:00
bool self_only )
2003-08-27 05:25:01 +04:00
{
struct subnet_record * subrec ;
2005-12-07 02:06:38 +03:00
struct name_record * namerec ;
2003-08-27 05:25:01 +04:00
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST ( subrec ) ) {
2005-12-07 02:06:38 +03:00
namerec = find_name_on_subnet ( subrec , nmbname , self_only ) ;
if ( namerec ) {
return namerec ;
}
2003-08-27 05:25:01 +04:00
}
2005-12-07 02:06:38 +03:00
return NULL ;
2003-08-27 05:25:01 +04:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/**************************************************************************
Update the ttl of an entry in a subnet name list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-09 05:56:18 +04:00
void update_name_ttl ( struct name_record * namerec , int ttl )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
time_t time_now = time ( NULL ) ;
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
if ( namerec - > data . death_time ! = PERMANENT_TTL ) {
2003-08-27 05:25:01 +04:00
namerec - > data . death_time = time_now + ttl ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
namerec - > data . refresh_time = time_now + MIN ( ( ttl / 2 ) , MAX_REFRESH_TIME ) ;
2005-12-07 02:06:38 +03:00
if ( namerec - > subnet = = wins_server_subnet ) {
wins_store_changed_namerec ( namerec ) ;
} else {
namerec - > subnet - > namelist_changed = True ;
}
2003-08-27 05:25:01 +04:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/**************************************************************************
Add an entry to a subnet name list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-10 23:51:58 +04:00
2007-10-19 04:40:25 +04:00
bool add_name_to_subnet ( struct subnet_record * subrec ,
2005-12-07 02:06:38 +03:00
const char * name ,
int type ,
uint16 nb_flags ,
int ttl ,
enum name_source source ,
int num_ips ,
struct in_addr * iplist )
1997-12-13 17:16:07 +03:00
{
2007-10-19 04:40:25 +04:00
bool ret = False ;
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
time_t time_now = time ( NULL ) ;
1997-12-13 17:16:07 +03:00
2007-11-16 04:59:12 +03:00
if ( num_ips = = 0 ) {
return false ;
}
2004-12-07 21:25:53 +03:00
namerec = SMB_MALLOC_P ( struct name_record ) ;
2003-08-27 05:25:01 +04:00
if ( NULL = = namerec ) {
DEBUG ( 0 , ( " add_name_to_subnet: malloc fail. \n " ) ) ;
2005-12-07 02:06:38 +03:00
return False ;
2003-08-27 05:25:01 +04:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
memset ( ( char * ) namerec , ' \0 ' , sizeof ( * namerec ) ) ;
2004-12-07 21:25:53 +03:00
namerec - > data . ip = SMB_MALLOC_ARRAY ( struct in_addr , num_ips ) ;
2003-08-27 05:25:01 +04:00
if ( NULL = = namerec - > data . ip ) {
DEBUG ( 0 , ( " add_name_to_subnet: malloc fail when creating ip_flgs. \n " ) ) ;
ZERO_STRUCTP ( namerec ) ;
SAFE_FREE ( namerec ) ;
2005-12-07 02:06:38 +03:00
return False ;
2003-08-27 05:25:01 +04:00
}
1998-08-30 08:27:26 +04:00
2003-08-27 05:25:01 +04:00
namerec - > subnet = subrec ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
make_nmb_name ( & namerec - > name , name , type ) ;
2012-08-09 02:35:28 +04:00
if ( ! upcase_name ( & namerec - > name , NULL ) ) {
SAFE_FREE ( namerec - > data . ip ) ;
SAFE_FREE ( namerec ) ;
return False ;
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Enter the name as active. */
namerec - > data . nb_flags = nb_flags | NB_ACTIVE ;
namerec - > data . wins_flags = WINS_ACTIVE ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* If it's our primary name, flag it as so. */
2005-12-07 02:06:38 +03:00
if ( strequal ( my_netbios_names ( 0 ) , name ) ) {
2003-08-27 05:25:01 +04:00
namerec - > data . nb_flags | = NB_PERM ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Copy the IPs. */
namerec - > data . num_ips = num_ips ;
memcpy ( ( namerec - > data . ip ) , iplist , num_ips * sizeof ( struct in_addr ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Data source. */
namerec - > data . source = source ;
1998-06-10 23:51:58 +04:00
2003-08-27 05:25:01 +04:00
/* Setup the death_time and refresh_time. */
2005-12-07 02:06:38 +03:00
if ( ttl = = PERMANENT_TTL ) {
2003-08-27 05:25:01 +04:00
namerec - > data . death_time = PERMANENT_TTL ;
2005-12-07 02:06:38 +03:00
} else {
2003-08-27 05:25:01 +04:00
namerec - > data . death_time = time_now + ttl ;
2005-12-07 02:06:38 +03:00
}
1998-06-10 23:51:58 +04:00
2003-08-27 05:25:01 +04:00
namerec - > data . refresh_time = time_now + MIN ( ( ttl / 2 ) , MAX_REFRESH_TIME ) ;
1998-06-10 23:51:58 +04:00
2003-08-27 05:25:01 +04:00
DEBUG ( 3 , ( " add_name_to_subnet: Added netbios name %s with first IP %s \
1998-06-09 05:56:18 +04:00
ttl = % d nb_flags = % 2 x to subnet % s \ n " ,
2003-08-27 05:25:01 +04:00
nmb_namestr ( & namerec - > name ) ,
inet_ntoa ( * iplist ) ,
ttl ,
( unsigned int ) nb_flags ,
subrec - > subnet_name ) ) ;
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
/* Now add the record to the name list. */
if ( subrec = = wins_server_subnet ) {
ret = add_name_to_wins_subnet ( namerec ) ;
/* Free namerec - it's stored in the tdb. */
SAFE_FREE ( namerec - > data . ip ) ;
SAFE_FREE ( namerec ) ;
} else {
DLIST_ADD ( subrec - > namelist , namerec ) ;
subrec - > namelist_changed = True ;
ret = True ;
}
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
return ret ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function automatically called when a name refresh or register
succeeds . By definition this is a SELF_NAME ( or we wouldn ' t be registering
it ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void standard_success_register ( struct subnet_record * subrec ,
struct userdata_struct * userdata ,
struct nmb_name * nmbname , uint16 nb_flags , int ttl ,
struct in_addr registered_ip )
{
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
2005-12-07 02:06:38 +03:00
namerec = find_name_on_subnet ( subrec , nmbname , FIND_SELF_NAME ) ;
if ( namerec = = NULL ) {
2004-03-16 00:45:45 +03:00
unstring name ;
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( name , sizeof ( name ) , nmbname - > name ) ;
2003-08-27 05:25:01 +04:00
add_name_to_subnet ( subrec , name , nmbname - > name_type ,
nb_flags , ttl , SELF_NAME , 1 , & registered_ip ) ;
} else {
update_name_ttl ( namerec , ttl ) ;
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function automatically called when a name refresh or register
1998-06-30 02:50:49 +04:00
fails . Note that this is only ever called on a broadcast subnet with
one IP address per name . This is why it can just delete the name
without enumerating the IP adresses . JRA .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-09 05:56:18 +04:00
void standard_fail_register ( struct subnet_record * subrec ,
struct nmb_name * nmbname )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
namerec = find_name_on_subnet ( subrec , nmbname , FIND_SELF_NAME ) ;
1998-06-09 05:56:18 +04:00
2003-08-27 05:25:01 +04:00
DEBUG ( 0 , ( " standard_fail_register: Failed to register/refresh name %s \
on subnet % s \ n " , nmb_namestr(nmbname), subrec->subnet_name) );
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Remove the name from the subnet. */
2005-12-07 02:06:38 +03:00
if ( namerec ) {
2003-08-27 05:25:01 +04:00
remove_name_from_namelist ( subrec , namerec ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function to remove an IP address from a name record .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void remove_nth_ip_in_record ( struct name_record * namerec , int ind )
{
2005-12-07 02:06:38 +03:00
if ( ind ! = namerec - > data . num_ips ) {
2003-08-27 05:25:01 +04:00
memmove ( ( char * ) ( & namerec - > data . ip [ ind ] ) ,
( char * ) ( & namerec - > data . ip [ ind + 1 ] ) ,
( namerec - > data . num_ips - ind - 1 ) * sizeof ( struct in_addr ) ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
namerec - > data . num_ips - - ;
2005-12-07 02:06:38 +03:00
if ( namerec - > subnet = = wins_server_subnet ) {
wins_store_changed_namerec ( namerec ) ;
} else {
namerec - > subnet - > namelist_changed = True ;
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function to check if an IP address exists in a name record .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool find_ip_in_name_record ( struct name_record * namerec , struct in_addr ip )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
int i ;
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
for ( i = 0 ; i < namerec - > data . num_ips ; i + + ) {
2007-10-25 01:16:54 +04:00
if ( ip_equal_v4 ( namerec - > data . ip [ i ] , ip ) ) {
2003-08-27 05:25:01 +04:00
return True ;
2005-12-07 02:06:38 +03:00
}
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
return False ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function to add an IP address to a name record .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-10 23:51:58 +04:00
void add_ip_to_name_record ( struct name_record * namerec , struct in_addr new_ip )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct in_addr * new_list ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Don't add one we already have. */
2005-12-07 02:06:38 +03:00
if ( find_ip_in_name_record ( namerec , new_ip ) ) {
2003-08-27 05:25:01 +04:00
return ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2004-12-07 21:25:53 +03:00
new_list = SMB_MALLOC_ARRAY ( struct in_addr , namerec - > data . num_ips + 1 ) ;
2003-08-27 05:25:01 +04:00
if ( NULL = = new_list ) {
DEBUG ( 0 , ( " add_ip_to_name_record: Malloc fail ! \n " ) ) ;
return ;
}
memcpy ( ( char * ) new_list , ( char * ) namerec - > data . ip , namerec - > data . num_ips * sizeof ( struct in_addr ) ) ;
new_list [ namerec - > data . num_ips ] = new_ip ;
SAFE_FREE ( namerec - > data . ip ) ;
namerec - > data . ip = new_list ;
namerec - > data . num_ips + = 1 ;
2005-12-07 02:06:38 +03:00
if ( namerec - > subnet = = wins_server_subnet ) {
wins_store_changed_namerec ( namerec ) ;
} else {
namerec - > subnet - > namelist_changed = True ;
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function to remove an IP address from a name record .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-09 05:56:18 +04:00
void remove_ip_from_name_record ( struct name_record * namerec ,
struct in_addr remove_ip )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
/* Try and find the requested ip address - remove it. */
int i ;
int orig_num = namerec - > data . num_ips ;
for ( i = 0 ; i < orig_num ; i + + ) {
2007-10-25 01:16:54 +04:00
if ( ip_equal_v4 ( remove_ip , namerec - > data . ip [ i ] ) ) {
2003-08-27 05:25:01 +04:00
remove_nth_ip_in_record ( namerec , i ) ;
break ;
}
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Utility function that release_name callers can plug into as the
success function when a name release is successful . Used to save
duplication of success_function code .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-09 05:56:18 +04:00
void standard_success_release ( struct subnet_record * subrec ,
struct userdata_struct * userdata ,
struct nmb_name * nmbname ,
struct in_addr released_ip )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
namerec = find_name_on_subnet ( subrec , nmbname , FIND_ANY_NAME ) ;
if ( namerec = = NULL ) {
DEBUG ( 0 , ( " standard_success_release: Name release for name %s IP %s \
on subnet % s . Name was not found on subnet . \ n " , nmb_namestr(nmbname), inet_ntoa(released_ip),
subrec - > subnet_name ) ) ;
return ;
} else {
int orig_num = namerec - > data . num_ips ;
remove_ip_from_name_record ( namerec , released_ip ) ;
2005-12-07 02:06:38 +03:00
if ( namerec - > data . num_ips = = orig_num ) {
2003-08-27 05:25:01 +04:00
DEBUG ( 0 , ( " standard_success_release: Name release for name %s IP %s \
on subnet % s . This ip is not known for this name . \ n " , nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) );
2005-12-07 02:06:38 +03:00
}
2003-08-27 05:25:01 +04:00
}
2005-12-07 02:06:38 +03:00
if ( namerec - > data . num_ips = = 0 ) {
2003-08-27 05:25:01 +04:00
remove_name_from_namelist ( subrec , namerec ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
2005-12-07 02:06:38 +03:00
Expires old names in a subnet namelist .
NB . Does not touch the wins_subnet - no wins specific processing here .
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
static void expire_names_on_subnet ( struct subnet_record * subrec , time_t t )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
struct name_record * next_namerec ;
2005-12-07 02:06:38 +03:00
for ( namerec = subrec - > namelist ; namerec ; namerec = next_namerec ) {
next_namerec = namerec - > next ;
2003-08-27 05:25:01 +04:00
if ( ( namerec - > data . death_time ! = PERMANENT_TTL ) & & ( namerec - > data . death_time < t ) ) {
if ( namerec - > data . source = = SELF_NAME ) {
DEBUG ( 3 , ( " expire_names_on_subnet: Subnet %s not expiring SELF \
name % s \ n " , subrec->subnet_name, nmb_namestr(&namerec->name) ) );
namerec - > data . death_time + = 300 ;
namerec - > subnet - > namelist_changed = True ;
continue ;
}
DEBUG ( 3 , ( " expire_names_on_subnet: Subnet %s - removing expired name %s \n " ,
subrec - > subnet_name , nmb_namestr ( & namerec - > name ) ) ) ;
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
remove_name_from_namelist ( subrec , namerec ) ;
2003-08-27 05:25:01 +04:00
}
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
2005-12-07 02:06:38 +03:00
Expires old names in all subnet namelists .
NB . Does not touch the wins_subnet .
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
void expire_names ( time_t t )
{
2003-08-27 05:25:01 +04:00
struct subnet_record * subrec ;
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST ( subrec ) ) {
expire_names_on_subnet ( subrec , t ) ;
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Add the magic samba names , useful for finding samba servers .
These go directly into the name list for a particular subnet ,
without going through the normal registration process .
When adding them to the unicast subnet , add them as a list of
all broadcast subnet IP addresses .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-06-09 05:56:18 +04:00
void add_samba_names_to_subnet ( struct subnet_record * subrec )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct in_addr * iplist = & subrec - > myip ;
int num_ips = 1 ;
/* These names are added permanently (ttl of zero) and will NOT be refreshed. */
if ( ( subrec = = unicast_subnet ) | | ( subrec = = wins_server_subnet ) | | ( subrec = = remote_broadcast_subnet ) ) {
struct subnet_record * bcast_subrecs ;
int i ;
/* Create an IP list containing all our known subnets. */
num_ips = iface_count ( ) ;
2004-12-07 21:25:53 +03:00
iplist = SMB_MALLOC_ARRAY ( struct in_addr , num_ips ) ;
2003-08-27 05:25:01 +04:00
if ( NULL = = iplist ) {
DEBUG ( 0 , ( " add_samba_names_to_subnet: Malloc fail ! \n " ) ) ;
return ;
}
2007-11-16 04:59:12 +03:00
for ( bcast_subrecs = FIRST_SUBNET , i = 0 ; bcast_subrecs & &
i < num_ips ;
bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST ( bcast_subrecs ) , i + + ) {
2003-08-27 05:25:01 +04:00
iplist [ i ] = bcast_subrecs - > myip ;
2007-11-16 04:59:12 +03:00
}
num_ips = i ;
2003-08-27 05:25:01 +04:00
}
add_name_to_subnet ( subrec , " * " , 0x0 , samba_nb_type , PERMANENT_TTL ,
PERMANENT_NAME , num_ips , iplist ) ;
add_name_to_subnet ( subrec , " * " , 0x20 , samba_nb_type , PERMANENT_TTL ,
PERMANENT_NAME , num_ips , iplist ) ;
add_name_to_subnet ( subrec , " __SAMBA__ " , 0x20 , samba_nb_type , PERMANENT_TTL ,
PERMANENT_NAME , num_ips , iplist ) ;
add_name_to_subnet ( subrec , " __SAMBA__ " , 0x00 , samba_nb_type , PERMANENT_TTL ,
PERMANENT_NAME , num_ips , iplist ) ;
2005-12-07 02:06:38 +03:00
if ( iplist ! = & subrec - > myip ) {
2003-08-27 05:25:01 +04:00
SAFE_FREE ( iplist ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
2005-12-07 02:06:38 +03:00
Dump a name_record struct .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-07 02:06:38 +03:00
void dump_name_record ( struct name_record * namerec , XFILE * fp )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
const char * src_type ;
struct tm * tm ;
int i ;
2005-12-07 02:06:38 +03:00
x_fprintf ( fp , " \t Name = %s \t " , nmb_namestr ( & namerec - > name ) ) ;
switch ( namerec - > data . source ) {
case LMHOSTS_NAME :
src_type = " LMHOSTS_NAME " ;
break ;
case WINS_PROXY_NAME :
src_type = " WINS_PROXY_NAME " ;
break ;
case REGISTER_NAME :
src_type = " REGISTER_NAME " ;
break ;
case SELF_NAME :
src_type = " SELF_NAME " ;
break ;
case DNS_NAME :
src_type = " DNS_NAME " ;
break ;
case DNSFAIL_NAME :
src_type = " DNSFAIL_NAME " ;
break ;
case PERMANENT_NAME :
src_type = " PERMANENT_NAME " ;
break ;
default :
src_type = " unknown! " ;
break ;
}
2003-08-27 05:25:01 +04:00
2005-12-07 02:06:38 +03:00
x_fprintf ( fp , " Source = %s \n b_flags = %x \t " , src_type , namerec - > data . nb_flags ) ;
2003-08-27 05:25:01 +04:00
2005-12-07 02:06:38 +03:00
if ( namerec - > data . death_time ! = PERMANENT_TTL ) {
2006-06-15 01:36:49 +04:00
const char * asct ;
2005-12-07 02:06:38 +03:00
tm = localtime ( & namerec - > data . death_time ) ;
2006-06-15 01:36:49 +04:00
if ( ! tm ) {
return ;
}
asct = asctime ( tm ) ;
if ( ! asct ) {
return ;
}
x_fprintf ( fp , " death_time = %s \t " , asct ) ;
2005-12-07 02:06:38 +03:00
} else {
x_fprintf ( fp , " death_time = PERMANENT \t " ) ;
}
2003-08-27 05:25:01 +04:00
2005-12-07 02:06:38 +03:00
if ( namerec - > data . refresh_time ! = PERMANENT_TTL ) {
2006-06-15 01:36:49 +04:00
const char * asct ;
2005-12-07 02:06:38 +03:00
tm = localtime ( & namerec - > data . refresh_time ) ;
2006-06-15 01:36:49 +04:00
if ( ! tm ) {
return ;
}
asct = asctime ( tm ) ;
if ( ! asct ) {
return ;
}
x_fprintf ( fp , " refresh_time = %s \n " , asct ) ;
2005-12-07 02:06:38 +03:00
} else {
x_fprintf ( fp , " refresh_time = PERMANENT \n " ) ;
}
2003-08-27 05:25:01 +04:00
2005-12-07 02:06:38 +03:00
x_fprintf ( fp , " \t \t number of IPS = %d " , namerec - > data . num_ips ) ;
for ( i = 0 ; i < namerec - > data . num_ips ; i + + ) {
x_fprintf ( fp , " \t %s " , inet_ntoa ( namerec - > data . ip [ i ] ) ) ;
}
x_fprintf ( fp , " \n \n " ) ;
}
/****************************************************************************
Dump the contents of the namelists on all the subnets ( including unicast )
into a file . Initiated by SIGHUP - used to debug the state of the namelists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-27 05:25:01 +04:00
2005-12-07 02:06:38 +03:00
static void dump_subnet_namelist ( struct subnet_record * subrec , XFILE * fp )
{
struct name_record * namerec ;
x_fprintf ( fp , " Subnet %s \n ---------------------- \n " , subrec - > subnet_name ) ;
for ( namerec = subrec - > namelist ; namerec ; namerec = namerec - > next ) {
dump_name_record ( namerec , fp ) ;
2003-08-27 05:25:01 +04:00
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Dump the contents of the namelists on all the subnets ( including unicast )
into a file . Initiated by SIGHUP - used to debug the state of the namelists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-04-13 23:24:06 +04:00
void dump_all_namelists ( void )
1997-12-13 17:16:07 +03:00
{
2014-11-02 22:21:45 +03:00
XFILE * fp ;
2003-08-27 05:25:01 +04:00
struct subnet_record * subrec ;
2014-11-02 22:21:45 +03:00
char * dump_path ;
1997-12-13 17:16:07 +03:00
2014-11-02 22:21:45 +03:00
dump_path = lock_path ( " namelist.debug " ) ;
if ( dump_path = = NULL ) {
DEBUG ( 0 , ( " out of memory! \n " ) ) ;
return ;
}
fp = x_fopen ( dump_path , ( O_WRONLY | O_CREAT | O_TRUNC ) , 0644 ) ;
TALLOC_FREE ( dump_path ) ;
if ( ! fp ) {
2003-08-27 05:25:01 +04:00
DEBUG ( 0 , ( " dump_all_namelists: Can't open file %s. Error was %s \n " ,
" namelist.debug " , strerror ( errno ) ) ) ;
return ;
}
2014-11-02 22:21:45 +03:00
2005-12-07 02:06:38 +03:00
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST ( subrec ) ) {
2003-08-27 05:25:01 +04:00
dump_subnet_namelist ( subrec , fp ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
if ( ! we_are_a_wins_client ( ) ) {
2003-08-27 05:25:01 +04:00
dump_subnet_namelist ( unicast_subnet , fp ) ;
2005-12-07 02:06:38 +03:00
}
1997-12-13 17:16:07 +03:00
2005-12-07 02:06:38 +03:00
if ( remote_broadcast_subnet - > namelist ! = NULL ) {
2003-08-27 05:25:01 +04:00
dump_subnet_namelist ( remote_broadcast_subnet , fp ) ;
2005-12-07 02:06:38 +03:00
}
if ( wins_server_subnet ! = NULL ) {
dump_wins_subnet_namelist ( fp ) ;
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
x_fclose ( fp ) ;
1997-12-13 17:16:07 +03:00
}