diff options
Diffstat (limited to 'source/nmbd/nmbd.c')
-rw-r--r-- | source/nmbd/nmbd.c | 1186 |
1 files changed, 664 insertions, 522 deletions
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 880de7f91bf..e95167ff136 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -1,9 +1,8 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Jeremy Allison 1997-2002 - Copyright (C) Jelmer Vernooij 2002,2003 (Conversion to popt) 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 @@ -19,24 +18,30 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + Revision History: + + 14 jan 96: lkcl@pires.co.uk + added multiple workgroup domain master support + */ #include "includes.h" +pstring servicesf = CONFIGFILE; + int ClientNMB = -1; int ClientDGRAM = -1; int global_nmb_port = -1; +static pstring host_file; +extern pstring global_myname; +extern fstring global_myworkgroup; +extern char **my_netbios_names; + extern BOOL global_in_nmbd; /* are we running as a daemon ? */ -static BOOL is_daemon; - -/* fork or run in foreground ? */ -static BOOL Fork = True; - -/* log to standard output ? */ -static BOOL log_stdout; +static BOOL is_daemon = False; /* have we found LanMan clients yet? */ BOOL found_lm_clients = False; @@ -52,13 +57,13 @@ time_t StartupTime = 0; static void terminate(void) { DEBUG(0,("Got SIGTERM: going down...\n")); - + /* Write out wins.dat file if samba is a WINS server */ wins_write_database(False); - - /* Remove all SELF registered names from WINS */ - release_wins_names(); - + + /* Remove all SELF registered names. */ + release_my_names(); + /* Announce all server entries as 0 time-to-live, 0 type. */ announce_my_servers_removed(); @@ -69,15 +74,6 @@ static void terminate(void) } /**************************************************************************** ** - Handle a SHUTDOWN message from smbcontrol. - **************************************************************************** */ - -static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len) -{ - terminate(); -} - -/**************************************************************************** ** Catch a SIGTERM signal. **************************************************************************** */ @@ -108,37 +104,37 @@ static void sig_hup(int sig) static BOOL dump_core(void) { - 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) ); + char *p; + pstring dname; + pstrcpy( dname, lp_logfile() ); + if ((p=strrchr(dname,'/'))) + *p=0; + pstrcat( dname, "/corefiles" ); + mkdir( dname, 0700 ); + sys_chown( dname, getuid(), getgid() ); + chmod( dname, 0700 ); + if ( chdir(dname) ) + return( False ); + umask( ~(0700) ); #ifdef HAVE_GETRLIMIT #ifdef RLIMIT_CORE - { - 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 ) ); - } + { + 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 ) ); + } #endif #endif - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return( True ); -} + DEBUG(0,("Dumping core in %s\n",dname)); + abort(); + return( True ); +} /* dump_core */ #endif /**************************************************************************** ** @@ -148,9 +144,9 @@ static BOOL dump_core(void) static void fault_continue(void) { #if DUMP_CORE - dump_core(); + dump_core(); #endif -} +} /* fault_continue */ /**************************************************************************** ** Expire old names from the namelist and server list. @@ -158,32 +154,30 @@ static void fault_continue(void) static void expire_names_and_servers(time_t t) { - static time_t lastrun = 0; + static time_t lastrun = 0; - if ( !lastrun ) - lastrun = t; - if ( t < (lastrun + 5) ) - return; - lastrun = t; - - /* - * Expire any timed out names on all the broadcast - * subnets and those registered with the WINS server. - * (nmbd_namelistdb.c) - */ - - expire_names(t); - - /* - * 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); -} + if ( !lastrun ) + lastrun = t; + if ( t < (lastrun + 5) ) + return; + lastrun = t; + + /* + * Expire any timed out names on all the broadcast + * subnets and those registered with the WINS server. + * (nmbd_namelistdb.c) + */ + expire_names(t); + + /* + * 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 */ /************************************************************************** ** Reload the list of network interfaces. @@ -231,8 +225,7 @@ static BOOL reload_interfaces(time_t t) DEBUG(2,("Found new interface %s\n", inet_ntoa(iface->ip))); subrec = make_normal_subnet(iface); - if (subrec) - register_my_workgroup_one_subnet(subrec); + if (subrec) register_my_workgroup_one_subnet(subrec); } } @@ -272,500 +265,649 @@ static BOOL reload_interfaces(time_t t) static BOOL reload_nmbd_services(BOOL test) { - BOOL ret; - - set_remote_machine_name("nmbd", False); - - if ( lp_loaded() ) { - pstring fname; - pstrcpy( fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); - test = False; - } - } - - if ( test && !lp_file_list_changed() ) - return(True); - - ret = lp_load( dyn_CONFIGFILE, True , False, False); - - /* perhaps the config filename is now set */ - if ( !test ) { - DEBUG( 3, ( "services not loaded\n" ) ); - reload_nmbd_services( True ); - } - - return(ret); -} + BOOL ret; + extern fstring remote_machine; + + fstrcpy( remote_machine, "nmbd" ); + + if ( lp_loaded() ) + { + pstring fname; + pstrcpy( fname,lp_configfile()); + if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) + { + pstrcpy(servicesf,fname); + test = False; + } + } + + if ( test && !lp_file_list_changed() ) + return(True); + + ret = lp_load( servicesf, True , False, False); + + /* perhaps the config filename is now set */ + if ( !test ) + { + DEBUG( 3, ( "services not loaded\n" ) ); + reload_nmbd_services( True ); + } + + /* Do a sanity check for a misconfigured nmbd */ + if( lp_wins_support() && *lp_wins_server() ) + { + DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \ +cannot be set in the smb.conf file. nmbd aborting.\n")); + exit(10); + } + + return(ret); +} /* reload_nmbd_services */ /**************************************************************************** ** - * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP - * We use buf here to return BOOL result to process() when reload_interfaces() - * detects that there are no subnets. + The main select loop. **************************************************************************** */ -static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len) +static void process(void) { - write_browse_list( 0, True ); - dump_all_namelists(); - reload_nmbd_services( True ); - reopen_logs(); - - if(buf) { - /* We were called from process() */ - /* If reload_interfaces() returned True */ - /* we need to shutdown if there are no subnets... */ - /* pass this info back to process() */ - *((BOOL*)buf) = reload_interfaces(0); - } -} + BOOL run_election; + + while( True ) + { + time_t t = time(NULL); + + /* 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) + */ + run_election = check_elections(); + + /* + * Read incoming UDP packets. + * (nmbd_packets.c) + */ + if(listen_for_packets(run_election)) + return; + + /* + * Handle termination inband. + */ + + 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); + + /* + * 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<1c> 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<1b> 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(); + } +} /* process */ /**************************************************************************** ** - The main select loop. + Open the socket communication. **************************************************************************** */ -static void process(void) +static BOOL open_sockets(BOOL isdaemon, int port) { - BOOL run_election; - BOOL no_subnets; - - while( True ) { - time_t t = time(NULL); - - /* 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) - */ - - run_election = check_elections(); - - /* - * Read incoming UDP packets. - * (nmbd_packets.c) - */ - - if(listen_for_packets(run_election)) - return; - - /* - * Handle termination inband. - */ - - 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); - - /* - * 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) - */ + /* 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,interpret_addr(lp_socket_address()),True); + else + ClientNMB = 0; + + ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True); - dmb_expire_and_sync_browser_lists(t); + if ( ClientNMB == -1 ) + return( False ); - /* - * 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) - */ + /* we are never interested in SIGPIPE */ + BlockSignals(True,SIGPIPE); - check_master_browser_exists(t); + set_socket_options( ClientNMB, "SO_BROADCAST" ); + set_socket_options( ClientDGRAM, "SO_BROADCAST" ); - /* - * If we are configured as a logon server, attempt to - * register the special NetBIOS names to become such - * (WORKGROUP<1c> 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<1b> name) to - * become such. - * (nmbd_become_dmb.c) - */ + DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); + return( True ); +} /* open_sockets */ - add_domain_names(t); - - /* - * If we are a WINS server, do any timer dependent - * processing required. - * (nmbd_winsserver.c) - */ - - initiate_wins_processing(t); +/**************************************************************************** ** + Initialise connect, service and file structs. + **************************************************************************** */ - /* - * 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) - */ +static BOOL init_structs(void) +{ + extern fstring local_machine; + char *p; + const char *ptr; + int namecount; + int n; + int nodup; + pstring nbname; + + if (! *global_myname) + { + fstrcpy( global_myname, myhostname() ); + p = strchr( global_myname, '.' ); + if (p) + *p = 0; + } + strupper( global_myname ); + + /* Add any NETBIOS name aliases. Ensure that the first entry + is equal to global_myname. + */ + /* Work out the max number of netbios aliases that we have */ + ptr = lp_netbios_aliases(); + for( namecount=0; next_token(&ptr,nbname,NULL, sizeof(nbname)); namecount++ ) + ; + if ( *global_myname ) + namecount++; + + /* Allocate space for the netbios aliases */ + my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) ); + if( NULL == my_netbios_names ) + { + DEBUG( 0, ( "init_structs: malloc fail.\n" ) ); + return( False ); + } + + /* Use the global_myname string first */ + namecount=0; + if ( *global_myname ) + my_netbios_names[namecount++] = global_myname; + + ptr = lp_netbios_aliases(); + while ( next_token( &ptr, nbname, NULL, sizeof(nbname) ) ) + { + 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++] = strdup( nbname ); + } + + /* Check the strdups succeeded. */ + for( n = 0; n < namecount; n++ ) + if( NULL == my_netbios_names[n] ) + { + DEBUG(0,("init_structs: malloc fail when allocating names.\n")); + return False; + } + + /* Terminate name list */ + my_netbios_names[namecount++] = NULL; + + fstrcpy( local_machine, global_myname ); + trim_string( local_machine, " ", " " ); + p = strchr( local_machine, ' ' ); + if (p) + *p = 0; + strlower( local_machine ); - if (lp_enhanced_browsing()) - collect_all_workgroup_names_from_wins_server(t); + DEBUG( 5, ("Netbios name list:-\n") ); + for( n=0; my_netbios_names[n]; n++ ) + DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) ); - /* - * Go through the response record queue and time out or re-transmit - * and expired entries. - * (nmbd_packets.c) - */ + return( True ); +} /* init_structs */ - retransmit_or_expire_response_records(t); +/**************************************************************************** ** + Usage on the program. + **************************************************************************** */ - /* - * check to see if any remote browse sync child processes have completed - */ +static void usage(char *pname) +{ - sync_check_completion(); + printf( "Usage: %s [-DaiohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname ); + printf( " [-n name] [-p port] [-s configuration file]\n" ); + printf( "\t-D Become a daemon (default)\n" ); + printf( "\t-a Append to log file (default)\n" ); + printf( "\t-i Run interactive (not a daemon)\n" ); + 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" ); + printf( "\t-l log basename. Basename for log/debug files\n" ); + 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" ); + printf( "\n"); +} /* usage */ - /* - * regularly sync with any other DMBs we know about - */ - if (lp_enhanced_browsing()) - sync_all_dmbs(t); +/**************************************************************************** ** + Main program. + **************************************************************************** */ - /* - * clear the unexpected packet queue - */ + int main(int argc,char *argv[]) +{ + int opt; + extern FILE *dbf; + extern char *optarg; + extern BOOL append_log; + extern BOOL AllowDebugChange; + BOOL opt_interactive = False; + pstring logfile; - clear_unexpected(t); + append_log = True; /* Default, override with '-o' option. */ - /* - * Reload the services file if we got a sighup. - */ + global_nmb_port = NMB_PORT; + *host_file = 0; + global_in_nmbd = True; - if(reload_after_sighup) { - DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); - msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, (void*) &no_subnets, 0); - if(no_subnets) - return; - reload_after_sighup = 0; - } + StartupTime = time(NULL); - /* check for new network interfaces */ + sys_srandom(time(NULL) ^ sys_getpid()); - if(reload_interfaces(t)) - return; + TimeInit(); - /* free up temp memory */ - lp_talloc_free(); - } -} + slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", LOGFILEBASE); + lp_set_logfile(logfile); -/**************************************************************************** ** - Open the socket communication. - **************************************************************************** */ + charset_initialise(); -static BOOL open_sockets(BOOL isdaemon, int port) -{ - /* - * 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, interpret_addr(lp_socket_address()), - True); - else - ClientNMB = 0; - - ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True); +#ifdef LMHOSTSFILE + pstrcpy( host_file, LMHOSTSFILE ); +#endif - if ( ClientNMB == -1 ) - return( False ); + /* this is for people who can't start the program correctly */ + while (argc > 1 && (*argv[1] != '-')) + { + argv++; + argc--; + } - /* we are never interested in SIGPIPE */ - BlockSignals(True,SIGPIPE); + fault_setup((void (*)(void *))fault_continue ); - set_socket_options( ClientNMB, "SO_BROADCAST" ); - set_socket_options( ClientDGRAM, "SO_BROADCAST" ); + /* 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); - DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); - return( True ); -} + CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); + CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); -/**************************************************************************** ** - main program - **************************************************************************** */ - int main(int argc, const char *argv[]) -{ - pstring logfile; - static BOOL opt_interactive; - poptContext pc; - int opt; - struct poptOption long_options[] = { - POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" }, - {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" }, - {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, - {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, - {"hosts", 'H', POPT_ARG_STRING, dyn_LMHOSTSFILE, 'H', "Load a netbios hosts file"}, - {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" }, - POPT_COMMON_SAMBA - { NULL } - }; - - global_nmb_port = NMB_PORT; - - pc = poptGetContext("nmbd", argc, argv, long_options, 0); - while ((opt = poptGetNextOpt(pc)) != -1) ; - poptFreeContext(pc); - - global_in_nmbd = True; - - StartupTime = time(NULL); - - sys_srandom(time(NULL) ^ sys_getpid()); - - slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - fault_setup((void (*)(void *))fault_continue ); - - /* 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); - - CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); - CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); - #if defined(SIGFPE) - /* we are never interested in SIGFPE */ - BlockSignals(True,SIGFPE); + /* we are never interested in SIGFPE */ + BlockSignals(True,SIGFPE); #endif - /* We no longer use USR2... */ + /* We no longer use USR2... */ #if defined(SIGUSR2) - BlockSignals(True, SIGUSR2); + BlockSignals(True, SIGUSR2); #endif - if ( opt_interactive ) { - Fork = False; - log_stdout = True; - } - - if ( log_stdout && Fork ) { - DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); - exit(1); - } - - setup_logging( argv[0], log_stdout ); - - reopen_logs(); - - DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) ); - DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2004\n" ) ); - - if ( !reload_nmbd_services(False) ) - return(-1); - - if(!init_names()) - return -1; - - reload_nmbd_services( True ); - - if (strequal(lp_workgroup(),"*")) { - DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); - exit(1); - } - - set_samba_nb_type(); - - if (!is_daemon && !is_a_socket(0)) { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } + while( EOF != + (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dip:hSH:G:f:" )) ) + { + switch (opt) + { + 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(global_myname,optarg); + strupper(global_myname); + break; + case 'l': + slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", optarg); + lp_set_logfile(logfile); + break; + case 'a': + append_log = True; + break; + case 'o': + append_log = False; + break; + case 'i': + opt_interactive = True; + break; + case 'D': + is_daemon = True; + break; + case 'd': + DEBUGLEVEL = atoi(optarg); + AllowDebugChange = False; + break; + case 'p': + global_nmb_port = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + case 'V': + printf( "Version %s\n", VERSION ); + exit(0); + break; + default: + if( !is_a_socket(0) ) + { + DEBUG(0,("Incorrect program usage - is the command line correct?\n")); + usage(argv[0]); + exit(0); + } + break; + } + } + + setup_logging( argv[0], opt_interactive ); + reopen_logs(); + + DEBUG( 0, ( "Netbios nameserver version %s started.\n", VERSION ) ); + DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) ); + + if ( !reload_nmbd_services(False) ) + return(-1); + +#ifdef WITH_PROFILE + if (!profile_setup(False)) { + DEBUG(0,("ERROR: failed to setup profiling shared memory\n")); + return -1; + } +#endif /* WITH_PROFILE */ + + codepage_initialise(lp_client_code_page()); + + if(!init_structs()) + return -1; + + reload_nmbd_services( True ); + + fstrcpy( global_myworkgroup, lp_workgroup() ); + + if (strequal(global_myworkgroup,"*")) + { + DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); + exit(1); + } + + set_samba_nb_type(); + + if (!is_daemon && !is_a_socket(0)) + { + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + is_daemon = True; + } - if (is_daemon && !opt_interactive) { - DEBUG( 2, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork); - } + if (is_daemon && !opt_interactive) + { + DEBUG( 2, ( "Becoming a daemon.\n" ) ); + become_daemon(); + } #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 ); + /* + * 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 #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 */ - if(lp_we_are_a_wins_server() && lp_dns_proxy()) { - start_async_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 */ + if(lp_we_are_a_wins_server()) { + start_async_dns(); + } #endif - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } - - pidfile_create("nmbd"); - message_init(); - message_register(MSG_FORCE_ELECTION, nmbd_message_election); - message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); - message_register(MSG_SHUTDOWN, nmbd_terminate); - message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); - - DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); - - if ( !open_sockets( is_daemon, global_nmb_port ) ) { - 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() ) { - DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); - kill_async_dns_child(); - exit(1); - } - - /* Load in any static local names. */ - load_lmhosts_file(dyn_LMHOSTSFILE); - DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE)); - - /* If we are acting as a WINS server, initialise data structures. */ - if( !initialise_wins() ) { - DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); - kill_async_dns_child(); - exit(1); - } - - /* - * 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")); - kill_async_dns_child(); - exit(1); - } - - /* We can only take signals in the select. */ - BlockSignals( True, SIGTERM ); - - process(); - - if (dbf) - x_fclose(dbf); - kill_async_dns_child(); - return(0); -} + if (!directory_exist(lp_lockdir(), NULL)) { + mkdir(lp_lockdir(), 0755); + } + + pidfile_create("nmbd"); + message_init(); + message_register(MSG_FORCE_ELECTION, nmbd_message_election); + + DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); + + if ( !open_sockets( is_daemon, global_nmb_port ) ) + 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() ) + { + DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); + exit(1); + } + + /* Load in any static local names. */ + if ( *host_file ) + { + load_lmhosts_file(host_file); + DEBUG(3,("Loaded hosts file\n")); + } + + /* 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); + } + + /* + * 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); + } + + /* We can only take signals in the select. */ + BlockSignals( True, SIGTERM ); + + process(); + + if (dbf) + fclose(dbf); + return(0); +} /* main */ |