1996-06-04 10:42:03 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1999-12-13 16:27:58 +03:00
NBT netbios routines and daemon - version 2
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
2002-03-01 05:57:52 +03:00
Copyright ( C ) Jeremy Allison 1997 - 2002
2003-04-14 07:30:20 +04:00
Copyright ( C ) Jelmer Vernooij 2002 , 2003 ( Conversion to popt )
2011-02-03 23:47:42 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-06-04 10:42:03 +04:00
( at your option ) any later version .
2011-02-03 23:47:42 +03:00
1996-06-04 10:42:03 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2011-02-03 23:47:42 +03:00
1996-06-04 10:42:03 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-06-04 10:42:03 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2010-08-18 17:22:09 +04:00
# include "nmbd/nmbd.h"
2011-02-25 01:05:57 +03:00
# include "serverid.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2012-07-20 03:36:18 +04:00
# include "../lib/util/pidfile.h"
2013-10-17 17:19:41 +04:00
# include "util_cluster.h"
2018-10-18 22:53:36 +03:00
# include "lib/gencache.h"
1996-06-04 10:42:03 +04:00
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
2007-10-19 04:40:25 +04:00
extern bool rescan_listen_set ;
extern bool global_in_nmbd ;
1998-03-16 23:59:47 +03:00
2007-10-19 04:40:25 +04:00
extern bool override_logfile ;
2004-09-21 13:07:42 +04:00
1997-12-16 12:20:34 +03:00
/* have we found LanMan clients yet? */
2007-10-19 04:40:25 +04:00
bool found_lm_clients = False ;
1997-12-16 12:20:34 +03:00
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
2013-02-18 12:58:40 +04:00
struct tevent_context * nmbd_event_context ( void )
2007-05-15 17:44:11 +04:00
{
2018-08-21 21:06:16 +03:00
return global_event_context ( ) ;
2007-05-15 17:44:11 +04:00
}
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
2002-03-01 05:57:52 +03:00
Handle a SIGTERM in band .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
2011-12-13 20:03:21 +04:00
static void terminate ( struct messaging_context * msg )
1996-06-08 08:41:51 +04:00
{
2002-03-01 05:57:52 +03:00
DEBUG ( 0 , ( " Got SIGTERM: going down... \n " ) ) ;
2011-12-13 14:00:16 +04:00
2002-03-01 05:57:52 +03:00
/* Write out wins.dat file if samba is a WINS server */
2005-12-07 02:06:38 +03:00
wins_write_database ( 0 , False ) ;
2011-12-13 14:00:16 +04:00
2002-07-15 14:35:28 +04:00
/* Remove all SELF registered names from WINS */
release_wins_names ( ) ;
2011-12-13 14:00:16 +04:00
2002-03-01 05:57:52 +03:00
/* Announce all server entries as 0 time-to-live, 0 type. */
announce_my_servers_removed ( ) ;
1998-03-03 23:19:14 +03:00
2002-03-01 05:57:52 +03:00
/* If there was an async dns child - kill it. */
kill_async_dns_child ( ) ;
1997-12-24 12:30:56 +03:00
2014-02-03 06:57:21 +04:00
pidfile_unlink ( lp_pid_directory ( ) , " nmbd " ) ;
2009-06-18 13:45:57 +04:00
2002-03-01 05:57:52 +03:00
exit ( 0 ) ;
}
1996-06-08 08:41:51 +04:00
2009-01-22 18:17:23 +03:00
static void nmbd_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
2002-03-29 16:58:32 +03:00
{
2011-12-13 20:03:21 +04:00
struct messaging_context * msg = talloc_get_type_abort (
private_data , struct messaging_context ) ;
terminate ( msg ) ;
2002-03-29 16:58:32 +03:00
}
2012-03-02 11:21:09 +04:00
/*
handle stdin becoming readable when we are in - - foreground mode
*/
static void nmbd_stdin_handler ( struct tevent_context * ev ,
struct tevent_fd * fde ,
uint16_t flags ,
void * private_data )
{
char c ;
if ( read ( 0 , & c , 1 ) ! = 1 ) {
struct messaging_context * msg = talloc_get_type_abort (
private_data , struct messaging_context ) ;
DEBUG ( 0 , ( " EOF on stdin \n " ) ) ;
terminate ( msg ) ;
}
}
2011-12-13 20:03:21 +04:00
static bool nmbd_setup_sig_term_handler ( struct messaging_context * msg )
2009-01-22 18:17:23 +03:00
{
struct tevent_signal * se ;
se = tevent_add_signal ( nmbd_event_context ( ) ,
nmbd_event_context ( ) ,
SIGTERM , 0 ,
nmbd_sig_term_handler ,
2011-12-13 20:03:21 +04:00
msg ) ;
2009-01-22 18:17:23 +03:00
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGTERM handler " ) ) ;
return false ;
}
return true ;
}
1997-12-13 17:16:07 +03:00
2012-03-02 11:21:09 +04:00
static bool nmbd_setup_stdin_handler ( struct messaging_context * msg , bool foreground )
{
if ( foreground ) {
/* if we are running in the foreground then look for
EOF on stdin , and exit if it happens . This allows
us to die if the parent process dies
2013-06-11 00:33:40 +04:00
Only do this on a pipe or socket , no other device .
2012-03-02 11:21:09 +04:00
*/
2013-06-11 00:33:40 +04:00
struct stat st ;
if ( fstat ( 0 , & st ) ! = 0 ) {
return false ;
}
if ( S_ISFIFO ( st . st_mode ) | | S_ISSOCK ( st . st_mode ) ) {
tevent_add_fd ( nmbd_event_context ( ) ,
nmbd_event_context ( ) ,
0 ,
TEVENT_FD_READ ,
nmbd_stdin_handler ,
msg ) ;
}
2012-03-02 11:21:09 +04:00
}
return true ;
}
2009-01-22 18:17:23 +03:00
static void msg_reload_nmbd_services ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data ) ;
static void nmbd_sig_hup_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
2011-12-13 20:03:21 +04:00
struct messaging_context * msg = talloc_get_type_abort (
private_data , struct messaging_context ) ;
2009-01-22 18:17:23 +03:00
DEBUG ( 0 , ( " Got SIGHUP dumping debug info. \n " ) ) ;
2011-12-13 20:03:21 +04:00
msg_reload_nmbd_services ( msg , NULL , MSG_SMB_CONF_UPDATED ,
messaging_server_id ( msg ) , NULL ) ;
2009-01-22 18:17:23 +03:00
}
1996-06-04 10:42:03 +04:00
2011-12-13 20:03:21 +04:00
static bool nmbd_setup_sig_hup_handler ( struct messaging_context * msg )
2002-03-01 05:57:52 +03:00
{
2009-01-22 18:17:23 +03:00
struct tevent_signal * se ;
se = tevent_add_signal ( nmbd_event_context ( ) ,
nmbd_event_context ( ) ,
SIGHUP , 0 ,
nmbd_sig_hup_handler ,
2011-12-13 20:03:21 +04:00
msg ) ;
2009-01-22 18:17:23 +03:00
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGHUP handler " ) ) ;
return false ;
}
return true ;
2002-03-01 05:57:52 +03:00
}
1996-08-01 21:49:40 +04:00
2002-03-01 05:57:52 +03:00
/**************************************************************************** **
2009-01-22 18:17:23 +03:00
Handle a SHUTDOWN message from smbcontrol .
2002-03-01 05:57:52 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-29 07:08:05 +04:00
2009-01-22 18:17:23 +03:00
static void nmbd_terminate ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
2002-03-01 05:57:52 +03:00
{
2011-12-13 20:03:21 +04:00
terminate ( msg ) ;
2002-03-01 05:57:52 +03:00
}
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
2002-03-01 05:57:52 +03:00
Expire old names from the namelist and server list .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
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
{
2002-03-01 05:57:52 +03:00
static time_t lastrun = 0 ;
2011-12-13 14:00:16 +04:00
2002-03-01 05:57:52 +03:00
if ( ! lastrun )
lastrun = t ;
if ( t < ( lastrun + 5 ) )
return ;
lastrun = t ;
1997-12-13 17:16:07 +03:00
2002-03-01 05:57:52 +03:00
/*
* Expire any timed out names on all the broadcast
* subnets and those registered with the WINS server .
* ( nmbd_namelistdb . c )
*/
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
expire_names ( t ) ;
1997-12-13 17:16:07 +03:00
2002-03-01 05:57:52 +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 ) ;
}
1999-12-13 16:27:58 +03:00
/************************************************************************** **
2002-03-01 05:57:52 +03:00
Reload the list of network interfaces .
2008-03-07 04:43:25 +03:00
Doesn ' t return until a network interface is up .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
2008-03-07 04:43:25 +03:00
static void reload_interfaces ( time_t t )
1999-12-13 16:27:58 +03:00
{
static time_t lastt ;
int n ;
2008-04-12 04:41:49 +04:00
bool print_waiting_msg = true ;
1999-12-13 16:27:58 +03:00
struct subnet_record * subrec ;
2008-03-07 04:43:25 +03:00
if ( t & & ( ( t - lastt ) < NMBD_INTERFACES_RELOAD ) ) {
return ;
}
1999-12-13 16:27:58 +03:00
lastt = t ;
2008-03-07 04:43:25 +03:00
if ( ! interfaces_changed ( ) ) {
return ;
}
1999-12-13 16:27:58 +03:00
2008-03-28 00:23:20 +03:00
try_again :
1999-12-13 16:27:58 +03:00
/* 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 - - ) {
2007-10-11 05:25:16 +04:00
char str [ INET6_ADDRSTRLEN ] ;
const struct interface * iface = get_interface ( n ) ;
struct in_addr ip , nmask ;
2000-03-30 01:30:52 +04:00
2006-06-28 04:01:28 +04:00
if ( ! iface ) {
DEBUG ( 2 , ( " reload_interfaces: failed to get interface %d \n " , n ) ) ;
continue ;
}
2007-10-11 05:25:16 +04:00
/* Ensure we're only dealing with IPv4 here. */
if ( iface - > ip . ss_family ! = AF_INET ) {
DEBUG ( 2 , ( " reload_interfaces: "
" ignoring non IPv4 interface. \n " ) ) ;
continue ;
}
2011-05-06 01:22:11 +04:00
ip = ( ( const struct sockaddr_in * ) ( const void * ) & iface - > ip ) - > sin_addr ;
nmask = ( ( const struct sockaddr_in * ) ( const void * )
2010-07-04 18:09:09 +04:00
& iface - > netmask ) - > sin_addr ;
2007-10-11 05:25:16 +04:00
2000-03-30 01:30:52 +04:00
/*
* 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 .
*/
2011-05-06 01:22:11 +04:00
if ( is_loopback_addr ( ( const struct sockaddr * ) ( const void * ) & iface - > ip ) ) {
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " reload_interfaces: Ignoring loopback "
" interface %s \n " ,
2007-10-25 01:16:54 +04:00
print_sockaddr ( str , sizeof ( str ) , & iface - > ip ) ) ) ;
2000-03-30 01:30:52 +04:00
continue ;
}
1999-12-13 16:27:58 +03:00
for ( subrec = subnetlist ; subrec ; subrec = subrec - > next ) {
2007-10-25 01:16:54 +04:00
if ( ip_equal_v4 ( ip , subrec - > myip ) & &
ip_equal_v4 ( nmask , subrec - > mask_ip ) ) {
break ;
}
1999-12-13 16:27:58 +03:00
}
2000-03-30 01:30:52 +04:00
1999-12-13 16:27:58 +03:00
if ( ! subrec ) {
/* it wasn't found! add it */
2007-10-25 01:16:54 +04:00
DEBUG ( 2 , ( " Found new interface %s \n " ,
print_sockaddr ( str ,
sizeof ( str ) , & iface - > ip ) ) ) ;
1999-12-13 16:27:58 +03:00
subrec = make_normal_subnet ( iface ) ;
2003-08-27 05:25:01 +04:00
if ( subrec )
register_my_workgroup_one_subnet ( subrec ) ;
1999-12-13 16:27:58 +03:00
}
}
/* 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 ) ;
2007-10-11 05:25:16 +04:00
struct in_addr ip , nmask ;
if ( ! iface ) {
continue ;
}
/* Ensure we're only dealing with IPv4 here. */
if ( iface - > ip . ss_family ! = AF_INET ) {
DEBUG ( 2 , ( " reload_interfaces: "
" ignoring non IPv4 interface. \n " ) ) ;
continue ;
}
2010-07-04 18:09:09 +04:00
ip = ( ( struct sockaddr_in * ) ( void * )
& iface - > ip ) - > sin_addr ;
nmask = ( ( struct sockaddr_in * ) ( void * )
& iface - > netmask ) - > sin_addr ;
2007-10-25 01:16:54 +04:00
if ( ip_equal_v4 ( ip , subrec - > myip ) & &
ip_equal_v4 ( nmask , subrec - > mask_ip ) ) {
break ;
}
1999-12-13 16:27:58 +03:00
}
if ( n = = - 1 ) {
2018-01-25 16:21:22 +03:00
/* oops, an interface has disappeared. This is
1999-12-13 16:27:58 +03:00
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 */
2007-10-25 01:16:54 +04:00
DEBUG ( 2 , ( " Deleting dead interface %s \n " ,
1999-12-13 16:27:58 +03:00
inet_ntoa ( subrec - > myip ) ) ) ;
close_subnet ( subrec ) ;
}
}
2007-10-25 01:16:54 +04:00
1999-12-13 16:27:58 +03:00
rescan_listen_set = True ;
2000-10-13 01:19:49 +04:00
2008-03-07 04:43:25 +03:00
/* We need to wait if there are no subnets... */
2000-10-13 01:19:49 +04:00
if ( FIRST_SUBNET = = NULL ) {
2009-01-23 12:13:29 +03:00
void ( * saved_handler ) ( int ) ;
2008-03-07 04:43:25 +03:00
2008-04-12 04:41:49 +04:00
if ( print_waiting_msg ) {
DEBUG ( 0 , ( " reload_interfaces: "
" No subnets to listen to. Waiting.. \n " ) ) ;
print_waiting_msg = false ;
}
2008-03-07 04:43:25 +03:00
/*
* Whilst we ' re waiting for an interface , allow SIGTERM to
* cause us to exit .
*/
2010-02-19 17:28:11 +03:00
saved_handler = CatchSignal ( SIGTERM , SIG_DFL ) ;
2008-03-07 04:43:25 +03:00
2008-08-20 04:30:30 +04:00
/* We only count IPv4, non-loopback interfaces here. */
2009-01-23 12:13:29 +03:00
while ( iface_count_v4_nl ( ) = = 0 ) {
2008-03-07 04:43:25 +03:00
sleep ( 5 ) ;
load_interfaces ( ) ;
}
2010-02-19 17:28:11 +03:00
CatchSignal ( SIGTERM , saved_handler ) ;
2008-03-28 00:23:20 +03:00
/*
* We got an interface , go back to blocking term .
2008-03-07 04:43:25 +03:00
*/
goto try_again ;
2000-10-13 01:19:49 +04:00
}
1999-12-13 16:27:58 +03:00
}
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
2002-03-01 05:57:52 +03:00
Reload the services file .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
2007-10-19 04:40:25 +04:00
static bool reload_nmbd_services ( bool test )
1996-06-04 10:42:03 +04:00
{
2007-10-19 04:40:25 +04:00
bool ret ;
1996-06-04 10:42:03 +04:00
2003-03-18 12:52:55 +03:00
set_remote_machine_name ( " nmbd " , False ) ;
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
if ( lp_loaded ( ) ) {
2014-01-15 08:29:57 +04:00
char * fname = lp_next_configfile ( talloc_tos ( ) ) ;
2008-10-17 14:48:19 +04:00
if ( file_exist ( fname ) & & ! strcsequal ( fname , get_dyn_CONFIGFILE ( ) ) ) {
2007-12-10 22:30:37 +03:00
set_dyn_CONFIGFILE ( fname ) ;
2002-03-01 05:57:52 +03:00
test = False ;
}
2012-06-01 02:06:58 +04:00
TALLOC_FREE ( fname ) ;
2002-03-01 05:57:52 +03:00
}
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
if ( test & & ! lp_file_list_changed ( ) )
return ( True ) ;
1996-06-04 10:42:03 +04:00
2011-07-27 18:34:53 +04:00
ret = lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
/* perhaps the config filename is now set */
if ( ! test ) {
DEBUG ( 3 , ( " services not loaded \n " ) ) ;
reload_nmbd_services ( True ) ;
}
1996-06-04 10:42:03 +04:00
2014-03-19 18:01:11 +04:00
reopen_logs ( ) ;
2002-03-01 05:57:52 +03:00
return ( ret ) ;
}
1996-06-04 10:42:03 +04:00
2003-07-15 21:21:21 +04:00
/**************************************************************************** **
* React on ' smbcontrol nmbd reload - config ' in the same way as to SIGHUP
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
2007-05-20 01:53:28 +04:00
static void msg_reload_nmbd_services ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
2003-07-15 21:21:21 +04:00
{
write_browse_list ( 0 , True ) ;
dump_all_namelists ( ) ;
reload_nmbd_services ( True ) ;
reopen_logs ( ) ;
2008-03-07 04:43:25 +03:00
reload_interfaces ( 0 ) ;
2003-07-15 21:21:21 +04:00
}
2007-05-20 01:53:28 +04:00
static void msg_nmbd_send_packet ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
DATA_BLOB * data )
2005-06-09 02:10:34 +04:00
{
2007-05-20 01:53:28 +04:00
struct packet_struct * p = ( struct packet_struct * ) data - > data ;
2005-06-09 02:10:34 +04:00
struct subnet_record * subrec ;
2007-10-11 05:25:16 +04:00
struct sockaddr_storage ss ;
const struct sockaddr_storage * pss ;
const struct in_addr * local_ip ;
2005-06-09 02:10:34 +04:00
2009-02-24 03:22:43 +03:00
DEBUG ( 10 , ( " Received send_packet from %u \n " , ( unsigned int ) procid_to_pid ( & src ) ) ) ;
2005-06-09 02:10:34 +04:00
2007-05-20 01:53:28 +04:00
if ( data - > length ! = sizeof ( struct packet_struct ) ) {
2009-02-24 03:22:43 +03:00
DEBUG ( 2 , ( " Discarding invalid packet length from %u \n " ,
( unsigned int ) procid_to_pid ( & src ) ) ) ;
2005-06-09 02:10:34 +04:00
return ;
}
if ( ( p - > packet_type ! = NMB_PACKET ) & &
( p - > packet_type ! = DGRAM_PACKET ) ) {
2009-02-24 03:22:43 +03:00
DEBUG ( 2 , ( " Discarding invalid packet type from %u: %d \n " ,
( unsigned int ) procid_to_pid ( & src ) , p - > packet_type ) ) ;
2005-06-09 02:10:34 +04:00
return ;
}
2007-10-11 05:25:16 +04:00
in_addr_to_sockaddr_storage ( & ss , p - > ip ) ;
2010-07-04 18:09:09 +04:00
pss = iface_ip ( ( struct sockaddr * ) ( void * ) & ss ) ;
2005-06-09 02:10:34 +04:00
2007-10-11 05:25:16 +04:00
if ( pss = = NULL ) {
2009-02-24 03:22:43 +03:00
DEBUG ( 2 , ( " Could not find ip for packet from %u \n " ,
( unsigned int ) procid_to_pid ( & src ) ) ) ;
2005-06-09 02:10:34 +04:00
return ;
}
2007-10-11 05:25:16 +04:00
local_ip = & ( ( const struct sockaddr_in * ) pss ) - > sin_addr ;
2005-06-09 02:10:34 +04:00
subrec = FIRST_SUBNET ;
2010-01-28 13:04:05 +03:00
p - > recv_fd = - 1 ;
p - > send_fd = ( p - > packet_type = = NMB_PACKET ) ?
2005-06-09 02:10:34 +04:00
subrec - > nmb_sock : subrec - > dgram_sock ;
for ( subrec = FIRST_SUBNET ; subrec ! = NULL ;
subrec = NEXT_SUBNET_EXCLUDING_UNICAST ( subrec ) ) {
2007-10-25 01:16:54 +04:00
if ( ip_equal_v4 ( * local_ip , subrec - > myip ) ) {
2010-01-28 13:04:05 +03:00
p - > send_fd = ( p - > packet_type = = NMB_PACKET ) ?
2005-06-09 02:10:34 +04:00
subrec - > nmb_sock : subrec - > dgram_sock ;
break ;
}
}
if ( p - > packet_type = = DGRAM_PACKET ) {
p - > port = 138 ;
p - > packet . dgram . header . source_ip . s_addr = local_ip - > s_addr ;
p - > packet . dgram . header . source_port = 138 ;
}
2011-01-05 16:50:21 +03:00
send_packet ( p ) ;
2005-06-09 02:10:34 +04:00
}
2003-07-15 21:21:21 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
The main select loop .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
2011-12-13 19:59:55 +04:00
static void process ( struct messaging_context * msg )
1996-06-04 10:42:03 +04:00
{
2007-10-19 04:40:25 +04:00
bool run_election ;
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
while ( True ) {
time_t t = time ( NULL ) ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
1997-12-24 10:10:04 +03:00
2002-03-01 05:57:52 +03:00
/*
* Check all broadcast subnets to see if
* we need to run an election on any of them .
* ( nmbd_elections . c )
*/
1999-12-13 16:27:58 +03:00
2002-03-01 05:57:52 +03:00
run_election = check_elections ( ) ;
2000-01-03 06:17:16 +03:00
2002-03-01 05:57:52 +03:00
/*
* Read incoming UDP packets .
* ( nmbd_packets . c )
*/
1999-12-13 16:27:58 +03:00
2011-12-13 19:59:55 +04:00
if ( listen_for_packets ( msg , run_election ) ) {
2007-08-30 23:48:31 +04:00
TALLOC_FREE ( frame ) ;
2000-10-13 01:19:49 +04:00
return ;
2007-08-30 23:48:31 +04:00
}
1999-12-13 16:27:58 +03:00
2002-03-01 05:57:52 +03:00
/*
* Process all incoming packets
* read above . This calls the success and
* failure functions registered when response
2018-01-25 16:07:53 +03:00
* packets arrive , and also deals with request
2002-03-01 05:57:52 +03:00
* 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 ) ;
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
/*
* 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 ) ;
/* check for new network interfaces */
2008-03-07 04:43:25 +03:00
reload_interfaces ( t ) ;
2002-03-01 05:57:52 +03:00
/* free up temp memory */
2007-08-30 23:48:31 +04:00
TALLOC_FREE ( frame ) ;
2002-03-01 05:57:52 +03:00
}
}
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
2002-03-01 05:57:52 +03:00
Open the socket communication .
1997-12-13 17:16:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:57:52 +03:00
2007-10-19 04:40:25 +04:00
static bool open_sockets ( bool isdaemon , int port )
1996-06-04 10:42:03 +04:00
{
2007-10-25 01:16:54 +04:00
struct sockaddr_storage ss ;
2012-07-27 06:56:22 +04:00
const char * sock_addr = lp_nbt_client_socket_address ( ) ;
2007-10-25 01:16:54 +04:00
2002-03-01 05:57:52 +03: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 .
*/
2007-10-25 01:16:54 +04:00
if ( ! interpret_string_addr ( & ss , sock_addr ,
AI_NUMERICHOST | AI_PASSIVE ) ) {
DEBUG ( 0 , ( " open_sockets: unable to get socket address "
" from string %s " , sock_addr ) ) ;
return false ;
}
if ( ss . ss_family ! = AF_INET ) {
DEBUG ( 0 , ( " open_sockets: unable to use IPv6 socket "
" %s in nmbd \n " ,
sock_addr ) ) ;
return false ;
}
if ( isdaemon ) {
2003-04-25 16:42:32 +04:00
ClientNMB = open_socket_in ( SOCK_DGRAM , port ,
2007-10-25 01:16:54 +04:00
0 , & ss ,
true ) ;
} else {
2007-10-11 00:34:30 +04:00
ClientNMB = 0 ;
2007-10-25 01:16:54 +04:00
}
2008-01-24 18:12:42 +03:00
if ( ClientNMB = = - 1 ) {
return false ;
}
2005-11-08 02:28:42 +03:00
ClientDGRAM = open_socket_in ( SOCK_DGRAM , DGRAM_PORT ,
2007-10-25 01:16:54 +04:00
3 , & ss ,
true ) ;
1996-06-04 10:42:03 +04:00
2008-01-24 18:12:42 +03:00
if ( ClientDGRAM = = - 1 ) {
if ( ClientNMB ! = 0 ) {
close ( ClientNMB ) ;
}
2007-10-25 01:16:54 +04:00
return false ;
}
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
/* we are never interested in SIGPIPE */
BlockSignals ( True , SIGPIPE ) ;
1996-06-04 10:42:03 +04:00
2002-03-01 05:57:52 +03:00
set_socket_options ( ClientNMB , " SO_BROADCAST " ) ;
set_socket_options ( ClientDGRAM , " SO_BROADCAST " ) ;
1996-06-04 10:42:03 +04:00
2006-05-18 23:49:44 +04:00
/* Ensure we're non-blocking. */
set_blocking ( ClientNMB , False ) ;
set_blocking ( ClientDGRAM , False ) ;
2002-03-01 05:57:52 +03:00
DEBUG ( 3 , ( " open_sockets: Broadcast sockets opened. \n " ) ) ;
return ( True ) ;
}
1996-06-04 10:42:03 +04:00
1997-12-13 17:16:07 +03:00
/**************************************************************************** **
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 22:38:36 +04:00
2002-11-09 19:57:45 +03:00
int main ( int argc , const char * argv [ ] )
1996-06-04 10:42:03 +04:00
{
2012-02-15 02:56:43 +04:00
bool is_daemon = false ;
bool opt_interactive = false ;
2011-12-13 20:07:39 +04:00
bool Fork = true ;
2012-02-15 02:56:43 +04:00
bool no_process_group = false ;
bool log_stdout = false ;
2002-11-09 19:57:45 +03:00
poptContext pc ;
2007-12-10 22:30:37 +03:00
char * p_lmhosts = NULL ;
2007-08-21 18:22:16 +04:00
int opt ;
2011-12-13 20:10:33 +04:00
struct messaging_context * msg ;
2007-10-19 22:38:36 +04:00
enum {
OPT_DAEMON = 1000 ,
OPT_INTERACTIVE ,
OPT_FORK ,
OPT_NO_PROCESS_GROUP ,
OPT_LOG_STDOUT
} ;
2002-11-09 19:57:45 +03:00
struct poptOption long_options [ ] = {
2019-01-14 12:56:08 +03:00
POPT_AUTOHELP
{
. longName = " daemon " ,
. shortName = ' D ' ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = OPT_DAEMON ,
2019-01-18 03:15:36 +03:00
. descrip = " Become a daemon (default) " ,
2019-01-14 12:56:08 +03:00
} ,
{
. longName = " interactive " ,
. shortName = ' i ' ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = OPT_INTERACTIVE ,
. descrip = " Run interactive (not a daemon) " ,
} ,
{
. longName = " foreground " ,
. shortName = ' F ' ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = OPT_FORK ,
2019-01-18 03:15:36 +03:00
. descrip = " Run daemon in foreground "
" (for daemontools, etc.) " ,
2019-01-14 12:56:08 +03:00
} ,
{
. longName = " no-process-group " ,
. shortName = 0 ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = OPT_NO_PROCESS_GROUP ,
. descrip = " Don't create a new process group " ,
} ,
{
. longName = " log-stdout " ,
. shortName = ' S ' ,
. argInfo = POPT_ARG_NONE ,
. arg = NULL ,
. val = OPT_LOG_STDOUT ,
. descrip = " Log to stdout " ,
} ,
{
. longName = " hosts " ,
. shortName = ' H ' ,
. argInfo = POPT_ARG_STRING ,
. arg = & p_lmhosts ,
. val = 0 ,
. descrip = " Load a netbios hosts file " ,
} ,
{
. longName = " port " ,
. shortName = ' p ' ,
. argInfo = POPT_ARG_INT ,
. arg = & global_nmb_port ,
. val = 0 ,
. descrip = " Listen on the specified port " ,
} ,
POPT_COMMON_SAMBA
POPT_TABLEEND
2002-11-09 19:57:45 +03:00
} ;
2010-09-24 20:45:52 +04:00
TALLOC_CTX * frame ;
2010-07-04 18:28:13 +04:00
NTSTATUS status ;
2012-12-13 21:16:34 +04:00
bool ok ;
1998-08-31 10:59:23 +04:00
2010-09-24 20:45:52 +04:00
/*
* Do this before any other talloc operation
*/
talloc_enable_null_tracking ( ) ;
frame = talloc_stackframe ( ) ;
2013-06-18 04:25:41 +04:00
/*
* We want total control over the permissions on created files ,
* so set our umask to 0.
*/
umask ( 0 ) ;
2011-07-18 11:07:25 +04:00
setup_logging ( argv [ 0 ] , DEBUG_DEFAULT_STDOUT ) ;
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2005-12-29 16:10:33 +03:00
2003-04-16 18:25:56 +04:00
global_nmb_port = NMB_PORT ;
1996-06-04 10:42:03 +04:00
2003-04-16 18:25:56 +04:00
pc = poptGetContext ( " nmbd " , argc , argv , long_options , 0 ) ;
2007-08-21 18:22:16 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
2007-10-19 22:38:36 +04:00
case OPT_DAEMON :
is_daemon = true ;
break ;
case OPT_INTERACTIVE :
opt_interactive = true ;
break ;
case OPT_FORK :
Fork = false ;
break ;
case OPT_NO_PROCESS_GROUP :
no_process_group = true ;
break ;
case OPT_LOG_STDOUT :
log_stdout = true ;
break ;
2007-08-21 18:22:16 +04:00
default :
2007-08-22 16:06:27 +04:00
d_fprintf ( stderr , " \n Invalid option %s: %s \n \n " ,
2007-08-21 18:22:16 +04:00
poptBadOption ( pc , 0 ) , poptStrerror ( opt ) ) ;
2007-08-22 16:06:27 +04:00
poptPrintUsage ( pc , stderr , 0 ) ;
2007-08-21 18:22:16 +04:00
exit ( 1 ) ;
}
} ;
2003-04-16 18:25:56 +04:00
poptFreeContext ( pc ) ;
1996-06-04 10:42:03 +04:00
2007-10-25 01:16:54 +04:00
global_in_nmbd = true ;
2011-12-13 14:00:16 +04:00
2003-04-16 18:25:56 +04:00
StartupTime = time ( NULL ) ;
2011-12-13 14:00:16 +04:00
2012-03-24 23:17:08 +04:00
sys_srandom ( time ( NULL ) ^ getpid ( ) ) ;
2011-12-13 14:00:16 +04:00
2004-09-21 13:07:42 +04:00
if ( ! override_logfile ) {
2008-11-03 23:36:34 +03:00
char * lfile = NULL ;
if ( asprintf ( & lfile , " %s/log.nmbd " , get_dyn_LOGFILEBASE ( ) ) < 0 ) {
2007-11-20 02:15:09 +03:00
exit ( 1 ) ;
}
2008-11-03 23:36:34 +03:00
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
2004-09-21 13:07:42 +04:00
}
2011-12-13 14:00:16 +04:00
2011-03-22 06:05:23 +03:00
fault_setup ( ) ;
2012-07-18 09:37:23 +04:00
dump_core_setup ( " nmbd " , lp_logfile ( talloc_tos ( ) ) ) ;
2011-12-13 14:00:16 +04:00
2003-04-16 18:25:56 +04:00
/* POSIX demands that signals are inherited. If the invoking process has
* these signals masked , we will have problems , as we won ' t receive them . */
BlockSignals ( False , SIGHUP ) ;
BlockSignals ( False , SIGUSR1 ) ;
BlockSignals ( False , SIGTERM ) ;
2009-01-22 18:17:23 +03:00
1999-12-13 16:27:58 +03:00
# if defined(SIGFPE)
2003-04-16 18:25:56 +04:00
/* we are never interested in SIGFPE */
BlockSignals ( True , SIGFPE ) ;
1999-12-13 16:27:58 +03:00
# endif
2003-04-16 18:25:56 +04:00
/* We no longer use USR2... */
2000-10-13 01:19:49 +04:00
# if defined(SIGUSR2)
2003-04-16 18:25:56 +04:00
BlockSignals ( True , SIGUSR2 ) ;
2000-10-13 01:19:49 +04:00
# endif
2003-01-03 20:39:30 +03:00
2014-09-24 00:32:37 +04:00
/* Ignore children - no zombies. */
CatchChild ( ) ;
2007-10-11 00:34:30 +04:00
if ( opt_interactive ) {
Fork = False ;
2003-04-16 18:25:56 +04:00
log_stdout = True ;
}
2003-01-03 20:39:30 +03:00
2007-10-11 00:34:30 +04:00
if ( log_stdout & & Fork ) {
2003-08-23 05:59:14 +04:00
DEBUG ( 0 , ( " ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i) \n " ) ) ;
exit ( 1 ) ;
}
2011-07-18 11:07:25 +04:00
2010-10-29 07:19:32 +04:00
if ( log_stdout ) {
2011-07-18 11:07:25 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDOUT ) ;
2010-10-29 07:19:32 +04:00
} else {
setup_logging ( argv [ 0 ] , DEBUG_FILE ) ;
}
2001-11-27 06:40:06 +03:00
2003-08-23 05:59:14 +04:00
reopen_logs ( ) ;
1998-04-16 00:00:41 +04:00
2009-01-16 00:27:52 +03:00
DEBUG ( 0 , ( " nmbd version %s started. \n " , samba_version_string ( ) ) ) ;
2007-10-30 17:44:27 +03:00
DEBUGADD ( 0 , ( " %s \n " , COPYRIGHT_STARTUP_MESSAGE ) ) ;
1996-06-04 10:42:03 +04:00
2008-04-15 12:50:27 +04:00
if ( ! lp_load_initial_only ( get_dyn_CONFIGFILE ( ) ) ) {
2011-03-23 03:22:15 +03:00
DEBUG ( 0 , ( " error opening config file '%s' \n " , get_dyn_CONFIGFILE ( ) ) ) ;
2008-04-15 12:50:27 +04:00
exit ( 1 ) ;
}
2014-03-19 18:01:11 +04:00
reopen_logs ( ) ;
2012-08-22 15:01:16 +04:00
if ( lp_server_role ( ) = = ROLE_ACTIVE_DIRECTORY_DC
& & ! lp_parm_bool ( - 1 , " server role check " , " inhibit " , false ) ) {
/* TODO: when we have a merged set of defaults for
* loadparm , we could possibly check if the internal
* nbt server is in the list , and allow a startup if disabled */
DEBUG ( 0 , ( " server role = 'active directory domain controller' not compatible with running nmbd standalone. \n " ) ) ;
DEBUGADD ( 0 , ( " You should start 'samba' instead, and it will control starting the internal nbt server \n " ) ) ;
exit ( 1 ) ;
}
2013-10-17 17:19:41 +04:00
if ( ! cluster_probe_ok ( ) ) {
exit ( 1 ) ;
}
2018-08-21 21:06:16 +03:00
msg = messaging_init ( NULL , global_event_context ( ) ) ;
2011-12-13 20:10:33 +04:00
if ( msg = = NULL ) {
2008-04-15 12:50:27 +04:00
return 1 ;
}
2003-08-23 05:59:14 +04:00
if ( ! reload_nmbd_services ( False ) )
return ( - 1 ) ;
1996-10-02 19:41:30 +04:00
2003-08-23 05:59:14 +04:00
if ( ! init_names ( ) )
return - 1 ;
1996-08-19 15:17:29 +04:00
2003-08-23 05:59:14 +04:00
reload_nmbd_services ( True ) ;
1996-08-22 10:32:03 +04:00
2003-08-23 05:59:14 +04:00
if ( strequal ( lp_workgroup ( ) , " * " ) ) {
DEBUG ( 0 , ( " ERROR: a workgroup name of * is no longer supported \n " ) ) ;
exit ( 1 ) ;
}
1998-12-09 19:23:57 +03:00
2003-08-23 05:59:14 +04:00
set_samba_nb_type ( ) ;
1996-08-01 21:49:40 +04:00
2007-10-11 00:34:30 +04:00
if ( ! is_daemon & & ! is_a_socket ( 0 ) ) {
2014-03-26 19:18:55 +04:00
DEBUG ( 3 , ( " standard input is not a socket, assuming -D option \n " ) ) ;
2007-10-11 00:34:30 +04:00
is_daemon = True ;
2003-08-23 05:59:14 +04:00
}
2011-12-13 14:00:16 +04:00
2007-10-11 00:34:30 +04:00
if ( is_daemon & & ! opt_interactive ) {
2014-03-26 19:18:55 +04:00
DEBUG ( 3 , ( " Becoming a daemon. \n " ) ) ;
2010-03-26 13:17:37 +03:00
become_daemon ( Fork , no_process_group , log_stdout ) ;
2003-08-23 05:59:14 +04:00
}
1996-06-04 10:42:03 +04:00
2018-11-20 17:55:43 +03:00
# ifdef HAVE_SETPGID
2003-08-23 05:59:14 +04:00
/*
* If we ' re interactive we want to set our own process group for
* signal management .
*/
2007-10-11 00:34:30 +04:00
if ( opt_interactive & & ! no_process_group )
2003-08-23 05:59:14 +04:00
setpgid ( ( pid_t ) 0 , ( pid_t ) 0 ) ;
2001-12-30 04:46:38 +03:00
# endif
1999-12-13 16:27:58 +03:00
# ifndef SYNC_DNS
2003-08-23 05:59:14 +04:00
/* Setup the async dns. We do it here so it doesn't have all the other
stuff initialised and thus chewing memory and sockets */
2012-05-28 10:51:47 +04:00
if ( lp_we_are_a_wins_server ( ) & & lp_wins_dns_proxy ( ) ) {
2011-12-13 20:10:33 +04:00
start_async_dns ( msg ) ;
2003-08-23 05:59:14 +04:00
}
1999-12-13 16:27:58 +03:00
# endif
2014-07-27 21:18:09 +04:00
ok = directory_create_or_exist ( lp_lock_directory ( ) , 0755 ) ;
2012-12-13 21:16:34 +04:00
if ( ! ok ) {
2014-03-26 13:34:56 +04:00
exit_daemon ( " Failed to create directory for lock files, check 'lock directory' " , errno ) ;
2003-08-23 05:59:14 +04:00
}
2014-07-27 21:18:09 +04:00
ok = directory_create_or_exist ( lp_pid_directory ( ) , 0755 ) ;
2012-12-13 21:16:34 +04:00
if ( ! ok ) {
2014-03-26 13:34:56 +04:00
exit_daemon ( " Failed to create directory for pid files, check 'pid directory' " , errno ) ;
2012-03-07 05:58:37 +04:00
}
2014-02-03 06:57:21 +04:00
pidfile_create ( lp_pid_directory ( ) , " nmbd " ) ;
2008-04-01 16:01:28 +04:00
2015-09-23 21:14:05 +03:00
status = reinit_after_fork ( msg , nmbd_event_context ( ) , false , NULL ) ;
2010-07-04 18:28:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-26 13:34:56 +04:00
exit_daemon ( " reinit_after_fork() failed " , map_errno_from_nt_status ( status ) ) ;
2008-04-15 12:38:21 +04:00
}
2012-03-15 19:29:27 +04:00
/*
* Do not initialize the parent - child - pipe before becoming
* a daemon : this is used to detect a died parent in the child
* process .
*/
status = init_before_fork ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-26 13:34:56 +04:00
exit_daemon ( nt_errstr ( status ) , map_errno_from_nt_status ( status ) ) ;
2012-03-15 19:29:27 +04:00
}
2011-12-13 20:10:33 +04:00
if ( ! nmbd_setup_sig_term_handler ( msg ) )
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed to setup signal handler " , EINVAL ) ;
2012-03-02 11:21:09 +04:00
if ( ! nmbd_setup_stdin_handler ( msg , ! Fork ) )
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed to setup stdin handler " , EINVAL ) ;
2011-12-13 20:10:33 +04:00
if ( ! nmbd_setup_sig_hup_handler ( msg ) )
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed to setup SIGHUP handler " , EINVAL ) ;
2009-01-22 18:17:23 +03:00
2014-04-19 02:08:19 +04:00
if ( ! messaging_parent_dgm_cleanup_init ( msg ) ) {
exit ( 1 ) ;
}
2011-12-13 20:10:33 +04:00
messaging_register ( msg , NULL , MSG_FORCE_ELECTION ,
nmbd_message_election ) ;
2005-12-07 02:06:38 +03:00
#if 0
/* Until winsrepl is done. */
2011-12-13 20:10:33 +04:00
messaging_register ( msg , NULL , MSG_WINS_NEW_ENTRY ,
nmbd_wins_new_entry ) ;
2005-12-07 02:06:38 +03:00
# endif
2011-12-13 20:10:33 +04:00
messaging_register ( msg , NULL , MSG_SHUTDOWN ,
nmbd_terminate ) ;
messaging_register ( msg , NULL , MSG_SMB_CONF_UPDATED ,
msg_reload_nmbd_services ) ;
messaging_register ( msg , NULL , MSG_SEND_PACKET ,
msg_nmbd_send_packet ) ;
2003-08-23 05:59:14 +04:00
2005-11-05 07:21:55 +03:00
TimeInit ( ) ;
2003-08-23 05:59:14 +04:00
DEBUG ( 3 , ( " Opening sockets %d \n " , global_nmb_port ) ) ;
2007-10-11 00:34:30 +04:00
if ( ! open_sockets ( is_daemon , global_nmb_port ) ) {
2003-08-23 05:59:14 +04:00
kill_async_dns_child ( ) ;
return 1 ;
}
/* Determine all the IP addresses we have. */
load_interfaces ( ) ;
/* Create an nmbd subnet record for each of the above. */
if ( False = = create_subnets ( ) ) {
kill_async_dns_child ( ) ;
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed when creating subnet lists " , EACCES ) ;
2003-08-23 05:59:14 +04:00
}
/* Load in any static local names. */
2007-12-10 22:30:37 +03:00
if ( p_lmhosts ) {
set_dyn_LMHOSTSFILE ( p_lmhosts ) ;
}
load_lmhosts_file ( get_dyn_LMHOSTSFILE ( ) ) ;
DEBUG ( 3 , ( " Loaded hosts file %s \n " , get_dyn_LMHOSTSFILE ( ) ) ) ;
2003-08-23 05:59:14 +04:00
/* If we are acting as a WINS server, initialise data structures. */
if ( ! initialise_wins ( ) ) {
kill_async_dns_child ( ) ;
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed when initialising WINS server. " , EACCES ) ;
2003-08-23 05:59:14 +04: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 ( ) ) {
kill_async_dns_child ( ) ;
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed when creating my workgroup. " , EACCES ) ;
2003-08-23 05:59:14 +04:00
}
2009-01-28 12:10:12 +03:00
if ( ! initialize_nmbd_proxy_logon ( ) ) {
kill_async_dns_child ( ) ;
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed to setup nmbd_proxy_logon. " , EACCES ) ;
2009-01-28 12:10:12 +03:00
}
2011-01-04 19:58:12 +03:00
if ( ! nmbd_init_packet_server ( ) ) {
kill_async_dns_child ( ) ;
2014-03-26 13:34:56 +04:00
exit_daemon ( " NMBD failed to setup packet server. " , EACCES ) ;
}
2011-01-04 19:58:12 +03:00
2014-03-25 14:53:04 +04:00
if ( is_daemon & & ! opt_interactive ) {
daemon_ready ( " nmbd " ) ;
}
2007-11-16 01:19:52 +03:00
TALLOC_FREE ( frame ) ;
2011-12-13 20:10:33 +04:00
process ( msg ) ;
2003-08-23 05:59:14 +04:00
kill_async_dns_child ( ) ;
return ( 0 ) ;
2002-03-01 05:57:52 +03:00
}