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"
2010-08-18 17:22:09 +04:00
# include "nmbd/nmbd.h"
1997-12-13 17:16:07 +03:00
2015-04-30 06:14:34 +03:00
extern uint16_t samba_nb_type ; /* Samba's NetBIOS type. */
1997-12-13 17:16:07 +03:00
2021-03-13 23:56:53 +03:00
static const char * * mynames = NULL ;
static bool add_unique_netbios_name ( const char * name )
{
size_t i , num_names = talloc_array_length ( mynames ) ;
char * str = NULL ;
const char * * tmp = NULL ;
for ( i = 0 ; i < num_names ; i + + ) {
if ( strequal ( name , mynames [ i ] ) ) {
return true ;
}
}
str = talloc_strdup ( NULL , name ) ;
if ( str = = NULL ) {
return false ;
}
tmp = talloc_realloc ( NULL , mynames , const char * , num_names + 1 ) ;
if ( tmp = = NULL ) {
TALLOC_FREE ( str ) ;
return false ;
}
tmp [ num_names ] = talloc_move ( tmp , & str ) ;
mynames = tmp ;
return true ;
}
bool nmbd_init_my_netbios_names ( void )
{
const char * name = lp_netbios_name ( ) ;
const char * * aliases = lp_netbios_aliases ( ) ;
TALLOC_FREE ( mynames ) ;
if ( name [ 0 ] ! = ' \0 ' ) {
bool ok = add_unique_netbios_name ( name ) ;
if ( ! ok ) {
return false ;
}
}
if ( aliases = = NULL ) {
return true ;
}
while ( * aliases ! = NULL ) {
bool ok = add_unique_netbios_name ( * aliases ) ;
if ( ! ok ) {
return false ;
}
aliases + = 1 ;
}
return true ;
}
const char * my_netbios_names ( int i )
{
size_t num_names = talloc_array_length ( mynames ) ;
if ( ( i > = 0 ) & & ( i < num_names ) ) {
return mynames [ i ] ;
}
return NULL ;
}
1997-12-13 17:16:07 +03:00
/****************************************************************************
2023-07-13 10:09:48 +03:00
Fail function when registering my netbios names .
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
static void my_name_register_failed ( struct subnet_record * subrec ,
struct response_record * rrec , struct nmb_name * nmbname )
{
2003-08-27 05:25:01 +04:00
DEBUG ( 0 , ( " my_name_register_failed: Failed to register my name %s on subnet %s. \n " ,
nmb_namestr ( nmbname ) , subrec - > subnet_name ) ) ;
1997-12-13 17:16:07 +03:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Add my workgroup and my given names to one subnet
Also add the magic Samba names .
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
void register_my_workgroup_one_subnet ( struct subnet_record * subrec )
{
int i ;
struct work_record * work ;
/* Create the workgroup on the subnet. */
2002-11-13 02:20:50 +03:00
if ( ( work = create_workgroup_on_subnet ( subrec , lp_workgroup ( ) ,
1999-12-13 16:27:58 +03:00
PERMANENT_TTL ) ) = = NULL ) {
DEBUG ( 0 , ( " register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \
2002-11-13 02:20:50 +03:00
Exiting . \ n " , lp_workgroup(), subrec->subnet_name));
1999-12-13 16:27:58 +03:00
return ;
}
/* Each subnet entry, except for the wins_server_subnet has
the magic Samba names . */
add_samba_names_to_subnet ( subrec ) ;
/* Register all our names including aliases. */
2002-11-13 02:20:50 +03:00
for ( i = 0 ; my_netbios_names ( i ) ; i + + ) {
register_name ( subrec , my_netbios_names ( i ) , 0x20 , samba_nb_type ,
1999-12-13 16:27:58 +03:00
NULL ,
my_name_register_failed , NULL ) ;
2002-11-13 02:20:50 +03:00
register_name ( subrec , my_netbios_names ( i ) , 0x03 , samba_nb_type ,
1999-12-13 16:27:58 +03:00
NULL ,
my_name_register_failed , NULL ) ;
2002-11-13 02:20:50 +03:00
register_name ( subrec , my_netbios_names ( i ) , 0x00 , samba_nb_type ,
1999-12-13 16:27:58 +03:00
NULL ,
my_name_register_failed , NULL ) ;
}
/* Initiate election processing, register the workgroup names etc. */
initiate_myworkgroup_startup ( subrec , work ) ;
}
2002-03-29 03:57:35 +03:00
/*******************************************************************
Utility function to add a name to the unicast subnet , or add in
our IP address if it already exists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void insert_refresh_name_into_unicast ( struct subnet_record * subrec ,
2015-04-30 06:14:34 +03:00
struct nmb_name * nmbname , uint16_t nb_type )
2002-03-29 03:57:35 +03:00
{
2003-08-27 05:25:01 +04:00
struct name_record * namerec ;
if ( ! we_are_a_wins_client ( ) ) {
insert_permanent_name_into_unicast ( subrec , nmbname , nb_type ) ;
return ;
}
if ( ( namerec = find_name_on_subnet ( unicast_subnet , nmbname , FIND_SELF_NAME ) ) = = 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
/* The name needs to be created on the unicast subnet. */
( void ) add_name_to_subnet ( unicast_subnet , name ,
nmbname - > name_type , nb_type ,
MIN ( lp_max_ttl ( ) , MAX_REFRESH_TIME ) , SELF_NAME , 1 , & subrec - > myip ) ;
} else {
/* The name already exists on the unicast subnet. Add our local
IP for the given broadcast subnet to the name . */
add_ip_to_name_record ( namerec , subrec - > myip ) ;
}
2002-03-29 03:57:35 +03:00
}
1999-12-13 16:27:58 +03:00
1997-12-13 17:16:07 +03:00
/****************************************************************************
Add my workgroup and my given names to the subnet lists .
Also add the magic Samba names .
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
2007-10-19 04:40:25 +04:00
bool register_my_workgroup_and_names ( void )
1997-12-13 17:16:07 +03:00
{
2003-08-27 05:25:01 +04:00
struct subnet_record * subrec ;
int i ;
2007-07-24 14:24:27 +04:00
const char * * cluster_addresses = NULL ;
2003-08-27 05:25:01 +04:00
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST ( subrec ) ) {
register_my_workgroup_one_subnet ( subrec ) ;
}
/* We still need to add the magic Samba
names and the netbios names to the unicast subnet directly . This is
to allow unicast node status requests and queries to still work
in a broadcast only environment . */
add_samba_names_to_subnet ( unicast_subnet ) ;
for ( i = 0 ; my_netbios_names ( i ) ; i + + ) {
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST ( subrec ) ) {
/*
* Ensure all the IP addresses are added if we are multihomed .
*/
struct nmb_name nmbname ;
make_nmb_name ( & nmbname , my_netbios_names ( i ) , 0x20 ) ;
insert_refresh_name_into_unicast ( subrec , & nmbname , samba_nb_type ) ;
make_nmb_name ( & nmbname , my_netbios_names ( i ) , 0x3 ) ;
insert_refresh_name_into_unicast ( subrec , & nmbname , samba_nb_type ) ;
make_nmb_name ( & nmbname , my_netbios_names ( i ) , 0x0 ) ;
insert_refresh_name_into_unicast ( subrec , & nmbname , samba_nb_type ) ;
}
}
2007-07-24 14:24:27 +04:00
/*
* add in any cluster addresses . We need to response to these ,
* but not listen on them . This allows us to run nmbd on every
* node in the cluster , and have all of them register with a
* WINS server correctly
*/
if ( lp_clustering ( ) ) {
cluster_addresses = lp_cluster_addresses ( ) ;
}
if ( cluster_addresses ) {
int a , n ;
unsigned name_types [ ] = { 0x20 , 0x3 , 0x0 } ;
for ( i = 0 ; my_netbios_names ( i ) ; i + + ) {
for ( subrec = FIRST_SUBNET ; subrec ; subrec = subrec - > next ) {
for ( n = 0 ; n < ARRAY_SIZE ( name_types ) ; n + + ) {
struct name_record * namerec ;
2007-11-04 08:34:46 +03:00
struct nmb_name nmbname ;
struct in_addr ip ;
2007-07-24 14:24:27 +04:00
make_nmb_name ( & nmbname , my_netbios_names ( i ) , name_types [ n ] ) ;
namerec = find_name_on_subnet ( unicast_subnet , & nmbname , FIND_SELF_NAME ) ;
if ( namerec = = NULL ) continue ;
for ( a = 0 ; cluster_addresses [ a ] ; a + + ) {
2008-10-23 22:41:15 +04:00
ip = interpret_addr2 ( cluster_addresses [ a ] ) ;
add_ip_to_name_record ( namerec , ip ) ;
2007-07-24 14:24:27 +04:00
}
}
}
}
}
2003-08-27 05:25:01 +04:00
/*
* Add the WORKGROUP < 0 > and WORKGROUP < 1 e > group names to the unicast subnet
* also for the same reasons .
*/
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST ( subrec ) ) {
/*
* Ensure all the IP addresses are added if we are multihomed .
*/
struct nmb_name nmbname ;
make_nmb_name ( & nmbname , lp_workgroup ( ) , 0x0 ) ;
insert_refresh_name_into_unicast ( subrec , & nmbname , samba_nb_type | NB_GROUP ) ;
make_nmb_name ( & nmbname , lp_workgroup ( ) , 0x1e ) ;
insert_refresh_name_into_unicast ( subrec , & nmbname , samba_nb_type | NB_GROUP ) ;
}
/*
* We need to add the Samba names to the remote broadcast subnet ,
* as NT 4. x does directed broadcast requests to the * < 0x0 > name .
*/
add_samba_names_to_subnet ( remote_broadcast_subnet ) ;
return True ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Remove all the names we registered .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-27 05:25:01 +04:00
2002-07-15 14:35:28 +04:00
void release_wins_names ( void )
1997-12-13 17:16:07 +03:00
{
2002-07-15 14:35:28 +04:00
struct subnet_record * subrec = unicast_subnet ;
struct name_record * namerec , * nextnamerec ;
2005-12-07 02:06:38 +03:00
for ( namerec = subrec - > namelist ; namerec ; namerec = nextnamerec ) {
nextnamerec = namerec - > next ;
2002-07-15 14:35:28 +04:00
if ( ( namerec - > data . source = = SELF_NAME )
& & ! NAME_IS_DEREGISTERING ( namerec ) )
release_name ( subrec , namerec , standard_success_release ,
NULL , NULL ) ;
}
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
2002-07-15 14:35:28 +04:00
Refresh our registered names with WINS
2003-08-27 05:25:01 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
void refresh_my_names ( time_t t )
{
2002-07-15 14:35:28 +04:00
struct name_record * namerec ;
2003-08-27 05:25:01 +04:00
if ( wins_srv_count ( ) < 1 )
return ;
2002-07-15 14:35:28 +04:00
2005-12-07 02:06:38 +03:00
for ( namerec = unicast_subnet - > namelist ; namerec ; namerec = namerec - > next ) {
2002-07-15 14:35:28 +04:00
/* Each SELF name has an individual time to be refreshed. */
if ( ( namerec - > data . source = = SELF_NAME ) & &
( namerec - > data . refresh_time < t ) & &
( namerec - > data . death_time ! = PERMANENT_TTL ) ) {
/* We cheat here and pretend the refresh is going to be
successful & update the refresh times . This stops
multiple refresh calls being done . We actually
deal with refresh failure in the fail_fn .
*/
if ( ! is_refresh_already_queued ( unicast_subnet , namerec ) ) {
wins_refresh_name ( namerec ) ;
}
namerec - > data . death_time = t + lp_max_ttl ( ) ;
2002-08-17 21:00:51 +04:00
namerec - > data . refresh_time = t + MIN ( lp_max_ttl ( ) / 2 , MAX_REFRESH_TIME ) ;
2002-07-15 14:35:28 +04:00
}
}
1997-12-13 17:16:07 +03:00
}