2 Unix SMB/Netbios implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 14 jan 96: lkcl@pires.co.uk
23 added multiple workgroup domain master support
29 extern pstring debugf;
33 int global_nmb_port = -1;
35 extern pstring global_myname;
36 extern fstring global_myworkgroup;
37 extern char **my_netbios_names;
39 extern BOOL global_in_nmbd;
41 /* are we running as a daemon ? */
42 static BOOL is_daemon = False;
44 /* have we found LanMan clients yet? */
45 BOOL found_lm_clients = False;
47 /* what server type are we currently */
49 time_t StartupTime = 0;
51 /**************************************************************************** **
53 **************************************************************************** */
54 static void sig_term(int sig)
56 BlockSignals(True,SIGTERM);
58 DEBUG(0,("Got SIGTERM: going down...\n"));
60 /* Write out wins.dat file if samba is a WINS server */
61 wins_write_database(False);
63 /* Remove all SELF registered names. */
66 /* Announce all server entries as 0 time-to-live, 0 type. */
67 announce_my_servers_removed();
69 /* If there was an async dns child - kill it. */
70 kill_async_dns_child();
76 /**************************************************************************** **
78 **************************************************************************** */
79 static VOLATILE sig_atomic_t reload_after_sighup = False;
81 static void sig_hup(int sig)
83 BlockSignals( True, SIGHUP );
85 DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
87 write_browse_list( 0, True );
91 reload_after_sighup = True;
93 BlockSignals(False,SIGHUP);
99 /**************************************************************************** **
100 prepare to dump a core file - carefully!
101 **************************************************************************** */
102 static BOOL dump_core(void)
106 pstrcpy( dname, debugf );
107 if ((p=strrchr_m(dname,'/')))
109 pstrcat( dname, "/corefiles" );
110 mkdir( dname, 0700 );
111 sys_chown( dname, getuid(), getgid() );
112 chmod( dname, 0700 );
117 #ifdef HAVE_GETRLIMIT
121 getrlimit( RLIMIT_CORE, &rlp );
122 rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
123 setrlimit( RLIMIT_CORE, &rlp );
124 getrlimit( RLIMIT_CORE, &rlp );
125 DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
131 DEBUG(0,("Dumping core in %s\n",dname));
138 /**************************************************************************** **
139 possibly continue after a fault
140 **************************************************************************** */
141 static void fault_continue(void)
146 } /* fault_continue */
148 /**************************************************************************** **
149 expire old names from the namelist and server list
150 **************************************************************************** */
151 static void expire_names_and_servers(time_t t)
153 static time_t lastrun = 0;
157 if ( t < (lastrun + 5) )
162 * Expire any timed out names on all the broadcast
163 * subnets and those registered with the WINS server.
164 * (nmbd_namelistdb.c)
169 * Go through all the broadcast subnets and for each
170 * workgroup known on that subnet remove any expired
171 * server names. If a workgroup has an empty serverlist
172 * and has itself timed out then remove the workgroup.
173 * (nmbd_workgroupdb.c)
175 expire_workgroups_and_servers(t);
176 } /* expire_names_and_servers */
179 /************************************************************************** **
180 reload the list of network interfaces
181 ************************************************************************** */
182 static BOOL reload_interfaces(time_t t)
186 struct subnet_record *subrec;
187 extern BOOL rescan_listen_set;
188 extern struct in_addr loopback_ip;
190 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
193 if (!interfaces_changed()) return False;
195 /* the list of probed interfaces has changed, we may need to add/remove
199 /* find any interfaces that need adding */
200 for (n=iface_count() - 1; n >= 0; n--) {
201 struct interface *iface = get_interface(n);
204 * We don't want to add a loopback interface, in case
205 * someone has added 127.0.0.1 for smbd, nmbd needs to
206 * ignore it here. JRA.
209 if (ip_equal(iface->ip, loopback_ip)) {
210 DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
214 for (subrec=subnetlist; subrec; subrec=subrec->next) {
215 if (ip_equal(iface->ip, subrec->myip) &&
216 ip_equal(iface->nmask, subrec->mask_ip)) break;
220 /* it wasn't found! add it */
221 DEBUG(2,("Found new interface %s\n",
222 inet_ntoa(iface->ip)));
223 subrec = make_normal_subnet(iface);
224 if (subrec) register_my_workgroup_one_subnet(subrec);
228 /* find any interfaces that need deleting */
229 for (subrec=subnetlist; subrec; subrec=subrec->next) {
230 for (n=iface_count() - 1; n >= 0; n--) {
231 struct interface *iface = get_interface(n);
232 if (ip_equal(iface->ip, subrec->myip) &&
233 ip_equal(iface->nmask, subrec->mask_ip)) break;
236 /* oops, an interface has disapeared. This is
237 tricky, we don't dare actually free the
238 interface as it could be being used, so
239 instead we just wear the memory leak and
240 remove it from the list of interfaces without
242 DEBUG(2,("Deleting dead interface %s\n",
243 inet_ntoa(subrec->myip)));
244 close_subnet(subrec);
248 rescan_listen_set = True;
250 /* We need to shutdown if there are no subnets... */
251 if (FIRST_SUBNET == NULL) {
252 DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
260 /**************************************************************************** **
261 reload the services file
262 **************************************************************************** */
263 static BOOL reload_nmbd_services(BOOL test)
266 extern fstring remote_machine;
268 fstrcpy( remote_machine, "nmbd" );
273 pstrcpy( fname,lp_configfile());
274 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE))
276 pstrcpy(dyn_CONFIGFILE,fname);
281 if ( test && !lp_file_list_changed() )
284 ret = lp_load( dyn_CONFIGFILE, True , False, False);
286 /* perhaps the config filename is now set */
289 DEBUG( 3, ( "services not loaded\n" ) );
290 reload_nmbd_services( True );
293 /* Do a sanity check for a misconfigured nmbd */
294 if( lp_wins_support() && wins_srv_count() )
298 dbgtext( "ERROR: 'wins support = true' and 'wins server = <server>'\n" );
299 dbgtext( "are conflicting settings. nmbd aborting.\n" );
305 } /* reload_nmbd_services */
307 /**************************************************************************** **
308 The main select loop.
309 **************************************************************************** */
310 static void process(void)
316 time_t t = time(NULL);
318 /* check for internal messages */
322 * Check all broadcast subnets to see if
323 * we need to run an election on any of them.
326 run_election = check_elections();
329 * Read incoming UDP packets.
332 if(listen_for_packets(run_election))
336 * Process all incoming packets
337 * read above. This calls the success and
338 * failure functions registered when response
339 * packets arrrive, and also deals with request
340 * packets from other sources.
346 * Run any elections - initiate becoming
347 * a local master browser if we have won.
353 * Send out any broadcast announcements
354 * of our server names. This also announces
355 * the workgroup name if we are a local
357 * (nmbd_sendannounce.c)
359 announce_my_server_names(t);
362 * Send out any LanMan broadcast announcements
363 * of our server names.
364 * (nmbd_sendannounce.c)
366 announce_my_lm_server_names(t);
369 * If we are a local master browser, periodically
370 * announce ourselves to the domain master browser.
371 * This also deals with syncronising the domain master
372 * browser server lists with ourselves as a local
374 * (nmbd_sendannounce.c)
376 announce_myself_to_domain_master_browser(t);
379 * Fullfill any remote announce requests.
380 * (nmbd_sendannounce.c)
385 * Fullfill any remote browse sync announce requests.
386 * (nmbd_sendannounce.c)
388 browse_sync_remote(t);
391 * Scan the broadcast subnets, and WINS client
392 * namelists and refresh any that need refreshing.
398 * Scan the subnet namelists and server lists and
399 * expire thos that have timed out.
402 expire_names_and_servers(t);
405 * Write out a snapshot of our current browse list into
406 * the browse.dat file. This is used by smbd to service
407 * incoming NetServerEnum calls - used to synchronise
408 * browse lists over subnets.
409 * (nmbd_serverlistdb.c)
411 write_browse_list(t, False);
414 * If we are a domain master browser, we have a list of
415 * local master browsers we should synchronise browse
416 * lists with (these are added by an incoming local
417 * master browser announcement packet). Expire any of
418 * these that are no longer current, and pull the server
419 * lists from each of these known local master browsers.
420 * (nmbd_browsesync.c)
422 dmb_expire_and_sync_browser_lists(t);
425 * Check that there is a local master browser for our
426 * workgroup for all our broadcast subnets. If one
427 * is not found, start an election (which we ourselves
428 * may or may not participate in, depending on the
429 * setting of the 'local master' parameter.
432 check_master_browser_exists(t);
435 * If we are configured as a logon server, attempt to
436 * register the special NetBIOS names to become such
437 * (WORKGROUP<1c> name) on all broadcast subnets and
438 * with the WINS server (if used). If we are configured
439 * to become a domain master browser, attempt to register
440 * the special NetBIOS name (WORKGROUP<1b> name) to
442 * (nmbd_become_dmb.c)
447 * If we are a WINS server, do any timer dependent
448 * processing required.
449 * (nmbd_winsserver.c)
451 initiate_wins_processing(t);
454 * If we are a domain master browser, attempt to contact the
455 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
456 * This will only work to a Samba WINS server.
457 * (nmbd_browsesync.c)
459 if (lp_enhanced_browsing()) {
460 collect_all_workgroup_names_from_wins_server(t);
464 * Go through the response record queue and time out or re-transmit
465 * and expired entries.
468 retransmit_or_expire_response_records(t);
471 * check to see if any remote browse sync child processes have completed
473 sync_check_completion();
476 * regularly sync with any other DMBs we know about
478 if (lp_enhanced_browsing()) {
483 * clear the unexpected packet queue
488 * Reload the services file if we got a sighup.
491 if(reload_after_sighup) {
492 reload_nmbd_services( True );
494 if(reload_interfaces(0))
496 reload_after_sighup = False;
499 /* check for new network interfaces */
500 if(reload_interfaces(t))
503 /* free up temp memory */
509 /**************************************************************************** **
510 open the socket communication
511 **************************************************************************** */
512 static BOOL open_sockets(BOOL isdaemon, int port)
514 /* The sockets opened here will be used to receive broadcast
515 packets *only*. Interface specific sockets are opened in
516 make_subnet() in namedbsubnet.c. Thus we bind to the
517 address "0.0.0.0". The parameter 'socket address' is
522 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
526 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
528 if ( ClientNMB == -1 )
531 /* we are never interested in SIGPIPE */
532 BlockSignals(True,SIGPIPE);
534 set_socket_options( ClientNMB, "SO_BROADCAST" );
535 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
537 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
542 /**************************************************************************** **
543 initialise connect, service and file structs
544 **************************************************************************** */
545 static BOOL init_structs(void)
547 extern fstring local_machine;
554 if (! *global_myname)
556 fstrcpy( global_myname, myhostname() );
557 p = strchr_m( global_myname, '.' );
561 strupper( global_myname );
563 /* Add any NETBIOS name aliases. Ensure that the first entry
564 is equal to global_myname.
566 /* Work out the max number of netbios aliases that we have */
567 ptr = lp_netbios_aliases();
570 for( ; *ptr; namecount++,ptr++ )
572 if ( *global_myname )
575 /* Allocate space for the netbios aliases */
576 my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
577 if( NULL == my_netbios_names )
579 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
583 /* Use the global_myname string first */
585 if ( *global_myname )
586 my_netbios_names[namecount++] = global_myname;
588 ptr = lp_netbios_aliases();
593 nbname = strdup(*ptr);
596 DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
600 /* Look for duplicates */
602 for( n=0; n<namecount; n++ )
604 if( 0 == strcmp( nbname, my_netbios_names[n] ) )
608 my_netbios_names[namecount++] = nbname;
616 /* Terminate name list */
617 my_netbios_names[namecount++] = NULL;
619 fstrcpy( local_machine, global_myname );
620 trim_string( local_machine, " ", " " );
621 p = strchr_m( local_machine, ' ' );
624 strlower( local_machine );
626 DEBUG( 5, ("Netbios name list:-\n") );
627 for( n=0; my_netbios_names[n]; n++ )
628 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
633 /**************************************************************************** **
635 **************************************************************************** */
636 static void usage(char *pname)
639 printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
640 printf( " [-n name] [-p port] [-s configuration file]\n" );
641 printf( "\t-D Become a daemon\n" );
642 printf( "\t-a Append to log file (default)\n" );
643 printf( "\t-o Overwrite log file, don't append\n" );
644 printf( "\t-h Print usage\n" );
645 printf( "\t-V Print version\n" );
646 printf( "\t-H hosts file Load a netbios hosts file\n" );
647 printf( "\t-d debuglevel Set the debuglevel\n" );
648 printf( "\t-l log basename. Basename for log/debug files\n" );
649 printf( "\t-n netbiosname. Primary netbios name\n" );
650 printf( "\t-p port Listen on the specified port\n" );
651 printf( "\t-s configuration file Configuration file name\n" );
656 /**************************************************************************** **
658 **************************************************************************** */
659 int main(int argc,char *argv[])
663 extern BOOL append_log;
665 append_log = True; /* Default, override with '-o' option. */
667 global_nmb_port = NMB_PORT;
668 global_in_nmbd = True;
670 StartupTime = time(NULL);
672 sys_srandom(time(NULL) ^ sys_getpid());
674 slprintf(debugf, sizeof(debugf)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
675 setup_logging( argv[0], False );
677 /* this is for people who can't start the program correctly */
678 while (argc > 1 && (*argv[1] != '-'))
684 fault_setup((void (*)(void *))fault_continue );
686 /* POSIX demands that signals are inherited. If the invoking process has
687 * these signals masked, we will have problems, as we won't recieve them. */
688 BlockSignals(False, SIGHUP);
689 BlockSignals(False, SIGUSR1);
690 BlockSignals(False, SIGTERM);
692 CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
693 CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
696 /* we are never interested in SIGFPE */
697 BlockSignals(True,SIGFPE);
700 /* We no longer use USR2... */
702 BlockSignals(True, SIGUSR2);
706 (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:" )) )
711 pstrcpy(dyn_CONFIGFILE, optarg);
718 DEBUG(0,("Obsolete option '%c' used\n",opt));
721 pstrcpy(dyn_LMHOSTSFILE, optarg);
724 pstrcpy(global_myname,optarg);
725 strupper(global_myname);
728 slprintf(debugf, sizeof(debugf)-1, "%s/log.nmbd", optarg);
740 DEBUGLEVEL = atoi(optarg);
743 global_nmb_port = atoi(optarg);
750 printf( "Version %s\n", VERSION );
754 if( !is_a_socket(0) )
756 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
766 DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
767 DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
769 if ( !reload_nmbd_services(False) )
775 reload_nmbd_services( True );
777 fstrcpy( global_myworkgroup, lp_workgroup() );
779 if (strequal(global_myworkgroup,"*"))
781 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
787 if (!is_daemon && !is_a_socket(0))
789 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
795 DEBUG( 2, ( "Becoming a daemon.\n" ) );
800 /* Setup the async dns. We do it here so it doesn't have all the other
801 stuff initialised and thus chewing memory and sockets */
802 if(lp_we_are_a_wins_server()) {
807 if (!directory_exist(lp_lockdir(), NULL)) {
808 mkdir(lp_lockdir(), 0755);
811 pidfile_create("nmbd");
813 message_register(MSG_FORCE_ELECTION, nmbd_message_election);
815 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
817 if ( !open_sockets( is_daemon, global_nmb_port ) )
820 /* Determine all the IP addresses we have. */
823 /* Create an nmbd subnet record for each of the above. */
824 if( False == create_subnets() )
826 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
830 /* Load in any static local names. */
831 load_lmhosts_file(dyn_LMHOSTSFILE);
832 DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
834 /* If we are acting as a WINS server, initialise data structures. */
835 if( !initialise_wins() )
837 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
842 * Register nmbd primary workgroup and nmbd names on all
843 * the broadcast subnets, and on the WINS server (if specified).
844 * Also initiate the startup of our primary workgroup (start
845 * elections if we are setup as being able to be a local
849 if( False == register_my_workgroup_and_names() )
851 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
855 /* We can only take signals in the select. */
856 BlockSignals( True, SIGTERM );