2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
30 extern int DEBUGLEVEL;
32 extern pstring debugf;
33 pstring servicesf = CONFIGFILE;
39 int global_nmb_port = -1;
41 static pstring host_file;
42 extern pstring global_myname;
43 extern fstring global_myworkgroup;
44 extern char **my_netbios_names;
46 extern BOOL global_in_nmbd;
48 /* are we running as a daemon ? */
49 static BOOL is_daemon = False;
51 /* have we found LanMan clients yet? */
52 BOOL found_lm_clients = False;
54 /* what server type are we currently */
56 time_t StartupTime = 0;
58 extern struct in_addr ipzero;
60 /**************************************************************************** **
62 **************************************************************************** */
63 static void sig_term(int sig)
65 BlockSignals(True,SIGTERM);
67 DEBUG(0,("Got SIGTERM: going down...\n"));
69 /* Write out wins.dat file if samba is a WINS server */
70 wins_write_database(False);
72 /* Remove all SELF registered names. */
75 /* Announce all server entries as 0 time-to-live, 0 type. */
76 announce_my_servers_removed();
78 /* If there was an async dns child - kill it. */
79 kill_async_dns_child();
85 /**************************************************************************** **
87 **************************************************************************** */
88 static VOLATILE SIG_ATOMIC_T reload_after_sighup = False;
90 static void sig_hup(int sig)
92 BlockSignals( True, SIGHUP );
94 DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
96 write_browse_list( 0, True );
100 reload_after_sighup = True;
102 BlockSignals(False,SIGHUP);
108 /**************************************************************************** **
109 prepare to dump a core file - carefully!
110 **************************************************************************** */
111 static BOOL dump_core(void)
115 pstrcpy( dname, debugf );
116 if ((p=strrchr(dname,'/')))
118 pstrcat( dname, "/corefiles" );
119 mkdir( dname, 0700 );
120 sys_chown( dname, getuid(), getgid() );
121 chmod( dname, 0700 );
126 #ifdef HAVE_GETRLIMIT
130 getrlimit( RLIMIT_CORE, &rlp );
131 rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
132 setrlimit( RLIMIT_CORE, &rlp );
133 getrlimit( RLIMIT_CORE, &rlp );
134 DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
140 DEBUG(0,("Dumping core in %s\n",dname));
147 /**************************************************************************** **
148 possibly continue after a fault
149 **************************************************************************** */
150 static void fault_continue(void)
155 } /* fault_continue */
157 /**************************************************************************** **
158 expire old names from the namelist and server list
159 **************************************************************************** */
160 static void expire_names_and_servers(time_t t)
162 static time_t lastrun = 0;
166 if ( t < (lastrun + 5) )
171 * Expire any timed out names on all the broadcast
172 * subnets and those registered with the WINS server.
173 * (nmbd_namelistdb.c)
178 * Go through all the broadcast subnets and for each
179 * workgroup known on that subnet remove any expired
180 * server names. If a workgroup has an empty serverlist
181 * and has itself timed out then remove the workgroup.
182 * (nmbd_workgroupdb.c)
184 expire_workgroups_and_servers(t);
185 } /* expire_names_and_servers */
188 /************************************************************************** **
189 reload the list of network interfaces
190 ************************************************************************** */
191 static void reload_interfaces(time_t t)
195 struct subnet_record *subrec;
196 extern BOOL rescan_listen_set;
198 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return;
201 if (!interfaces_changed()) return;
203 /* the list of probed interfaces has changed, we may need to add/remove
207 /* find any interfaces that need adding */
208 for (n=iface_count() - 1; n >= 0; n--) {
209 struct interface *iface = get_interface(n);
210 for (subrec=subnetlist; subrec; subrec=subrec->next) {
211 if (ip_equal(iface->ip, subrec->myip) &&
212 ip_equal(iface->nmask, subrec->mask_ip)) break;
215 /* it wasn't found! add it */
216 DEBUG(2,("Found new interface %s\n",
217 inet_ntoa(iface->ip)));
218 subrec = make_normal_subnet(iface);
219 if (subrec) register_my_workgroup_one_subnet(subrec);
223 /* find any interfaces that need deleting */
224 for (subrec=subnetlist; subrec; subrec=subrec->next) {
225 for (n=iface_count() - 1; n >= 0; n--) {
226 struct interface *iface = get_interface(n);
227 if (ip_equal(iface->ip, subrec->myip) &&
228 ip_equal(iface->nmask, subrec->mask_ip)) break;
231 /* oops, an interface has disapeared. This is
232 tricky, we don't dare actually free the
233 interface as it could be being used, so
234 instead we just wear the memory leak and
235 remove it from the list of interfaces without
237 DEBUG(2,("Deleting dead interface %s\n",
238 inet_ntoa(subrec->myip)));
239 close_subnet(subrec);
243 rescan_listen_set = True;
248 /**************************************************************************** **
249 reload the services file
250 **************************************************************************** */
251 BOOL reload_services(BOOL test)
254 extern fstring remote_machine;
256 fstrcpy( remote_machine, "nmb" );
261 pstrcpy( fname,lp_configfile());
262 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
264 pstrcpy(servicesf,fname);
269 if ( test && !lp_file_list_changed() )
272 ret = lp_load( servicesf, True , False, False);
274 /* perhaps the config filename is now set */
277 DEBUG( 3, ( "services not loaded\n" ) );
278 reload_services( True );
281 /* Do a sanity check for a misconfigured nmbd */
282 if( lp_wins_support() && *lp_wins_server() )
284 DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
285 cannot be set in the smb.conf file. nmbd aborting.\n"));
290 } /* reload_services */
292 /**************************************************************************** **
293 The main select loop.
294 **************************************************************************** */
295 static void process(void)
301 time_t t = time(NULL);
304 * Check all broadcast subnets to see if
305 * we need to run an election on any of them.
308 run_election = check_elections();
311 * Read incoming UDP packets.
314 if(listen_for_packets(run_election))
318 * Process all incoming packets
319 * read above. This calls the success and
320 * failure functions registered when response
321 * packets arrrive, and also deals with request
322 * packets from other sources.
328 * Run any elections - initiate becoming
329 * a local master browser if we have won.
335 * Send out any broadcast announcements
336 * of our server names. This also announces
337 * the workgroup name if we are a local
339 * (nmbd_sendannounce.c)
341 announce_my_server_names(t);
344 * Send out any LanMan broadcast announcements
345 * of our server names.
346 * (nmbd_sendannounce.c)
348 announce_my_lm_server_names(t);
351 * If we are a local master browser, periodically
352 * announce ourselves to the domain master browser.
353 * This also deals with syncronising the domain master
354 * browser server lists with ourselves as a local
356 * (nmbd_sendannounce.c)
358 announce_myself_to_domain_master_browser(t);
361 * Fullfill any remote announce requests.
362 * (nmbd_sendannounce.c)
367 * Fullfill any remote browse sync announce requests.
368 * (nmbd_sendannounce.c)
370 browse_sync_remote(t);
373 * Scan the broadcast subnets, and WINS client
374 * namelists and refresh any that need refreshing.
380 * Scan the subnet namelists and server lists and
381 * expire thos that have timed out.
384 expire_names_and_servers(t);
387 * Write out a snapshot of our current browse list into
388 * the browse.dat file. This is used by smbd to service
389 * incoming NetServerEnum calls - used to synchronise
390 * browse lists over subnets.
391 * (nmbd_serverlistdb.c)
393 write_browse_list(t, False);
396 * If we are a domain master browser, we have a list of
397 * local master browsers we should synchronise browse
398 * lists with (these are added by an incoming local
399 * master browser announcement packet). Expire any of
400 * these that are no longer current, and pull the server
401 * lists from each of these known local master browsers.
402 * (nmbd_browsesync.c)
404 dmb_expire_and_sync_browser_lists(t);
407 * Check that there is a local master browser for our
408 * workgroup for all our broadcast subnets. If one
409 * is not found, start an election (which we ourselves
410 * may or may not participate in, depending on the
411 * setting of the 'local master' parameter.
414 check_master_browser_exists(t);
417 * If we are configured as a logon server, attempt to
418 * register the special NetBIOS names to become such
419 * (WORKGROUP<1c> name) on all broadcast subnets and
420 * with the WINS server (if used). If we are configured
421 * to become a domain master browser, attempt to register
422 * the special NetBIOS name (WORKGROUP<1b> name) to
424 * (nmbd_become_dmb.c)
429 * If we are a WINS server, do any timer dependent
430 * processing required.
431 * (nmbd_winsserver.c)
433 initiate_wins_processing(t);
436 * If we are a domain master browser, attempt to contact the
437 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
438 * This will only work to a Samba WINS server.
439 * (nmbd_browsesync.c)
441 collect_all_workgroup_names_from_wins_server(t);
444 * Go through the response record queue and time out or re-transmit
445 * and expired entries.
448 retransmit_or_expire_response_records(t);
451 * check to see if any remote browse sync child processes have completed
453 sync_check_completion();
456 * regularly sync with any other DMBs we know about
461 * Reload the services file if we got a sighup.
464 if(reload_after_sighup) {
465 reload_services( True );
467 reload_interfaces(0);
468 reload_after_sighup = False;
471 /* check for new network interfaces */
472 reload_interfaces(t);
477 /**************************************************************************** **
478 open the socket communication
479 **************************************************************************** */
480 static BOOL open_sockets(BOOL isdaemon, int port)
482 /* The sockets opened here will be used to receive broadcast
483 packets *only*. Interface specific sockets are opened in
484 make_subnet() in namedbsubnet.c. Thus we bind to the
485 address "0.0.0.0". The parameter 'socket address' is
490 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
494 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
496 if ( ClientNMB == -1 )
499 /* we are never interested in SIGPIPE */
500 BlockSignals(True,SIGPIPE);
502 set_socket_options( ClientNMB, "SO_BROADCAST" );
503 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
505 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
510 /**************************************************************************** **
511 initialise connect, service and file structs
512 **************************************************************************** */
513 static BOOL init_structs(void)
515 extern fstring local_machine;
522 if (! *global_myname)
524 fstrcpy( global_myname, myhostname() );
525 p = strchr( global_myname, '.' );
529 strupper( global_myname );
531 /* Add any NETBIOS name aliases. Ensure that the first entry
532 is equal to global_myname.
534 /* Work out the max number of netbios aliases that we have */
535 ptr = lp_netbios_aliases();
536 for( namecount=0; next_token(&ptr,nbname,NULL, sizeof(nbname)); namecount++ )
538 if ( *global_myname )
541 /* Allocate space for the netbios aliases */
542 my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
543 if( NULL == my_netbios_names )
545 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
549 /* Use the global_myname string first */
551 if ( *global_myname )
552 my_netbios_names[namecount++] = global_myname;
554 ptr = lp_netbios_aliases();
555 while ( next_token( &ptr, nbname, NULL, sizeof(nbname) ) )
558 /* Look for duplicates */
560 for( n=0; n<namecount; n++ )
562 if( 0 == strcmp( nbname, my_netbios_names[n] ) )
566 my_netbios_names[namecount++] = strdup( nbname );
569 /* Check the strdups succeeded. */
570 for( n = 0; n < namecount; n++ )
571 if( NULL == my_netbios_names[n] )
573 DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
577 /* Terminate name list */
578 my_netbios_names[namecount++] = NULL;
580 fstrcpy( local_machine, global_myname );
581 trim_string( local_machine, " ", " " );
582 p = strchr( local_machine, ' ' );
585 strlower( local_machine );
587 DEBUG( 5, ("Netbios name list:-\n") );
588 for( n=0; my_netbios_names[n]; n++ )
589 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
594 /**************************************************************************** **
596 **************************************************************************** */
597 static void usage(char *pname)
600 printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
601 printf( " [-n name] [-p port] [-s configuration file] [-i scope]\n" );
602 printf( "\t-D Become a daemon\n" );
603 printf( "\t-a Append to log file (default)\n" );
604 printf( "\t-o Overwrite log file, don't append\n" );
605 printf( "\t-h Print usage\n" );
606 printf( "\t-V Print version\n" );
607 printf( "\t-H hosts file Load a netbios hosts file\n" );
608 printf( "\t-d debuglevel Set the debuglevel\n" );
609 printf( "\t-l log basename. Basename for log/debug files\n" );
610 printf( "\t-n netbiosname. Primary netbios name\n" );
611 printf( "\t-p port Listen on the specified port\n" );
612 printf( "\t-s configuration file Configuration file name\n" );
613 printf( "\t-i scope NetBIOS scope\n" );
618 /**************************************************************************** **
620 **************************************************************************** */
621 int main(int argc,char *argv[])
626 extern BOOL append_log;
628 append_log = True; /* Default, override with '-o' option. */
630 global_nmb_port = NMB_PORT;
632 global_in_nmbd = True;
634 StartupTime = time(NULL);
636 sys_srandom(time(NULL) ^ getpid());
640 pstrcpy( debugf, NMBLOGFILE );
642 setup_logging( argv[0], False );
644 charset_initialise();
647 pstrcpy( host_file, LMHOSTSFILE );
650 /* this is for people who can't start the program correctly */
651 while (argc > 1 && (*argv[1] != '-'))
657 fault_setup((void (*)(void *))fault_continue );
659 CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
660 CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
663 /* we are never interested in SIGFPE */
664 BlockSignals(True,SIGFPE);
667 /* Setup the signals that allow the debug log level
668 to by dynamically changed. */
670 /* If we are using the malloc debug code we can't use
671 SIGUSR1 and SIGUSR2 to do debug level changes. */
674 CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
678 CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
683 (opt = getopt( argc, argv, "Vaos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) )
688 pstrcpy(servicesf,optarg);
695 DEBUG(0,("Obsolete option '%c' used\n",opt));
698 pstrcpy(host_file,optarg);
701 pstrcpy(global_myname,optarg);
702 strupper(global_myname);
705 slprintf(debugf,sizeof(debugf)-1, "%s.nmb",optarg);
708 pstrcpy(scope,optarg);
721 DEBUGLEVEL = atoi(optarg);
724 global_nmb_port = atoi(optarg);
731 printf( "Version %s\n", VERSION );
735 if( !is_a_socket(0) )
737 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
747 DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
748 DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
750 if ( !reload_services(False) )
753 codepage_initialise(lp_client_code_page());
758 reload_services( True );
760 fstrcpy( global_myworkgroup, lp_workgroup() );
762 if (strequal(global_myworkgroup,"*"))
764 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
770 if (!is_daemon && !is_a_socket(0))
772 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
778 DEBUG( 2, ( "Becoming a daemon.\n" ) );
783 /* Setup the async dns. We do it here so it doesn't have all the other
784 stuff initialised and thus chewing memory and sockets */
785 if(lp_we_are_a_wins_server()) {
790 if (!directory_exist(lp_lockdir(), NULL)) {
791 mkdir(lp_lockdir(), 0755);
794 pidfile_create("nmbd");
796 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
798 if ( !open_sockets( is_daemon, global_nmb_port ) )
801 /* Determine all the IP addresses we have. */
804 /* Create an nmbd subnet record for each of the above. */
805 if( False == create_subnets() )
807 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
811 /* Load in any static local names. */
814 load_lmhosts_file(host_file);
815 DEBUG(3,("Loaded hosts file\n"));
818 /* If we are acting as a WINS server, initialise data structures. */
819 if( !initialise_wins() )
821 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
826 * Register nmbd primary workgroup and nmbd names on all
827 * the broadcast subnets, and on the WINS server (if specified).
828 * Also initiate the startup of our primary workgroup (start
829 * elections if we are setup as being able to be a local
833 if( False == register_my_workgroup_and_names() )
835 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
839 /* We can only take signals in the select. */
840 BlockSignals( True, SIGTERM );
842 BlockSignals( True, SIGUSR1);
845 BlockSignals( True, SIGUSR2);