0001-01-01 02:30:17 +02:30
/*
0001-01-01 02:30:17 +02:30
Unix SMB / CIFS implementation .
0001-01-01 02:30:17 +02:30
NBT netbios routines and daemon - version 2
0001-01-01 02:30:17 +02:30
Copyright ( C ) Andrew Tridgell 1994 - 1998
0001-01-01 02:30:17 +02:30
Copyright ( C ) Jeremy Allison 1997 - 2002
0001-01-01 02:30:17 +02:30
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"
0001-01-01 02:30:17 +02:30
int ClientNMB = - 1 ;
int ClientDGRAM = - 1 ;
0001-01-01 02:30:17 +02:30
int global_nmb_port = - 1 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
extern pstring global_myname ;
extern fstring global_myworkgroup ;
0001-01-01 02:30:17 +02:30
extern char * * my_netbios_names ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
extern BOOL global_in_nmbd ;
0001-01-01 02:30:17 +02:30
/* are we running as a daemon ? */
static BOOL is_daemon = False ;
0001-01-01 02:30:17 +02:30
/* have we found LanMan clients yet? */
BOOL found_lm_clients = False ;
0001-01-01 02:30:17 +02:30
/* what server type are we currently */
0001-01-01 02:30:17 +02:30
time_t StartupTime = 0 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Handle a SIGTERM in band .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
static void terminate ( void )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Got SIGTERM: going down... \n " ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Write out wins.dat file if samba is a WINS server */
wins_write_database ( False ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Remove all SELF registered names from WINS */
release_wins_names ( ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Announce all server entries as 0 time-to-live, 0 type. */
announce_my_servers_removed ( ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* If there was an async dns child - kill it. */
kill_async_dns_child ( ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
exit ( 0 ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
Handle a SHUTDOWN message from smbcontrol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void nmbd_terminate ( int msg_type , pid_t src , void * buf , size_t len )
{
terminate ( ) ;
}
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Catch a SIGTERM signal .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
static SIG_ATOMIC_T got_sig_term ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void sig_term ( int sig )
{
got_sig_term = 1 ;
sys_select_signal ( ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
Catch a SIGHUP signal .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static SIG_ATOMIC_T reload_after_sighup ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void sig_hup ( int sig )
{
reload_after_sighup = 1 ;
sys_select_signal ( ) ;
}
0001-01-01 02:30:17 +02:30
# if DUMP_CORE
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Prepare to dump a core file - carefully !
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static BOOL dump_core ( void )
{
0001-01-01 02:30:17 +02:30
char * p ;
pstring dname ;
pstrcpy ( dname , lp_logfile ( ) ) ;
if ( ( p = strrchr_m ( dname , ' / ' ) ) )
* p = 0 ;
pstrcat ( dname , " /corefiles " ) ;
mkdir ( dname , 0700 ) ;
sys_chown ( dname , getuid ( ) , getgid ( ) ) ;
chmod ( dname , 0700 ) ;
if ( chdir ( dname ) )
return ( False ) ;
umask ( ~ ( 0700 ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# ifdef HAVE_GETRLIMIT
0001-01-01 02:30:17 +02:30
# ifdef RLIMIT_CORE
0001-01-01 02:30:17 +02:30
{
struct rlimit rlp ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
rlp . rlim_cur = MAX ( 4 * 1024 * 1024 , rlp . rlim_cur ) ;
setrlimit ( RLIMIT_CORE , & rlp ) ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
DEBUG ( 3 , ( " Core limits now %d %d \n " , ( int ) rlp . rlim_cur , ( int ) rlp . rlim_max ) ) ;
}
0001-01-01 02:30:17 +02:30
# endif
# endif
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Dumping core in %s \n " , dname ) ) ;
abort ( ) ;
return ( True ) ;
}
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Possibly continue after a fault .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void fault_continue ( void )
{
# if DUMP_CORE
0001-01-01 02:30:17 +02:30
dump_core ( ) ;
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Expire old names from the namelist and server list .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void expire_names_and_servers ( time_t t )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
static time_t lastrun = 0 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! lastrun )
lastrun = t ;
if ( t < ( lastrun + 5 ) )
return ;
lastrun = t ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Expire any timed out names on all the broadcast
* subnets and those registered with the WINS server .
* ( nmbd_namelistdb . c )
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
expire_names ( t ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Go through all the broadcast subnets and for each
* workgroup known on that subnet remove any expired
* server names . If a workgroup has an empty serverlist
* and has itself timed out then remove the workgroup .
* ( nmbd_workgroupdb . c )
*/
expire_workgroups_and_servers ( t ) ;
}
0001-01-01 02:30:17 +02:30
/************************************************************************** **
0001-01-01 02:30:17 +02:30
Reload the list of network interfaces .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static BOOL reload_interfaces ( time_t t )
0001-01-01 02:30:17 +02:30
{
static time_t lastt ;
int n ;
struct subnet_record * subrec ;
extern BOOL rescan_listen_set ;
0001-01-01 02:30:17 +02:30
extern struct in_addr loopback_ip ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( t & & ( ( t - lastt ) < NMBD_INTERFACES_RELOAD ) ) return False ;
0001-01-01 02:30:17 +02:30
lastt = t ;
0001-01-01 02:30:17 +02:30
if ( ! interfaces_changed ( ) ) return False ;
0001-01-01 02:30:17 +02:30
/* the list of probed interfaces has changed, we may need to add/remove
some subnets */
load_interfaces ( ) ;
/* find any interfaces that need adding */
for ( n = iface_count ( ) - 1 ; n > = 0 ; n - - ) {
struct interface * iface = get_interface ( n ) ;
0001-01-01 02:30:17 +02:30
/*
* We don ' t want to add a loopback interface , in case
* someone has added 127.0 .0 .1 for smbd , nmbd needs to
* ignore it here . JRA .
*/
if ( ip_equal ( iface - > ip , loopback_ip ) ) {
DEBUG ( 2 , ( " reload_interfaces: Ignoring loopback interface %s \n " , inet_ntoa ( iface - > ip ) ) ) ;
continue ;
}
0001-01-01 02:30:17 +02:30
for ( subrec = subnetlist ; subrec ; subrec = subrec - > next ) {
if ( ip_equal ( iface - > ip , subrec - > myip ) & &
ip_equal ( iface - > nmask , subrec - > mask_ip ) ) break ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! subrec ) {
/* it wasn't found! add it */
DEBUG ( 2 , ( " Found new interface %s \n " ,
inet_ntoa ( iface - > ip ) ) ) ;
subrec = make_normal_subnet ( iface ) ;
if ( subrec ) register_my_workgroup_one_subnet ( subrec ) ;
}
}
/* find any interfaces that need deleting */
for ( subrec = subnetlist ; subrec ; subrec = subrec - > next ) {
for ( n = iface_count ( ) - 1 ; n > = 0 ; n - - ) {
struct interface * iface = get_interface ( n ) ;
if ( ip_equal ( iface - > ip , subrec - > myip ) & &
ip_equal ( iface - > nmask , subrec - > mask_ip ) ) break ;
}
if ( n = = - 1 ) {
/* oops, an interface has disapeared. This is
tricky , we don ' t dare actually free the
interface as it could be being used , so
instead we just wear the memory leak and
remove it from the list of interfaces without
freeing it */
DEBUG ( 2 , ( " Deleting dead interface %s \n " ,
inet_ntoa ( subrec - > myip ) ) ) ;
close_subnet ( subrec ) ;
}
}
rescan_listen_set = True ;
0001-01-01 02:30:17 +02:30
/* We need to shutdown if there are no subnets... */
if ( FIRST_SUBNET = = NULL ) {
DEBUG ( 0 , ( " reload_interfaces: No subnets to listen to. Shutting down... \n " ) ) ;
return True ;
}
return False ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Reload the services file .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static BOOL reload_nmbd_services ( BOOL test )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
BOOL ret ;
extern fstring remote_machine ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
fstrcpy ( remote_machine , " nmbd " ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( lp_loaded ( ) ) {
pstring fname ;
pstrcpy ( fname , lp_configfile ( ) ) ;
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , dyn_CONFIGFILE ) ) {
pstrcpy ( dyn_CONFIGFILE , fname ) ;
test = False ;
}
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( test & & ! lp_file_list_changed ( ) )
return ( True ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ret = lp_load ( dyn_CONFIGFILE , True , False , False ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* perhaps the config filename is now set */
if ( ! test ) {
DEBUG ( 3 , ( " services not loaded \n " ) ) ;
reload_nmbd_services ( True ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return ( ret ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
The main select loop .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void process ( void )
{
0001-01-01 02:30:17 +02:30
BOOL run_election ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
while ( True ) {
time_t t = time ( NULL ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Check for internal messages */
message_dispatch ( ) ;
/*
* Check all broadcast subnets to see if
* we need to run an election on any of them .
* ( nmbd_elections . c )
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
run_election = check_elections ( ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Read incoming UDP packets .
* ( nmbd_packets . c )
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( listen_for_packets ( run_election ) )
0001-01-01 02:30:17 +02:30
return ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Handle termination inband .
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( got_sig_term ) {
got_sig_term = 0 ;
terminate ( ) ;
}
/*
* Process all incoming packets
* read above . This calls the success and
* failure functions registered when response
* packets arrrive , and also deals with request
* packets from other sources .
* ( nmbd_packets . c )
*/
run_packet_queue ( ) ;
/*
* Run any elections - initiate becoming
* a local master browser if we have won .
* ( nmbd_elections . c )
*/
run_elections ( t ) ;
/*
* Send out any broadcast announcements
* of our server names . This also announces
* the workgroup name if we are a local
* master browser .
* ( nmbd_sendannounce . c )
*/
announce_my_server_names ( t ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Send out any LanMan broadcast announcements
* of our server names .
* ( nmbd_sendannounce . c )
*/
announce_my_lm_server_names ( t ) ;
/*
* If we are a local master browser , periodically
* announce ourselves to the domain master browser .
* This also deals with syncronising the domain master
* browser server lists with ourselves as a local
* master browser .
* ( nmbd_sendannounce . c )
*/
announce_myself_to_domain_master_browser ( t ) ;
/*
* Fullfill any remote announce requests .
* ( nmbd_sendannounce . c )
*/
announce_remote ( t ) ;
/*
* Fullfill any remote browse sync announce requests .
* ( nmbd_sendannounce . c )
*/
browse_sync_remote ( t ) ;
/*
* Scan the broadcast subnets , and WINS client
* namelists and refresh any that need refreshing .
* ( nmbd_mynames . c )
*/
refresh_my_names ( t ) ;
/*
* Scan the subnet namelists and server lists and
* expire thos that have timed out .
* ( nmbd . c )
*/
expire_names_and_servers ( t ) ;
/*
* Write out a snapshot of our current browse list into
* the browse . dat file . This is used by smbd to service
* incoming NetServerEnum calls - used to synchronise
* browse lists over subnets .
* ( nmbd_serverlistdb . c )
*/
write_browse_list ( t , False ) ;
/*
* If we are a domain master browser , we have a list of
* local master browsers we should synchronise browse
* lists with ( these are added by an incoming local
* master browser announcement packet ) . Expire any of
* these that are no longer current , and pull the server
* lists from each of these known local master browsers .
* ( nmbd_browsesync . c )
*/
dmb_expire_and_sync_browser_lists ( t ) ;
/*
* Check that there is a local master browser for our
* workgroup for all our broadcast subnets . If one
* is not found , start an election ( which we ourselves
* may or may not participate in , depending on the
* setting of the ' local master ' parameter .
* ( nmbd_elections . c )
*/
check_master_browser_exists ( t ) ;
/*
* If we are configured as a logon server , attempt to
* register the special NetBIOS names to become such
* ( WORKGROUP < 1 c > name ) on all broadcast subnets and
* with the WINS server ( if used ) . If we are configured
* to become a domain master browser , attempt to register
* the special NetBIOS name ( WORKGROUP < 1 b > name ) to
* become such .
* ( nmbd_become_dmb . c )
*/
add_domain_names ( t ) ;
/*
* If we are a WINS server , do any timer dependent
* processing required .
* ( nmbd_winsserver . c )
*/
initiate_wins_processing ( t ) ;
/*
* If we are a domain master browser , attempt to contact the
* WINS server to get a list of all known WORKGROUPS / DOMAINS .
* This will only work to a Samba WINS server .
* ( nmbd_browsesync . c )
*/
if ( lp_enhanced_browsing ( ) )
collect_all_workgroup_names_from_wins_server ( t ) ;
/*
* Go through the response record queue and time out or re - transmit
* and expired entries .
* ( nmbd_packets . c )
*/
retransmit_or_expire_response_records ( t ) ;
/*
* check to see if any remote browse sync child processes have completed
*/
sync_check_completion ( ) ;
/*
* regularly sync with any other DMBs we know about
*/
if ( lp_enhanced_browsing ( ) )
sync_all_dmbs ( t ) ;
/*
* clear the unexpected packet queue
*/
clear_unexpected ( t ) ;
/*
* Reload the services file if we got a sighup .
*/
if ( reload_after_sighup ) {
DEBUG ( 0 , ( " Got SIGHUP dumping debug info. \n " ) ) ;
write_browse_list ( 0 , True ) ;
dump_all_namelists ( ) ;
reload_nmbd_services ( True ) ;
reopen_logs ( ) ;
if ( reload_interfaces ( 0 ) )
return ;
reload_after_sighup = 0 ;
}
/* check for new network interfaces */
if ( reload_interfaces ( t ) )
return ;
/* free up temp memory */
lp_talloc_free ( ) ;
}
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Open the socket communication .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static BOOL open_sockets ( BOOL isdaemon , int port )
{
0001-01-01 02:30:17 +02:30
/*
* The sockets opened here will be used to receive broadcast
* packets * only * . Interface specific sockets are opened in
* make_subnet ( ) in namedbsubnet . c . Thus we bind to the
* address " 0.0.0.0 " . The parameter ' socket address ' is
* now deprecated .
*/
if ( isdaemon )
ClientNMB = open_socket_in ( SOCK_DGRAM , port , 0 , 0 , True ) ;
else
ClientNMB = 0 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ClientDGRAM = open_socket_in ( SOCK_DGRAM , DGRAM_PORT , 3 , 0 , True ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ClientNMB = = - 1 )
return ( False ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* we are never interested in SIGPIPE */
BlockSignals ( True , SIGPIPE ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
set_socket_options ( ClientNMB , " SO_BROADCAST " ) ;
set_socket_options ( ClientDGRAM , " SO_BROADCAST " ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " open_sockets: Broadcast sockets opened. \n " ) ) ;
return ( True ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Initialise connect , service and file structs .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static BOOL init_structs ( void )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
extern fstring local_machine ;
0001-01-01 02:30:17 +02:30
char * p , * * ptr ;
0001-01-01 02:30:17 +02:30
int namecount ;
int n ;
int nodup ;
0001-01-01 02:30:17 +02:30
char * nbname ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! * global_myname )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
fstrcpy ( global_myname , myhostname ( ) ) ;
0001-01-01 02:30:17 +02:30
p = strchr_m ( global_myname , ' . ' ) ;
0001-01-01 02:30:17 +02:30
if ( p )
* p = 0 ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
strupper ( global_myname ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Add any NETBIOS name aliases. Ensure that the first entry
0001-01-01 02:30:17 +02:30
is equal to global_myname .
0001-01-01 02:30:17 +02:30
*/
0001-01-01 02:30:17 +02:30
/* Work out the max number of netbios aliases that we have */
0001-01-01 02:30:17 +02:30
ptr = lp_netbios_aliases ( ) ;
0001-01-01 02:30:17 +02:30
namecount = 0 ;
if ( ptr )
for ( ; * ptr ; namecount + + , ptr + + )
;
0001-01-01 02:30:17 +02:30
if ( * global_myname )
0001-01-01 02:30:17 +02:30
namecount + + ;
0001-01-01 02:30:17 +02:30
/* Allocate space for the netbios aliases */
0001-01-01 02:30:17 +02:30
my_netbios_names = ( char * * ) malloc ( sizeof ( char * ) * ( namecount + 1 ) ) ;
if ( NULL = = my_netbios_names )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " init_structs: malloc fail. \n " ) ) ;
return ( False ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/* Use the global_myname string first */
0001-01-01 02:30:17 +02:30
namecount = 0 ;
0001-01-01 02:30:17 +02:30
if ( * global_myname )
my_netbios_names [ namecount + + ] = global_myname ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
ptr = lp_netbios_aliases ( ) ;
0001-01-01 02:30:17 +02:30
if ( ptr )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
while ( * ptr )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
nbname = strdup ( * ptr ) ;
if ( nbname = = NULL )
{
DEBUG ( 0 , ( " init_structs: malloc fail when allocating names. \n " ) ) ;
return False ;
}
strupper ( nbname ) ;
/* Look for duplicates */
nodup = 1 ;
for ( n = 0 ; n < namecount ; n + + )
{
if ( 0 = = strcmp ( nbname , my_netbios_names [ n ] ) )
nodup = 0 ;
}
if ( nodup )
my_netbios_names [ namecount + + ] = nbname ;
else
0001-01-01 02:30:17 +02:30
SAFE_FREE ( nbname ) ;
0001-01-01 02:30:17 +02:30
ptr + + ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
}
/* Terminate name list */
0001-01-01 02:30:17 +02:30
my_netbios_names [ namecount + + ] = NULL ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
fstrcpy ( local_machine , global_myname ) ;
0001-01-01 02:30:17 +02:30
trim_string ( local_machine , " " , " " ) ;
0001-01-01 02:30:17 +02:30
p = strchr_m ( local_machine , ' ' ) ;
0001-01-01 02:30:17 +02:30
if ( p )
0001-01-01 02:30:17 +02:30
* p = 0 ;
0001-01-01 02:30:17 +02:30
strlower ( local_machine ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " Netbios name list:- \n " ) ) ;
0001-01-01 02:30:17 +02:30
for ( n = 0 ; my_netbios_names [ n ] ; n + + )
0001-01-01 02:30:17 +02:30
DEBUGADD ( 5 , ( " my_netbios_names[%d]= \" %s \" \n " , n , my_netbios_names [ n ] ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return ( True ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
0001-01-01 02:30:17 +02:30
Usage on the program .
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void usage ( char * pname )
{
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
printf ( " Usage: %s [-DaiohV] [-H lmhosts file] [-d debuglevel] [-l log basename] \n " , pname ) ;
0001-01-01 02:30:17 +02:30
printf ( " [-n name] [-p port] [-s configuration file] \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -D Become a daemon (default) \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -a Append to log file (default) \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -i Run interactive (not a daemon) \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -o Overwrite log file, don't append \n " ) ;
printf ( " \t -h Print usage \n " ) ;
printf ( " \t -V Print version \n " ) ;
printf ( " \t -H hosts file Load a netbios hosts file \n " ) ;
printf ( " \t -d debuglevel Set the debuglevel \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -l log basename. Basename for log/debug files \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -n netbiosname. Primary netbios name \n " ) ;
printf ( " \t -p port Listen on the specified port \n " ) ;
printf ( " \t -s configuration file Configuration file name \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \n " ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/**************************************************************************** **
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
int main ( int argc , char * argv [ ] )
0001-01-01 02:30:17 +02:30
{
int opt ;
extern char * optarg ;
0001-01-01 02:30:17 +02:30
extern BOOL append_log ;
0001-01-01 02:30:17 +02:30
BOOL opt_interactive = False ;
0001-01-01 02:30:17 +02:30
pstring logfile ;
0001-01-01 02:30:17 +02:30
append_log = True ; /* Default, override with '-o' option. */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
global_nmb_port = NMB_PORT ;
0001-01-01 02:30:17 +02:30
global_in_nmbd = True ;
0001-01-01 02:30:17 +02:30
StartupTime = time ( NULL ) ;
0001-01-01 02:30:17 +02:30
sys_srandom ( time ( NULL ) ^ sys_getpid ( ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
slprintf ( logfile , sizeof ( logfile ) - 1 , " %s/log.nmbd " , dyn_LOGFILEBASE ) ;
lp_set_logfile ( logfile ) ;
0001-01-01 02:30:17 +02:30
/* this is for people who can't start the program correctly */
0001-01-01 02:30:17 +02:30
while ( argc > 1 & & ( * argv [ 1 ] ! = ' - ' ) )
{
0001-01-01 02:30:17 +02:30
argv + + ;
argc - - ;
}
0001-01-01 02:30:17 +02:30
fault_setup ( ( void ( * ) ( void * ) ) fault_continue ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* POSIX demands that signals are inherited. If the invoking process has
* these signals masked , we will have problems , as we won ' t recieve them . */
BlockSignals ( False , SIGHUP ) ;
BlockSignals ( False , SIGUSR1 ) ;
BlockSignals ( False , SIGTERM ) ;
0001-01-01 02:30:17 +02:30
CatchSignal ( SIGHUP , SIGNAL_CAST sig_hup ) ;
CatchSignal ( SIGTERM , SIGNAL_CAST sig_term ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# if defined(SIGFPE)
/* we are never interested in SIGFPE */
BlockSignals ( True , SIGFPE ) ;
# endif
0001-01-01 02:30:17 +02:30
/* We no longer use USR2... */
# if defined(SIGUSR2)
BlockSignals ( True , SIGUSR2 ) ;
# endif
0001-01-01 02:30:17 +02:30
while ( EOF ! =
0001-01-01 02:30:17 +02:30
( opt = getopt ( argc , argv , " Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:i " ) ) )
0001-01-01 02:30:17 +02:30
{
switch ( opt )
0001-01-01 02:30:17 +02:30
{
case ' s ' :
0001-01-01 02:30:17 +02:30
pstrcpy ( dyn_CONFIGFILE , optarg ) ;
0001-01-01 02:30:17 +02:30
break ;
case ' N ' :
case ' B ' :
case ' I ' :
case ' C ' :
case ' G ' :
DEBUG ( 0 , ( " Obsolete option '%c' used \n " , opt ) ) ;
break ;
0001-01-01 02:30:17 +02:30
case ' i ' :
opt_interactive = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' H ' :
0001-01-01 02:30:17 +02:30
pstrcpy ( dyn_LMHOSTSFILE , optarg ) ;
0001-01-01 02:30:17 +02:30
break ;
case ' n ' :
0001-01-01 02:30:17 +02:30
pstrcpy ( global_myname , optarg ) ;
strupper ( global_myname ) ;
0001-01-01 02:30:17 +02:30
break ;
case ' l ' :
0001-01-01 02:30:17 +02:30
slprintf ( logfile , sizeof ( logfile ) - 1 , " %s/log.nmbd " , optarg ) ;
lp_set_logfile ( logfile ) ;
0001-01-01 02:30:17 +02:30
break ;
case ' a ' :
0001-01-01 02:30:17 +02:30
append_log = True ;
break ;
case ' o ' :
append_log = False ;
0001-01-01 02:30:17 +02:30
break ;
case ' D ' :
is_daemon = True ;
break ;
case ' d ' :
DEBUGLEVEL = atoi ( optarg ) ;
break ;
case ' p ' :
global_nmb_port = atoi ( optarg ) ;
break ;
case ' h ' :
usage ( argv [ 0 ] ) ;
exit ( 0 ) ;
break ;
0001-01-01 02:30:17 +02:30
case ' V ' :
printf ( " Version %s \n " , VERSION ) ;
exit ( 0 ) ;
break ;
0001-01-01 02:30:17 +02:30
default :
0001-01-01 02:30:17 +02:30
if ( ! is_a_socket ( 0 ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Incorrect program usage - is the command line correct? \n " ) ) ;
0001-01-01 02:30:17 +02:30
usage ( argv [ 0 ] ) ;
0001-01-01 02:30:17 +02:30
exit ( 0 ) ;
0001-01-01 02:30:17 +02:30
}
break ;
}
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
setup_logging ( argv [ 0 ] , opt_interactive ) ;
0001-01-01 02:30:17 +02:30
reopen_logs ( ) ;
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Netbios nameserver version %s started. \n " , VERSION ) ) ;
DEBUGADD ( 0 , ( " Copyright Andrew Tridgell and the Samba Team 1994-2002 \n " ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! reload_nmbd_services ( False ) )
0001-01-01 02:30:17 +02:30
return ( - 1 ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! init_structs ( ) )
return - 1 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
reload_nmbd_services ( True ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
fstrcpy ( global_myworkgroup , lp_workgroup ( ) ) ;
if ( strequal ( global_myworkgroup , " * " ) )
{
DEBUG ( 0 , ( " ERROR: a workgroup name of * is no longer supported \n " ) ) ;
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
set_samba_nb_type ( ) ;
0001-01-01 02:30:17 +02:30
if ( ! is_daemon & & ! is_a_socket ( 0 ) )
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " standard input is not a socket, assuming -D option \n " ) ) ;
is_daemon = True ;
}
0001-01-01 02:30:17 +02:30
if ( is_daemon & & ! opt_interactive )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 2 , ( " Becoming a daemon. \n " ) ) ;
0001-01-01 02:30:17 +02:30
become_daemon ( ) ;
}
0001-01-01 02:30:17 +02:30
# if HAVE_SETPGID
/*
* If we ' re interactive we want to set our own process group for
* signal management .
*/
if ( opt_interactive )
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
# endif
0001-01-01 02:30:17 +02:30
# ifndef SYNC_DNS
/* Setup the async dns. We do it here so it doesn't have all the other
stuff initialised and thus chewing memory and sockets */
0001-01-01 02:30:17 +02:30
if ( lp_we_are_a_wins_server ( ) & & lp_dns_proxy ( ) ) {
0001-01-01 02:30:17 +02:30
start_async_dns ( ) ;
}
# endif
0001-01-01 02:30:17 +02:30
if ( ! directory_exist ( lp_lockdir ( ) , NULL ) ) {
mkdir ( lp_lockdir ( ) , 0755 ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
pidfile_create ( " nmbd " ) ;
0001-01-01 02:30:17 +02:30
message_init ( ) ;
0001-01-01 02:30:17 +02:30
message_register ( MSG_FORCE_ELECTION , nmbd_message_election ) ;
0001-01-01 02:30:17 +02:30
message_register ( MSG_WINS_NEW_ENTRY , nmbd_wins_new_entry ) ;
0001-01-01 02:30:17 +02:30
message_register ( MSG_SHUTDOWN , nmbd_terminate ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
DEBUG ( 3 , ( " Opening sockets %d \n " , global_nmb_port ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ! open_sockets ( is_daemon , global_nmb_port ) )
return 1 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Determine all the IP addresses we have. */
0001-01-01 02:30:17 +02:30
load_interfaces ( ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Create an nmbd subnet record for each of the above. */
if ( False = = create_subnets ( ) )
{
DEBUG ( 0 , ( " ERROR: Failed when creating subnet lists. Exiting. \n " ) ) ;
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* Load in any static local names. */
0001-01-01 02:30:17 +02:30
load_lmhosts_file ( dyn_LMHOSTSFILE ) ;
DEBUG ( 3 , ( " Loaded hosts file %s \n " , dyn_LMHOSTSFILE ) ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* If we are acting as a WINS server, initialise data structures. */
if ( ! initialise_wins ( ) )
{
DEBUG ( 0 , ( " nmbd: Failed when initialising WINS server. \n " ) ) ;
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
* Register nmbd primary workgroup and nmbd names on all
* the broadcast subnets , and on the WINS server ( if specified ) .
* Also initiate the startup of our primary workgroup ( start
* elections if we are setup as being able to be a local
* master browser .
*/
if ( False = = register_my_workgroup_and_names ( ) )
{
DEBUG ( 0 , ( " ERROR: Failed when creating my my workgroup. Exiting. \n " ) ) ;
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* We can only take signals in the select. */
0001-01-01 02:30:17 +02:30
BlockSignals ( True , SIGTERM ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
process ( ) ;
if ( dbf )
0001-01-01 02:30:17 +02:30
x_fclose ( dbf ) ;
0001-01-01 02:30:17 +02:30
return ( 0 ) ;
0001-01-01 02:30:17 +02:30
}