Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / nmbd / nmbd.c
blob26495d25c13a3f6df6847f49223027ee8164adae
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 1997-2002
6 Copyright (C) Jelmer Vernooij 2002,2003 (Conversion to popt)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 int ClientNMB = -1;
27 int ClientDGRAM = -1;
28 int global_nmb_port = -1;
30 extern BOOL rescan_listen_set;
31 extern struct in_addr loopback_ip;
32 extern BOOL global_in_nmbd;
34 extern BOOL override_logfile;
36 /* are we running as a daemon ? */
37 static BOOL is_daemon;
39 /* fork or run in foreground ? */
40 static BOOL Fork = True;
42 /* log to standard output ? */
43 static BOOL log_stdout;
45 /* have we found LanMan clients yet? */
46 BOOL found_lm_clients = False;
48 /* what server type are we currently */
50 time_t StartupTime = 0;
52 /**************************************************************************** **
53 Handle a SIGTERM in band.
54 **************************************************************************** */
56 static void terminate(void)
58 DEBUG(0,("Got SIGTERM: going down...\n"));
60 /* Write out wins.dat file if samba is a WINS server */
61 wins_write_database(0,False);
63 /* Remove all SELF registered names from WINS */
64 release_wins_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();
72 exit(0);
75 /**************************************************************************** **
76 Handle a SHUTDOWN message from smbcontrol.
77 **************************************************************************** */
79 static void nmbd_terminate(int msg_type, struct process_id src,
80 void *buf, size_t len)
82 terminate();
85 /**************************************************************************** **
86 Catch a SIGTERM signal.
87 **************************************************************************** */
89 static SIG_ATOMIC_T got_sig_term;
91 static void sig_term(int sig)
93 got_sig_term = 1;
94 sys_select_signal(SIGTERM);
97 /**************************************************************************** **
98 Catch a SIGHUP signal.
99 **************************************************************************** */
101 static SIG_ATOMIC_T reload_after_sighup;
103 static void sig_hup(int sig)
105 reload_after_sighup = 1;
106 sys_select_signal(SIGHUP);
109 /**************************************************************************** **
110 Possibly continue after a fault.
111 **************************************************************************** */
113 static void fault_continue(void)
115 #if DUMP_CORE
116 dump_core();
117 #endif
120 /**************************************************************************** **
121 Expire old names from the namelist and server list.
122 **************************************************************************** */
124 static void expire_names_and_servers(time_t t)
126 static time_t lastrun = 0;
128 if ( !lastrun )
129 lastrun = t;
130 if ( t < (lastrun + 5) )
131 return;
132 lastrun = t;
135 * Expire any timed out names on all the broadcast
136 * subnets and those registered with the WINS server.
137 * (nmbd_namelistdb.c)
140 expire_names(t);
143 * Go through all the broadcast subnets and for each
144 * workgroup known on that subnet remove any expired
145 * server names. If a workgroup has an empty serverlist
146 * and has itself timed out then remove the workgroup.
147 * (nmbd_workgroupdb.c)
150 expire_workgroups_and_servers(t);
153 /************************************************************************** **
154 Reload the list of network interfaces.
155 ************************************************************************** */
157 static BOOL reload_interfaces(time_t t)
159 static time_t lastt;
160 int n;
161 struct subnet_record *subrec;
163 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
164 lastt = t;
166 if (!interfaces_changed()) return False;
168 /* the list of probed interfaces has changed, we may need to add/remove
169 some subnets */
170 load_interfaces();
172 /* find any interfaces that need adding */
173 for (n=iface_count() - 1; n >= 0; n--) {
174 struct interface *iface = get_interface(n);
176 if (!iface) {
177 DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
178 continue;
182 * We don't want to add a loopback interface, in case
183 * someone has added 127.0.0.1 for smbd, nmbd needs to
184 * ignore it here. JRA.
187 if (ip_equal(iface->ip, loopback_ip)) {
188 DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
189 continue;
192 for (subrec=subnetlist; subrec; subrec=subrec->next) {
193 if (ip_equal(iface->ip, subrec->myip) &&
194 ip_equal(iface->nmask, subrec->mask_ip)) break;
197 if (!subrec) {
198 /* it wasn't found! add it */
199 DEBUG(2,("Found new interface %s\n",
200 inet_ntoa(iface->ip)));
201 subrec = make_normal_subnet(iface);
202 if (subrec)
203 register_my_workgroup_one_subnet(subrec);
207 /* find any interfaces that need deleting */
208 for (subrec=subnetlist; subrec; subrec=subrec->next) {
209 for (n=iface_count() - 1; n >= 0; n--) {
210 struct interface *iface = get_interface(n);
211 if (ip_equal(iface->ip, subrec->myip) &&
212 ip_equal(iface->nmask, subrec->mask_ip)) break;
214 if (n == -1) {
215 /* oops, an interface has disapeared. This is
216 tricky, we don't dare actually free the
217 interface as it could be being used, so
218 instead we just wear the memory leak and
219 remove it from the list of interfaces without
220 freeing it */
221 DEBUG(2,("Deleting dead interface %s\n",
222 inet_ntoa(subrec->myip)));
223 close_subnet(subrec);
227 rescan_listen_set = True;
229 /* We need to shutdown if there are no subnets... */
230 if (FIRST_SUBNET == NULL) {
231 DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
232 return True;
234 return False;
237 /**************************************************************************** **
238 Reload the services file.
239 **************************************************************************** */
241 static BOOL reload_nmbd_services(BOOL test)
243 BOOL ret;
245 set_remote_machine_name("nmbd", False);
247 if ( lp_loaded() ) {
248 pstring fname;
249 pstrcpy( fname,lp_configfile());
250 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
251 pstrcpy(dyn_CONFIGFILE,fname);
252 test = False;
256 if ( test && !lp_file_list_changed() )
257 return(True);
259 ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
261 /* perhaps the config filename is now set */
262 if ( !test ) {
263 DEBUG( 3, ( "services not loaded\n" ) );
264 reload_nmbd_services( True );
267 return(ret);
270 /**************************************************************************** **
271 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
272 * We use buf here to return BOOL result to process() when reload_interfaces()
273 * detects that there are no subnets.
274 **************************************************************************** */
276 static void msg_reload_nmbd_services(int msg_type, struct process_id src,
277 void *buf, size_t len)
279 write_browse_list( 0, True );
280 dump_all_namelists();
281 reload_nmbd_services( True );
282 reopen_logs();
284 if(buf) {
285 /* We were called from process() */
286 /* If reload_interfaces() returned True */
287 /* we need to shutdown if there are no subnets... */
288 /* pass this info back to process() */
289 *((BOOL*)buf) = reload_interfaces(0);
293 static void msg_nmbd_send_packet(int msg_type, struct process_id src,
294 void *buf, size_t len)
296 struct packet_struct *p = (struct packet_struct *)buf;
297 struct subnet_record *subrec;
298 struct in_addr *local_ip;
300 DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
302 if (len != sizeof(struct packet_struct)) {
303 DEBUG(2, ("Discarding invalid packet length from %d\n",
304 procid_to_pid(&src)));
305 return;
308 if ((p->packet_type != NMB_PACKET) &&
309 (p->packet_type != DGRAM_PACKET)) {
310 DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
311 procid_to_pid(&src), p->packet_type));
312 return;
315 local_ip = iface_ip(p->ip);
317 if (local_ip == NULL) {
318 DEBUG(2, ("Could not find ip for packet from %d\n",
319 procid_to_pid(&src)));
320 return;
323 subrec = FIRST_SUBNET;
325 p->fd = (p->packet_type == NMB_PACKET) ?
326 subrec->nmb_sock : subrec->dgram_sock;
328 for (subrec = FIRST_SUBNET; subrec != NULL;
329 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
330 if (ip_equal(*local_ip, subrec->myip)) {
331 p->fd = (p->packet_type == NMB_PACKET) ?
332 subrec->nmb_sock : subrec->dgram_sock;
333 break;
337 if (p->packet_type == DGRAM_PACKET) {
338 p->port = 138;
339 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
340 p->packet.dgram.header.source_port = 138;
343 send_packet(p);
346 /**************************************************************************** **
347 The main select loop.
348 **************************************************************************** */
350 static void process(void)
352 BOOL run_election;
353 BOOL no_subnets;
355 while( True ) {
356 time_t t = time(NULL);
358 /* Check for internal messages */
360 message_dispatch();
363 * Check all broadcast subnets to see if
364 * we need to run an election on any of them.
365 * (nmbd_elections.c)
368 run_election = check_elections();
371 * Read incoming UDP packets.
372 * (nmbd_packets.c)
375 if(listen_for_packets(run_election))
376 return;
379 * Handle termination inband.
382 if (got_sig_term) {
383 got_sig_term = 0;
384 terminate();
388 * Process all incoming packets
389 * read above. This calls the success and
390 * failure functions registered when response
391 * packets arrrive, and also deals with request
392 * packets from other sources.
393 * (nmbd_packets.c)
396 run_packet_queue();
399 * Run any elections - initiate becoming
400 * a local master browser if we have won.
401 * (nmbd_elections.c)
404 run_elections(t);
407 * Send out any broadcast announcements
408 * of our server names. This also announces
409 * the workgroup name if we are a local
410 * master browser.
411 * (nmbd_sendannounce.c)
414 announce_my_server_names(t);
417 * Send out any LanMan broadcast announcements
418 * of our server names.
419 * (nmbd_sendannounce.c)
422 announce_my_lm_server_names(t);
425 * If we are a local master browser, periodically
426 * announce ourselves to the domain master browser.
427 * This also deals with syncronising the domain master
428 * browser server lists with ourselves as a local
429 * master browser.
430 * (nmbd_sendannounce.c)
433 announce_myself_to_domain_master_browser(t);
436 * Fullfill any remote announce requests.
437 * (nmbd_sendannounce.c)
440 announce_remote(t);
443 * Fullfill any remote browse sync announce requests.
444 * (nmbd_sendannounce.c)
447 browse_sync_remote(t);
450 * Scan the broadcast subnets, and WINS client
451 * namelists and refresh any that need refreshing.
452 * (nmbd_mynames.c)
455 refresh_my_names(t);
458 * Scan the subnet namelists and server lists and
459 * expire thos that have timed out.
460 * (nmbd.c)
463 expire_names_and_servers(t);
466 * Write out a snapshot of our current browse list into
467 * the browse.dat file. This is used by smbd to service
468 * incoming NetServerEnum calls - used to synchronise
469 * browse lists over subnets.
470 * (nmbd_serverlistdb.c)
473 write_browse_list(t, False);
476 * If we are a domain master browser, we have a list of
477 * local master browsers we should synchronise browse
478 * lists with (these are added by an incoming local
479 * master browser announcement packet). Expire any of
480 * these that are no longer current, and pull the server
481 * lists from each of these known local master browsers.
482 * (nmbd_browsesync.c)
485 dmb_expire_and_sync_browser_lists(t);
488 * Check that there is a local master browser for our
489 * workgroup for all our broadcast subnets. If one
490 * is not found, start an election (which we ourselves
491 * may or may not participate in, depending on the
492 * setting of the 'local master' parameter.
493 * (nmbd_elections.c)
496 check_master_browser_exists(t);
499 * If we are configured as a logon server, attempt to
500 * register the special NetBIOS names to become such
501 * (WORKGROUP<1c> name) on all broadcast subnets and
502 * with the WINS server (if used). If we are configured
503 * to become a domain master browser, attempt to register
504 * the special NetBIOS name (WORKGROUP<1b> name) to
505 * become such.
506 * (nmbd_become_dmb.c)
509 add_domain_names(t);
512 * If we are a WINS server, do any timer dependent
513 * processing required.
514 * (nmbd_winsserver.c)
517 initiate_wins_processing(t);
520 * If we are a domain master browser, attempt to contact the
521 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
522 * This will only work to a Samba WINS server.
523 * (nmbd_browsesync.c)
526 if (lp_enhanced_browsing())
527 collect_all_workgroup_names_from_wins_server(t);
530 * Go through the response record queue and time out or re-transmit
531 * and expired entries.
532 * (nmbd_packets.c)
535 retransmit_or_expire_response_records(t);
538 * check to see if any remote browse sync child processes have completed
541 sync_check_completion();
544 * regularly sync with any other DMBs we know about
547 if (lp_enhanced_browsing())
548 sync_all_dmbs(t);
551 * clear the unexpected packet queue
554 clear_unexpected(t);
557 * Reload the services file if we got a sighup.
560 if(reload_after_sighup) {
561 DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
562 msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
563 pid_to_procid(0), (void*) &no_subnets, 0);
564 if(no_subnets)
565 return;
566 reload_after_sighup = 0;
569 /* check for new network interfaces */
571 if(reload_interfaces(t))
572 return;
574 /* free up temp memory */
575 lp_TALLOC_FREE();
579 /**************************************************************************** **
580 Open the socket communication.
581 **************************************************************************** */
583 static BOOL open_sockets(BOOL isdaemon, int port)
586 * The sockets opened here will be used to receive broadcast
587 * packets *only*. Interface specific sockets are opened in
588 * make_subnet() in namedbsubnet.c. Thus we bind to the
589 * address "0.0.0.0". The parameter 'socket address' is
590 * now deprecated.
593 if ( isdaemon )
594 ClientNMB = open_socket_in(SOCK_DGRAM, port,
595 0, interpret_addr(lp_socket_address()),
596 True);
597 else
598 ClientNMB = 0;
600 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
601 3, interpret_addr(lp_socket_address()),
602 True);
604 if ( ClientNMB == -1 )
605 return( False );
607 /* we are never interested in SIGPIPE */
608 BlockSignals(True,SIGPIPE);
610 set_socket_options( ClientNMB, "SO_BROADCAST" );
611 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
613 /* Ensure we're non-blocking. */
614 set_blocking( ClientNMB, False);
615 set_blocking( ClientDGRAM, False);
617 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
618 return( True );
621 /**************************************************************************** **
622 main program
623 **************************************************************************** */
624 int main(int argc, const char *argv[])
626 pstring logfile;
627 static BOOL opt_interactive;
628 poptContext pc;
629 static char *p_lmhosts = dyn_LMHOSTSFILE;
630 static BOOL no_process_group = False;
631 struct poptOption long_options[] = {
632 POPT_AUTOHELP
633 {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
634 {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
635 {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
636 {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
637 {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
638 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
639 {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
640 POPT_COMMON_SAMBA
641 { NULL }
644 load_case_tables();
646 global_nmb_port = NMB_PORT;
648 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
649 while (poptGetNextOpt(pc) != -1) {};
650 poptFreeContext(pc);
652 global_in_nmbd = True;
654 StartupTime = time(NULL);
656 sys_srandom(time(NULL) ^ sys_getpid());
658 if (!override_logfile) {
659 slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
660 lp_set_logfile(logfile);
663 fault_setup((void (*)(void *))fault_continue );
664 dump_core_setup("nmbd");
666 /* POSIX demands that signals are inherited. If the invoking process has
667 * these signals masked, we will have problems, as we won't receive them. */
668 BlockSignals(False, SIGHUP);
669 BlockSignals(False, SIGUSR1);
670 BlockSignals(False, SIGTERM);
672 CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
673 CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
675 #if defined(SIGFPE)
676 /* we are never interested in SIGFPE */
677 BlockSignals(True,SIGFPE);
678 #endif
680 /* We no longer use USR2... */
681 #if defined(SIGUSR2)
682 BlockSignals(True, SIGUSR2);
683 #endif
685 if ( opt_interactive ) {
686 Fork = False;
687 log_stdout = True;
690 if ( log_stdout && Fork ) {
691 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
692 exit(1);
695 setup_logging( argv[0], log_stdout );
697 reopen_logs();
699 DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
700 DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
702 if ( !reload_nmbd_services(False) )
703 return(-1);
705 if(!init_names())
706 return -1;
708 reload_nmbd_services( True );
710 if (strequal(lp_workgroup(),"*")) {
711 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
712 exit(1);
715 set_samba_nb_type();
717 if (!is_daemon && !is_a_socket(0)) {
718 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
719 is_daemon = True;
722 if (is_daemon && !opt_interactive) {
723 DEBUG( 2, ( "Becoming a daemon.\n" ) );
724 become_daemon(Fork, no_process_group);
727 #if HAVE_SETPGID
729 * If we're interactive we want to set our own process group for
730 * signal management.
732 if (opt_interactive && !no_process_group)
733 setpgid( (pid_t)0, (pid_t)0 );
734 #endif
736 #ifndef SYNC_DNS
737 /* Setup the async dns. We do it here so it doesn't have all the other
738 stuff initialised and thus chewing memory and sockets */
739 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
740 start_async_dns();
742 #endif
744 if (!directory_exist(lp_lockdir(), NULL)) {
745 mkdir(lp_lockdir(), 0755);
748 pidfile_create("nmbd");
749 message_init();
750 message_register(MSG_FORCE_ELECTION, nmbd_message_election);
751 #if 0
752 /* Until winsrepl is done. */
753 message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
754 #endif
755 message_register(MSG_SHUTDOWN, nmbd_terminate);
756 message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
757 message_register(MSG_SEND_PACKET, msg_nmbd_send_packet);
759 TimeInit();
761 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
763 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
764 kill_async_dns_child();
765 return 1;
768 /* Determine all the IP addresses we have. */
769 load_interfaces();
771 /* Create an nmbd subnet record for each of the above. */
772 if( False == create_subnets() ) {
773 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
774 kill_async_dns_child();
775 exit(1);
778 /* Load in any static local names. */
779 load_lmhosts_file(p_lmhosts);
780 DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));
782 /* If we are acting as a WINS server, initialise data structures. */
783 if( !initialise_wins() ) {
784 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
785 kill_async_dns_child();
786 exit(1);
790 * Register nmbd primary workgroup and nmbd names on all
791 * the broadcast subnets, and on the WINS server (if specified).
792 * Also initiate the startup of our primary workgroup (start
793 * elections if we are setup as being able to be a local
794 * master browser.
797 if( False == register_my_workgroup_and_names() ) {
798 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
799 kill_async_dns_child();
800 exit(1);
803 /* We can only take signals in the select. */
804 BlockSignals( True, SIGTERM );
806 process();
808 if (dbf)
809 x_fclose(dbf);
810 kill_async_dns_child();
811 return(0);