1996-06-04 10:42:03 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
NBT netbios routines and daemon - version 2
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1996-06-04 10:42:03 +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
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 .
Revision History :
14 jan 96 : lkcl @ pires . co . uk
added multiple workgroup domain master support
*/
# include "includes.h"
extern int DEBUGLEVEL ;
extern pstring debugf ;
pstring servicesf = CONFIGFILE ;
extern pstring scope ;
1997-12-13 17:16:07 +03:00
int ClientNMB = - 1 ;
int ClientDGRAM = - 1 ;
1997-10-18 03:08:07 +04:00
int global_nmb_port = - 1 ;
1996-06-04 10:42:03 +04:00
extern pstring myhostname ;
static pstring host_file ;
extern pstring myname ;
1997-05-20 04:32:51 +04:00
extern fstring myworkgroup ;
1997-07-31 22:47:26 +04:00
extern char * * my_netbios_names ;
1996-06-04 10:42:03 +04:00
/* are we running as a daemon ? */
static BOOL is_daemon = False ;
1997-12-16 12:20:34 +03:00
/* have we found LanMan clients yet? */
BOOL found_lm_clients = False ;
1996-06-04 10:42:03 +04:00
/* what server type are we currently */
1997-12-13 17:16:07 +03:00
time_t StartupTime = 0 ;
1996-06-04 10:42:03 +04:00
1996-06-06 15:43:09 +04:00
extern struct in_addr ipzero ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
1996-07-04 23:19:26 +04:00
catch a sigterm
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-08 08:41:51 +04:00
static int sig_term ( )
{
1996-08-15 19:11:34 +04:00
BlockSignals ( True , SIGTERM ) ;
1996-06-08 08:41:51 +04:00
DEBUG ( 0 , ( " Got SIGTERM: going down... \n " ) ) ;
1997-12-13 17:16:07 +03:00
/* Write out wins.dat file if samba is a WINS server */
wins_write_database ( ) ;
1996-06-08 08:41:51 +04:00
1997-12-13 17:16:07 +03:00
/* Remove all SELF registered names. */
release_my_names ( ) ;
1996-06-08 08:41:51 +04:00
1997-12-13 17:16:07 +03:00
/* Announce all server entries as 0 time-to-live, 0 type. */
1997-05-20 04:32:51 +04:00
announce_my_servers_removed ( ) ;
1996-06-29 22:49:20 +04:00
1998-03-03 23:19:14 +03:00
/* If there was an async dns child - kill it. */
kill_async_dns_child ( ) ;
1996-06-08 08:41:51 +04:00
exit ( 0 ) ;
1997-12-24 12:30:56 +03:00
1997-05-31 00:40:48 +04:00
/* Keep compiler happy.. */
return 0 ;
1997-12-13 17:16:07 +03:00
} /* sig_term */
1996-06-08 08:41:51 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
catch a sighup
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static int sig_hup ( void )
{
1997-12-13 17:16:07 +03:00
BlockSignals ( True , SIGHUP ) ;
DEBUG ( 0 , ( " Got SIGHUP dumping debug info. \n " ) ) ;
write_browse_list ( 0 , True ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
dump_all_namelists ( ) ;
reload_services ( True ) ;
1996-06-04 10:42:03 +04:00
1996-08-01 21:49:40 +04:00
set_samba_nb_type ( ) ;
1996-08-15 19:11:34 +04:00
BlockSignals ( False , SIGHUP ) ;
1996-06-04 10:42:03 +04:00
# ifndef DONT_REINSTALL_SIG
signal ( SIGHUP , SIGNAL_CAST sig_hup ) ;
# endif
return ( 0 ) ;
1997-12-13 17:16:07 +03:00
} /* sig_hup */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
catch a sigpipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static int sig_pipe ( void )
{
1997-12-13 17:16:07 +03:00
BlockSignals ( True , SIGPIPE ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
DEBUG ( 0 , ( " Got SIGPIPE \n " ) ) ;
if ( ! is_daemon )
1996-06-04 10:42:03 +04:00
exit ( 1 ) ;
1997-12-13 17:16:07 +03:00
BlockSignals ( False , SIGPIPE ) ;
1996-06-04 10:42:03 +04:00
return ( 0 ) ;
1997-12-13 17:16:07 +03:00
} /* sig_pipe */
1996-06-04 10:42:03 +04:00
# if DUMP_CORE
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
prepare to dump a core file - carefully !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static BOOL dump_core ( void )
{
char * p ;
pstring dname ;
1997-12-13 17:16:07 +03:00
pstrcpy ( dname , debugf ) ;
if ( ( p = strrchr ( dname , ' / ' ) ) )
* p = 0 ;
strcat ( dname , " /corefiles " ) ;
mkdir ( dname , 0700 ) ;
sys_chown ( dname , getuid ( ) , getgid ( ) ) ;
chmod ( dname , 0700 ) ;
if ( chdir ( dname ) )
return ( False ) ;
umask ( ~ ( 0700 ) ) ;
1996-06-04 10:42:03 +04:00
# ifndef NO_GETRLIMIT
# ifdef RLIMIT_CORE
{
struct rlimit rlp ;
1997-12-13 17:16:07 +03:00
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 " , rlp . rlim_cur , rlp . rlim_max ) ) ;
1996-06-04 10:42:03 +04:00
}
# endif
# endif
1997-12-13 17:16:07 +03:00
DEBUG ( 0 , ( " Dumping core in %s \n " , dname ) ) ;
return ( True ) ;
} /* dump_core */
1996-06-04 10:42:03 +04:00
# endif
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
possibly continue after a fault
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static void fault_continue ( void )
{
# if DUMP_CORE
dump_core ( ) ;
# endif
1997-12-13 17:16:07 +03:00
} /* fault_continue */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
expire old names from the namelist and server list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-07 05:56:21 +04:00
static void expire_names_and_servers ( time_t t )
1996-06-04 10:42:03 +04:00
{
1996-06-04 19:14:47 +04:00
static time_t lastrun = 0 ;
1997-12-13 17:16:07 +03:00
if ( ! lastrun )
lastrun = t ;
if ( t < ( lastrun + 5 ) )
return ;
1996-06-04 19:14:47 +04:00
lastrun = t ;
1997-12-13 17:16:07 +03:00
/*
* Expire any timed out names on all the broadcast
* subnets and those registered with the WINS server .
* ( nmbd_namelistdb . c )
*/
1996-10-02 19:41:30 +04:00
expire_names ( t ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/*
* 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 ) ;
} /* expire_names_and_servers */
/**************************************************************************** **
1996-06-04 10:42:03 +04:00
reload the services file
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
BOOL reload_services ( BOOL test )
{
BOOL ret ;
extern fstring remote_machine ;
1998-02-12 17:57:55 +03:00
strcpy ( remote_machine , " nmb " ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( lp_loaded ( ) )
{
pstring fname ;
pstrcpy ( fname , lp_configfile ( ) ) ;
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , servicesf ) )
1996-06-04 10:42:03 +04:00
{
1997-12-13 17:16:07 +03:00
pstrcpy ( servicesf , fname ) ;
test = False ;
1996-06-04 10:42:03 +04:00
}
1997-12-13 17:16:07 +03:00
}
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( test & & ! lp_file_list_changed ( ) )
1996-06-04 10:42:03 +04:00
return ( True ) ;
1998-03-14 11:27:41 +03:00
ret = lp_load ( servicesf , True , False , False ) ;
1996-06-04 10:42:03 +04:00
/* perhaps the config filename is now set */
1997-12-13 17:16:07 +03:00
if ( ! test )
{
DEBUG ( 3 , ( " services not loaded \n " ) ) ;
reload_services ( True ) ;
1996-06-04 10:42:03 +04:00
}
1997-05-08 05:14:17 +04:00
/* Do a sanity check for a misconfigured nmbd */
1997-12-13 17:16:07 +03:00
if ( lp_wins_support ( ) & & * lp_wins_server ( ) )
{
1997-05-08 05:14:17 +04:00
DEBUG ( 0 , ( " ERROR: both 'wins support = true' and 'wins server = <server>' \
cannot be set in the smb . conf file . nmbd aborting . \ n " ));
exit ( 10 ) ;
}
1996-06-04 10:42:03 +04:00
return ( ret ) ;
1997-12-13 17:16:07 +03:00
} /* reload_services */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
The main select loop .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static void process ( void )
{
BOOL run_election ;
1997-12-13 17:16:07 +03:00
while ( True )
{
time_t t = time ( NULL ) ;
/*
* Check all broadcast subnets to see if
* we need to run an election on any of them .
* ( nmbd_elections . c )
*/
run_election = check_elections ( ) ;
/*
* Read incoming UDP packets .
* ( nmbd_packets . c )
*/
if ( listen_for_packets ( run_election ) )
return ;
/*
* 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 ) ;
1997-12-16 12:20:34 +03:00
/*
* Send out any LanMan broadcast announcements
* of our server names .
* ( nmbd_sendannounce . c )
*/
announce_my_lm_server_names ( t ) ;
1997-12-13 17:16:07 +03:00
/*
* 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 ) ;
1997-12-24 10:10:04 +03:00
/*
* 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 )
*/
collect_all_workgroup_names_from_wins_server ( t ) ;
1997-12-13 17:16:07 +03:00
/*
1997-12-23 09:38:36 +03:00
* Go through the response record queue and time out or re - transmit
1997-12-13 17:16:07 +03:00
* and expired entries .
* ( nmbd_packets . c )
*/
retransmit_or_expire_response_records ( t ) ;
}
} /* process */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
open the socket communication
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static BOOL open_sockets ( BOOL isdaemon , int port )
{
1997-10-18 03:08:07 +04:00
/* 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 .
*/
1997-12-13 17:16:07 +03:00
if ( isdaemon )
1997-10-18 03:08:07 +04:00
ClientNMB = open_socket_in ( SOCK_DGRAM , port , 0 , 0 ) ;
1996-06-04 10:42:03 +04:00
else
ClientNMB = 0 ;
1997-10-18 03:08:07 +04:00
ClientDGRAM = open_socket_in ( SOCK_DGRAM , DGRAM_PORT , 3 , 0 ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( ClientNMB = = - 1 )
return ( False ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
signal ( SIGPIPE , SIGNAL_CAST sig_pipe ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
set_socket_options ( ClientNMB , " SO_BROADCAST " ) ;
set_socket_options ( ClientDGRAM , " SO_BROADCAST " ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
DEBUG ( 3 , ( " open_sockets: Broadcast sockets opened. \n " ) ) ;
return ( True ) ;
} /* open_sockets */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
initialise connect , service and file structs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static BOOL init_structs ( )
{
1996-08-22 10:32:03 +04:00
extern fstring local_machine ;
1997-07-31 22:47:26 +04:00
char * p , * ptr ;
int namecount ;
int n ;
int nodup ;
pstring nbname ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( ! * myname )
{
fstrcpy ( myname , myhostname ) ;
p = strchr ( myname , ' . ' ) ;
if ( p )
* p = 0 ;
1996-06-04 10:42:03 +04:00
}
1997-12-13 17:16:07 +03:00
strupper ( myname ) ;
1996-06-04 10:42:03 +04:00
1997-07-31 22:47:26 +04:00
/* Add any NETBIOS name aliases. Ensure that the first entry
1997-12-13 17:16:07 +03:00
is equal to myname .
*/
1997-07-31 22:47:26 +04:00
/* Work out the max number of netbios aliases that we have */
1997-12-13 17:16:07 +03:00
ptr = lp_netbios_aliases ( ) ;
for ( namecount = 0 ; next_token ( & ptr , nbname , NULL ) ; namecount + + )
1997-07-31 22:47:26 +04:00
;
1997-12-13 17:16:07 +03:00
if ( * myname )
namecount + + ;
1997-07-31 22:47:26 +04:00
/* Allocate space for the netbios aliases */
1997-12-13 17:16:07 +03:00
my_netbios_names = ( char * * ) malloc ( sizeof ( char * ) * ( namecount + 1 ) ) ;
if ( NULL = = my_netbios_names )
1997-07-31 22:47:26 +04:00
{
1997-12-13 17:16:07 +03:00
DEBUG ( 0 , ( " init_structs: malloc fail. \n " ) ) ;
return ( False ) ;
1997-07-31 22:47:26 +04:00
}
/* Use the myname string first */
namecount = 0 ;
1997-12-13 17:16:07 +03:00
if ( * myname )
1997-07-31 22:47:26 +04:00
my_netbios_names [ namecount + + ] = myname ;
1997-12-13 17:16:07 +03:00
ptr = lp_netbios_aliases ( ) ;
while ( next_token ( & ptr , nbname , NULL ) )
{
strupper ( nbname ) ;
1997-07-31 22:47:26 +04:00
/* Look for duplicates */
nodup = 1 ;
1997-12-13 17:16:07 +03:00
for ( n = 0 ; n < namecount ; n + + )
{
if ( 0 = = strcmp ( nbname , my_netbios_names [ n ] ) )
1997-07-31 22:47:26 +04:00
nodup = 0 ;
}
if ( nodup )
1997-12-13 17:16:07 +03:00
my_netbios_names [ namecount + + ] = strdup ( nbname ) ;
1997-07-31 22:47:26 +04:00
}
/* Check the strdups succeeded. */
1997-12-13 17:16:07 +03:00
for ( n = 0 ; n < namecount ; n + + )
if ( NULL = = my_netbios_names [ n ] )
1997-07-31 22:47:26 +04:00
{
DEBUG ( 0 , ( " init_structs: malloc fail when allocating names. \n " ) ) ;
return False ;
}
/* Terminate name list */
1997-12-13 17:16:07 +03:00
my_netbios_names [ namecount + + ] = NULL ;
1997-07-31 22:47:26 +04:00
1997-12-13 17:16:07 +03:00
fstrcpy ( local_machine , myname ) ;
trim_string ( local_machine , " " , " " ) ;
p = strchr ( local_machine , ' ' ) ;
if ( p )
1997-07-31 22:47:26 +04:00
* p = 0 ;
1997-12-13 17:16:07 +03:00
strlower ( local_machine ) ;
1996-08-22 10:32:03 +04:00
1997-12-13 17:16:07 +03:00
DEBUG ( 5 , ( " Netbios name list:- \n " ) ) ;
for ( n = 0 ; my_netbios_names [ n ] ; n + + )
DEBUG ( 5 , ( " my_netbios_names[%d]= \" %s \" \n " , n , my_netbios_names [ n ] ) ) ;
1997-07-31 22:47:26 +04:00
1997-12-13 17:16:07 +03:00
return ( True ) ;
} /* init_structs */
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
usage on the program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static void usage ( char * pname )
{
DEBUG ( 0 , ( " Incorrect program usage - is the command line correct? \n " ) ) ;
1997-12-13 17:16:07 +03:00
printf ( " Usage: %s [-n name] [-D] [-p port] [-d debuglevel] " , pname ) ;
printf ( " [-l log basename] \n " ) ;
printf ( " Version %s \n " , VERSION ) ;
printf ( " \t -D become a daemon \n " ) ;
printf ( " \t -p port listen on the specified port \n " ) ;
printf ( " \t -d debuglevel set the debuglevel \n " ) ;
printf ( " \t -l log basename. Basename for log/debug files \n " ) ;
printf ( " \t -n netbiosname. " ) ;
printf ( " the netbios name to advertise for this host \n " ) ;
printf ( " \t -H hosts file load a netbios hosts file \n " ) ;
printf ( " \n " ) ;
} /* usage */
/**************************************************************************** **
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
1996-06-04 10:42:03 +04:00
{
int opt ;
extern FILE * dbf ;
extern char * optarg ;
1997-12-13 17:16:07 +03:00
char pidFile [ 100 ] = { 0 } ;
1996-06-04 10:42:03 +04:00
1997-10-18 03:08:07 +04:00
global_nmb_port = NMB_PORT ;
1996-06-04 10:42:03 +04:00
* host_file = 0 ;
StartupTime = time ( NULL ) ;
TimeInit ( ) ;
1997-12-13 17:16:07 +03:00
strcpy ( debugf , NMBLOGFILE ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
setup_logging ( argv [ 0 ] , False ) ;
1996-06-04 10:42:03 +04:00
1997-07-19 00:21:32 +04:00
charset_initialise ( ) ;
1996-06-04 10:42:03 +04:00
# ifdef LMHOSTSFILE
1997-12-13 17:16:07 +03:00
strcpy ( host_file , LMHOSTSFILE ) ;
1996-06-04 10:42:03 +04:00
# endif
/* this is for people who can't start the program correctly */
1997-12-13 17:16:07 +03:00
while ( argc > 1 & & ( * argv [ 1 ] ! = ' - ' ) )
{
1996-06-04 10:42:03 +04:00
argv + + ;
argc - - ;
}
1997-12-13 17:16:07 +03:00
fault_setup ( fault_continue ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
signal ( SIGHUP , SIGNAL_CAST sig_hup ) ;
signal ( SIGTERM , SIGNAL_CAST sig_term ) ;
1996-06-04 10:42:03 +04:00
1997-12-24 12:30:56 +03:00
/* Setup the signals that allow the debug log level
to by dynamically changed . */
1998-01-23 08:22:19 +03:00
/* If we are using the malloc debug code we can't use
SIGUSR1 and SIGUSR2 to do debug level changes . */
# ifndef MEM_MAN
1997-12-24 12:30:56 +03:00
# if defined(SIGUSR1)
signal ( SIGUSR1 , SIGNAL_CAST sig_usr1 ) ;
# endif /* SIGUSR1 */
# if defined(SIGUSR2)
signal ( SIGUSR2 , SIGNAL_CAST sig_usr2 ) ;
# endif /* SIGUSR2 */
1998-01-23 08:22:19 +03:00
# endif /* MEM_MAN */
1997-12-24 12:30:56 +03:00
1997-12-13 17:16:07 +03:00
while ( ( opt = getopt ( argc , argv , " as:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f: " ) ) ! = EOF )
1996-06-04 10:42:03 +04:00
{
switch ( opt )
1997-12-13 17:16:07 +03:00
{
1996-12-10 20:55:27 +03:00
case ' f ' :
strncpy ( pidFile , optarg , sizeof ( pidFile ) ) ;
break ;
1997-12-13 17:16:07 +03:00
case ' s ' :
pstrcpy ( servicesf , optarg ) ;
break ;
case ' N ' :
case ' B ' :
case ' I ' :
case ' C ' :
case ' G ' :
DEBUG ( 0 , ( " Obsolete option '%c' used \n " , opt ) ) ;
break ;
case ' H ' :
pstrcpy ( host_file , optarg ) ;
break ;
case ' n ' :
pstrcpy ( myname , optarg ) ;
strupper ( myname ) ;
break ;
case ' l ' :
sprintf ( debugf , " %s.nmb " , optarg ) ;
break ;
case ' i ' :
pstrcpy ( scope , optarg ) ;
strupper ( scope ) ;
break ;
case ' a ' :
{
extern BOOL append_log ;
append_log = ! append_log ;
}
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 ;
default :
if ( ! is_a_socket ( 0 ) )
{
usage ( argv [ 0 ] ) ;
}
break ;
}
1996-06-04 10:42:03 +04:00
}
DEBUG ( 1 , ( " %s netbios nameserver version %s started \n " , timestring ( ) , VERSION ) ) ;
1997-07-08 20:54:44 +04:00
DEBUG ( 1 , ( " Copyright Andrew Tridgell 1994-1997 \n " ) ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( ! get_myname ( myhostname , NULL ) )
1997-07-31 22:47:26 +04:00
{
DEBUG ( 0 , ( " Unable to get my hostname - exiting. \n " ) ) ;
return - 1 ;
}
1996-08-22 10:32:03 +04:00
1997-12-13 17:16:07 +03:00
if ( ! reload_services ( False ) )
return ( - 1 ) ;
1996-10-02 19:41:30 +04:00
1997-07-19 00:21:32 +04:00
codepage_initialise ( lp_client_code_page ( ) ) ;
1997-06-11 05:03:06 +04:00
1997-07-31 22:47:26 +04:00
if ( ! init_structs ( ) )
return - 1 ;
1996-08-19 15:17:29 +04:00
1997-12-13 17:16:07 +03:00
reload_services ( True ) ;
1996-08-22 10:32:03 +04:00
1997-12-13 17:16:07 +03:00
fstrcpy ( myworkgroup , lp_workgroup ( ) ) ;
1997-05-20 04:32:51 +04:00
1997-12-13 17:16:07 +03:00
if ( strequal ( myworkgroup , " * " ) )
{
1997-06-11 05:03:06 +04:00
DEBUG ( 0 , ( " ERROR: a workgroup name of * is no longer supported \n " ) ) ;
exit ( 1 ) ;
}
1996-08-01 21:49:40 +04:00
set_samba_nb_type ( ) ;
1997-12-13 17:16:07 +03:00
if ( ! is_daemon & & ! is_a_socket ( 0 ) )
{
1996-06-04 10:42:03 +04:00
DEBUG ( 0 , ( " standard input is not a socket, assuming -D option \n " ) ) ;
is_daemon = True ;
}
1997-12-13 17:16:07 +03:00
if ( is_daemon )
{
1996-06-04 10:42:03 +04:00
DEBUG ( 2 , ( " %s becoming a daemon \n " , timestring ( ) ) ) ;
become_daemon ( ) ;
}
1997-12-13 17:16:07 +03:00
if ( ! directory_exist ( lp_lockdir ( ) , NULL ) )
{
mkdir ( lp_lockdir ( ) , 0755 ) ;
1997-11-11 03:48:42 +03:00
}
1996-12-10 20:55:27 +03:00
if ( * pidFile )
1997-12-13 17:16:07 +03:00
{
int fd ;
char buf [ 20 ] ;
1996-12-10 20:55:27 +03:00
1997-07-24 21:25:11 +04:00
# ifdef O_NONBLOCK
1997-12-13 17:16:07 +03:00
fd = open ( pidFile , O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC , 0644 ) ;
# else
fd = open ( pidFile , O_CREAT | O_WRONLY | O_TRUNC , 0644 ) ;
1997-07-24 21:25:11 +04:00
# endif
1997-12-13 17:16:07 +03:00
if ( fd < 0 )
{
DEBUG ( 0 , ( " ERROR: can't open %s: %s \n " , pidFile , strerror ( errno ) ) ) ;
exit ( 1 ) ;
1996-12-10 20:55:27 +03:00
}
1997-12-13 17:16:07 +03:00
if ( fcntl_lock ( fd , F_SETLK , 0 , 1 , F_WRLCK ) = = False )
{
DEBUG ( 0 , ( " ERROR: nmbd is already running \n " ) ) ;
exit ( 1 ) ;
}
sprintf ( buf , " %u \n " , ( unsigned int ) getpid ( ) ) ;
if ( write ( fd , buf , strlen ( buf ) ) < 0 )
{
DEBUG ( 0 , ( " ERROR: can't write to %s: %s \n " , pidFile , strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
/* Leave pid file open & locked for the duration... */
}
1996-12-10 20:55:27 +03:00
1997-12-13 17:16:07 +03:00
DEBUG ( 3 , ( " Opening sockets %d \n " , global_nmb_port ) ) ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
if ( ! open_sockets ( is_daemon , global_nmb_port ) )
return 1 ;
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/* Determine all the IP addresses we have. */
1997-05-20 04:32:51 +04:00
load_interfaces ( ) ;
1996-08-17 15:37:44 +04:00
1997-12-13 17:16:07 +03:00
/* 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 ) ;
}
1996-06-29 22:49:20 +04:00
1997-12-13 17:16:07 +03:00
/* Load in any static local names. */
if ( * host_file )
{
load_lmhosts_file ( host_file ) ;
1997-06-11 05:03:06 +04:00
DEBUG ( 3 , ( " Loaded hosts file \n " ) ) ;
}
1997-12-13 17:16:07 +03:00
/* 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 ) ;
}
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/*
* 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 ) ;
}
1996-06-04 10:42:03 +04:00
1997-12-24 12:30:56 +03:00
/* We can only take signals in the select. */
1997-12-13 17:16:07 +03:00
BlockSignals ( True , SIGTERM ) ;
1997-12-24 12:30:56 +03:00
# if defined(SIGUSR1)
BlockSignals ( True , SIGUSR1 ) ;
# endif /* SIGUSR1 */
# if defined(SIGUSR2)
BlockSignals ( True , SIGUSR2 ) ;
# endif /* SIGUSR2 */
1997-10-22 15:02:00 +04:00
1996-06-04 10:42:03 +04:00
process ( ) ;
close_sockets ( ) ;
if ( dbf )
fclose ( dbf ) ;
return ( 0 ) ;
1997-12-13 17:16:07 +03:00
} /* main */
/* ========================================================================== */