s3: Lift the server_messaging_context from send_spoolss_notify2_msg
[Samba/gbeck.git] / source3 / nmbd / nmbd.c
blob16a4d7d81669e668a2b78574268cc131815b02bc
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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "popt_common.h"
25 #include "librpc/gen_ndr/messaging.h"
27 int ClientNMB = -1;
28 int ClientDGRAM = -1;
29 int global_nmb_port = -1;
31 extern bool rescan_listen_set;
32 extern bool global_in_nmbd;
34 extern bool override_logfile;
36 /* have we found LanMan clients yet? */
37 bool found_lm_clients = False;
39 /* what server type are we currently */
41 time_t StartupTime = 0;
43 struct event_context *nmbd_event_context(void)
45 static struct event_context *ctx;
47 if (!ctx && !(ctx = event_context_init(NULL))) {
48 smb_panic("Could not init nmbd event context");
50 return ctx;
53 struct messaging_context *nmbd_messaging_context(void)
55 static struct messaging_context *ctx;
57 if (ctx == NULL) {
58 ctx = messaging_init(NULL, procid_self(),
59 nmbd_event_context());
61 if (ctx == NULL) {
62 DEBUG(0, ("Could not init nmbd messaging context.\n"));
64 return ctx;
67 /**************************************************************************** **
68 Handle a SIGTERM in band.
69 **************************************************************************** */
71 static void terminate(void)
73 DEBUG(0,("Got SIGTERM: going down...\n"));
75 /* Write out wins.dat file if samba is a WINS server */
76 wins_write_database(0,False);
78 /* Remove all SELF registered names from WINS */
79 release_wins_names();
81 /* Announce all server entries as 0 time-to-live, 0 type. */
82 announce_my_servers_removed();
84 /* If there was an async dns child - kill it. */
85 kill_async_dns_child();
87 gencache_stabilize();
88 serverid_deregister(procid_self());
90 pidfile_unlink();
92 exit(0);
95 static void nmbd_sig_term_handler(struct tevent_context *ev,
96 struct tevent_signal *se,
97 int signum,
98 int count,
99 void *siginfo,
100 void *private_data)
102 terminate();
105 static bool nmbd_setup_sig_term_handler(void)
107 struct tevent_signal *se;
109 se = tevent_add_signal(nmbd_event_context(),
110 nmbd_event_context(),
111 SIGTERM, 0,
112 nmbd_sig_term_handler,
113 NULL);
114 if (!se) {
115 DEBUG(0,("failed to setup SIGTERM handler"));
116 return false;
119 return true;
122 static void msg_reload_nmbd_services(struct messaging_context *msg,
123 void *private_data,
124 uint32_t msg_type,
125 struct server_id server_id,
126 DATA_BLOB *data);
128 static void nmbd_sig_hup_handler(struct tevent_context *ev,
129 struct tevent_signal *se,
130 int signum,
131 int count,
132 void *siginfo,
133 void *private_data)
135 DEBUG(0,("Got SIGHUP dumping debug info.\n"));
136 msg_reload_nmbd_services(nmbd_messaging_context(),
137 NULL, MSG_SMB_CONF_UPDATED,
138 procid_self(), NULL);
141 static bool nmbd_setup_sig_hup_handler(void)
143 struct tevent_signal *se;
145 se = tevent_add_signal(nmbd_event_context(),
146 nmbd_event_context(),
147 SIGHUP, 0,
148 nmbd_sig_hup_handler,
149 NULL);
150 if (!se) {
151 DEBUG(0,("failed to setup SIGHUP handler"));
152 return false;
155 return true;
158 /**************************************************************************** **
159 Handle a SHUTDOWN message from smbcontrol.
160 **************************************************************************** */
162 static void nmbd_terminate(struct messaging_context *msg,
163 void *private_data,
164 uint32_t msg_type,
165 struct server_id server_id,
166 DATA_BLOB *data)
168 terminate();
171 /**************************************************************************** **
172 Possibly continue after a fault.
173 **************************************************************************** */
175 static void fault_continue(void)
177 dump_core();
180 /**************************************************************************** **
181 Expire old names from the namelist and server list.
182 **************************************************************************** */
184 static void expire_names_and_servers(time_t t)
186 static time_t lastrun = 0;
188 if ( !lastrun )
189 lastrun = t;
190 if ( t < (lastrun + 5) )
191 return;
192 lastrun = t;
195 * Expire any timed out names on all the broadcast
196 * subnets and those registered with the WINS server.
197 * (nmbd_namelistdb.c)
200 expire_names(t);
203 * Go through all the broadcast subnets and for each
204 * workgroup known on that subnet remove any expired
205 * server names. If a workgroup has an empty serverlist
206 * and has itself timed out then remove the workgroup.
207 * (nmbd_workgroupdb.c)
210 expire_workgroups_and_servers(t);
213 /************************************************************************** **
214 Reload the list of network interfaces.
215 Doesn't return until a network interface is up.
216 ************************************************************************** */
218 static void reload_interfaces(time_t t)
220 static time_t lastt;
221 int n;
222 bool print_waiting_msg = true;
223 struct subnet_record *subrec;
225 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
226 return;
229 lastt = t;
231 if (!interfaces_changed()) {
232 return;
235 try_again:
237 /* the list of probed interfaces has changed, we may need to add/remove
238 some subnets */
239 load_interfaces();
241 /* find any interfaces that need adding */
242 for (n=iface_count() - 1; n >= 0; n--) {
243 char str[INET6_ADDRSTRLEN];
244 const struct interface *iface = get_interface(n);
245 struct in_addr ip, nmask;
247 if (!iface) {
248 DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
249 continue;
252 /* Ensure we're only dealing with IPv4 here. */
253 if (iface->ip.ss_family != AF_INET) {
254 DEBUG(2,("reload_interfaces: "
255 "ignoring non IPv4 interface.\n"));
256 continue;
259 ip = ((struct sockaddr_in *)(void *)&iface->ip)->sin_addr;
260 nmask = ((struct sockaddr_in *)(void *)
261 &iface->netmask)->sin_addr;
264 * We don't want to add a loopback interface, in case
265 * someone has added 127.0.0.1 for smbd, nmbd needs to
266 * ignore it here. JRA.
269 if (is_loopback_addr((struct sockaddr *)(void *)&iface->ip)) {
270 DEBUG(2,("reload_interfaces: Ignoring loopback "
271 "interface %s\n",
272 print_sockaddr(str, sizeof(str), &iface->ip) ));
273 continue;
276 for (subrec=subnetlist; subrec; subrec=subrec->next) {
277 if (ip_equal_v4(ip, subrec->myip) &&
278 ip_equal_v4(nmask, subrec->mask_ip)) {
279 break;
283 if (!subrec) {
284 /* it wasn't found! add it */
285 DEBUG(2,("Found new interface %s\n",
286 print_sockaddr(str,
287 sizeof(str), &iface->ip) ));
288 subrec = make_normal_subnet(iface);
289 if (subrec)
290 register_my_workgroup_one_subnet(subrec);
294 /* find any interfaces that need deleting */
295 for (subrec=subnetlist; subrec; subrec=subrec->next) {
296 for (n=iface_count() - 1; n >= 0; n--) {
297 struct interface *iface = get_interface(n);
298 struct in_addr ip, nmask;
299 if (!iface) {
300 continue;
302 /* Ensure we're only dealing with IPv4 here. */
303 if (iface->ip.ss_family != AF_INET) {
304 DEBUG(2,("reload_interfaces: "
305 "ignoring non IPv4 interface.\n"));
306 continue;
308 ip = ((struct sockaddr_in *)(void *)
309 &iface->ip)->sin_addr;
310 nmask = ((struct sockaddr_in *)(void *)
311 &iface->netmask)->sin_addr;
312 if (ip_equal_v4(ip, subrec->myip) &&
313 ip_equal_v4(nmask, subrec->mask_ip)) {
314 break;
317 if (n == -1) {
318 /* oops, an interface has disapeared. This is
319 tricky, we don't dare actually free the
320 interface as it could be being used, so
321 instead we just wear the memory leak and
322 remove it from the list of interfaces without
323 freeing it */
324 DEBUG(2,("Deleting dead interface %s\n",
325 inet_ntoa(subrec->myip)));
326 close_subnet(subrec);
330 rescan_listen_set = True;
332 /* We need to wait if there are no subnets... */
333 if (FIRST_SUBNET == NULL) {
334 void (*saved_handler)(int);
336 if (print_waiting_msg) {
337 DEBUG(0,("reload_interfaces: "
338 "No subnets to listen to. Waiting..\n"));
339 print_waiting_msg = false;
343 * Whilst we're waiting for an interface, allow SIGTERM to
344 * cause us to exit.
346 saved_handler = CatchSignal(SIGTERM, SIG_DFL);
348 /* We only count IPv4, non-loopback interfaces here. */
349 while (iface_count_v4_nl() == 0) {
350 sleep(5);
351 load_interfaces();
354 CatchSignal(SIGTERM, saved_handler);
357 * We got an interface, go back to blocking term.
360 goto try_again;
364 /**************************************************************************** **
365 Reload the services file.
366 **************************************************************************** */
368 static bool reload_nmbd_services(bool test)
370 bool ret;
372 set_remote_machine_name("nmbd", False);
374 if ( lp_loaded() ) {
375 const char *fname = lp_configfile();
376 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
377 set_dyn_CONFIGFILE(fname);
378 test = False;
382 if ( test && !lp_file_list_changed() )
383 return(True);
385 ret = lp_load(get_dyn_CONFIGFILE(), True , False, False, True);
387 /* perhaps the config filename is now set */
388 if ( !test ) {
389 DEBUG( 3, ( "services not loaded\n" ) );
390 reload_nmbd_services( True );
393 return(ret);
396 /**************************************************************************** **
397 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
398 **************************************************************************** */
400 static void msg_reload_nmbd_services(struct messaging_context *msg,
401 void *private_data,
402 uint32_t msg_type,
403 struct server_id server_id,
404 DATA_BLOB *data)
406 write_browse_list( 0, True );
407 dump_all_namelists();
408 reload_nmbd_services( True );
409 reopen_logs();
410 reload_interfaces(0);
413 static void msg_nmbd_send_packet(struct messaging_context *msg,
414 void *private_data,
415 uint32_t msg_type,
416 struct server_id src,
417 DATA_BLOB *data)
419 struct packet_struct *p = (struct packet_struct *)data->data;
420 struct subnet_record *subrec;
421 struct sockaddr_storage ss;
422 const struct sockaddr_storage *pss;
423 const struct in_addr *local_ip;
425 DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
427 if (data->length != sizeof(struct packet_struct)) {
428 DEBUG(2, ("Discarding invalid packet length from %u\n",
429 (unsigned int)procid_to_pid(&src)));
430 return;
433 if ((p->packet_type != NMB_PACKET) &&
434 (p->packet_type != DGRAM_PACKET)) {
435 DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
436 (unsigned int)procid_to_pid(&src), p->packet_type));
437 return;
440 in_addr_to_sockaddr_storage(&ss, p->ip);
441 pss = iface_ip((struct sockaddr *)(void *)&ss);
443 if (pss == NULL) {
444 DEBUG(2, ("Could not find ip for packet from %u\n",
445 (unsigned int)procid_to_pid(&src)));
446 return;
449 local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
450 subrec = FIRST_SUBNET;
452 p->recv_fd = -1;
453 p->send_fd = (p->packet_type == NMB_PACKET) ?
454 subrec->nmb_sock : subrec->dgram_sock;
456 for (subrec = FIRST_SUBNET; subrec != NULL;
457 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
458 if (ip_equal_v4(*local_ip, subrec->myip)) {
459 p->send_fd = (p->packet_type == NMB_PACKET) ?
460 subrec->nmb_sock : subrec->dgram_sock;
461 break;
465 if (p->packet_type == DGRAM_PACKET) {
466 p->port = 138;
467 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
468 p->packet.dgram.header.source_port = 138;
471 send_packet(p);
474 /**************************************************************************** **
475 The main select loop.
476 **************************************************************************** */
478 static void process(void)
480 bool run_election;
482 while( True ) {
483 time_t t = time(NULL);
484 TALLOC_CTX *frame = talloc_stackframe();
487 * Check all broadcast subnets to see if
488 * we need to run an election on any of them.
489 * (nmbd_elections.c)
492 run_election = check_elections();
495 * Read incoming UDP packets.
496 * (nmbd_packets.c)
499 if(listen_for_packets(run_election)) {
500 TALLOC_FREE(frame);
501 return;
505 * Process all incoming packets
506 * read above. This calls the success and
507 * failure functions registered when response
508 * packets arrrive, and also deals with request
509 * packets from other sources.
510 * (nmbd_packets.c)
513 run_packet_queue();
516 * Run any elections - initiate becoming
517 * a local master browser if we have won.
518 * (nmbd_elections.c)
521 run_elections(t);
524 * Send out any broadcast announcements
525 * of our server names. This also announces
526 * the workgroup name if we are a local
527 * master browser.
528 * (nmbd_sendannounce.c)
531 announce_my_server_names(t);
534 * Send out any LanMan broadcast announcements
535 * of our server names.
536 * (nmbd_sendannounce.c)
539 announce_my_lm_server_names(t);
542 * If we are a local master browser, periodically
543 * announce ourselves to the domain master browser.
544 * This also deals with syncronising the domain master
545 * browser server lists with ourselves as a local
546 * master browser.
547 * (nmbd_sendannounce.c)
550 announce_myself_to_domain_master_browser(t);
553 * Fullfill any remote announce requests.
554 * (nmbd_sendannounce.c)
557 announce_remote(t);
560 * Fullfill any remote browse sync announce requests.
561 * (nmbd_sendannounce.c)
564 browse_sync_remote(t);
567 * Scan the broadcast subnets, and WINS client
568 * namelists and refresh any that need refreshing.
569 * (nmbd_mynames.c)
572 refresh_my_names(t);
575 * Scan the subnet namelists and server lists and
576 * expire thos that have timed out.
577 * (nmbd.c)
580 expire_names_and_servers(t);
583 * Write out a snapshot of our current browse list into
584 * the browse.dat file. This is used by smbd to service
585 * incoming NetServerEnum calls - used to synchronise
586 * browse lists over subnets.
587 * (nmbd_serverlistdb.c)
590 write_browse_list(t, False);
593 * If we are a domain master browser, we have a list of
594 * local master browsers we should synchronise browse
595 * lists with (these are added by an incoming local
596 * master browser announcement packet). Expire any of
597 * these that are no longer current, and pull the server
598 * lists from each of these known local master browsers.
599 * (nmbd_browsesync.c)
602 dmb_expire_and_sync_browser_lists(t);
605 * Check that there is a local master browser for our
606 * workgroup for all our broadcast subnets. If one
607 * is not found, start an election (which we ourselves
608 * may or may not participate in, depending on the
609 * setting of the 'local master' parameter.
610 * (nmbd_elections.c)
613 check_master_browser_exists(t);
616 * If we are configured as a logon server, attempt to
617 * register the special NetBIOS names to become such
618 * (WORKGROUP<1c> name) on all broadcast subnets and
619 * with the WINS server (if used). If we are configured
620 * to become a domain master browser, attempt to register
621 * the special NetBIOS name (WORKGROUP<1b> name) to
622 * become such.
623 * (nmbd_become_dmb.c)
626 add_domain_names(t);
629 * If we are a WINS server, do any timer dependent
630 * processing required.
631 * (nmbd_winsserver.c)
634 initiate_wins_processing(t);
637 * If we are a domain master browser, attempt to contact the
638 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
639 * This will only work to a Samba WINS server.
640 * (nmbd_browsesync.c)
643 if (lp_enhanced_browsing())
644 collect_all_workgroup_names_from_wins_server(t);
647 * Go through the response record queue and time out or re-transmit
648 * and expired entries.
649 * (nmbd_packets.c)
652 retransmit_or_expire_response_records(t);
655 * check to see if any remote browse sync child processes have completed
658 sync_check_completion();
661 * regularly sync with any other DMBs we know about
664 if (lp_enhanced_browsing())
665 sync_all_dmbs(t);
668 * clear the unexpected packet queue
671 clear_unexpected(t);
673 /* check for new network interfaces */
675 reload_interfaces(t);
677 /* free up temp memory */
678 TALLOC_FREE(frame);
682 /**************************************************************************** **
683 Open the socket communication.
684 **************************************************************************** */
686 static bool open_sockets(bool isdaemon, int port)
688 struct sockaddr_storage ss;
689 const char *sock_addr = lp_socket_address();
692 * The sockets opened here will be used to receive broadcast
693 * packets *only*. Interface specific sockets are opened in
694 * make_subnet() in namedbsubnet.c. Thus we bind to the
695 * address "0.0.0.0". The parameter 'socket address' is
696 * now deprecated.
699 if (!interpret_string_addr(&ss, sock_addr,
700 AI_NUMERICHOST|AI_PASSIVE)) {
701 DEBUG(0,("open_sockets: unable to get socket address "
702 "from string %s", sock_addr));
703 return false;
705 if (ss.ss_family != AF_INET) {
706 DEBUG(0,("open_sockets: unable to use IPv6 socket"
707 "%s in nmbd\n",
708 sock_addr));
709 return false;
712 if (isdaemon) {
713 ClientNMB = open_socket_in(SOCK_DGRAM, port,
714 0, &ss,
715 true);
716 } else {
717 ClientNMB = 0;
720 if (ClientNMB == -1) {
721 return false;
724 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
725 3, &ss,
726 true);
728 if (ClientDGRAM == -1) {
729 if (ClientNMB != 0) {
730 close(ClientNMB);
732 return false;
735 /* we are never interested in SIGPIPE */
736 BlockSignals(True,SIGPIPE);
738 set_socket_options( ClientNMB, "SO_BROADCAST" );
739 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
741 /* Ensure we're non-blocking. */
742 set_blocking( ClientNMB, False);
743 set_blocking( ClientDGRAM, False);
745 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
746 return( True );
749 /**************************************************************************** **
750 main program
751 **************************************************************************** */
753 int main(int argc, const char *argv[])
755 static bool is_daemon;
756 static bool opt_interactive;
757 static bool Fork = true;
758 static bool no_process_group;
759 static bool log_stdout;
760 poptContext pc;
761 char *p_lmhosts = NULL;
762 int opt;
763 enum {
764 OPT_DAEMON = 1000,
765 OPT_INTERACTIVE,
766 OPT_FORK,
767 OPT_NO_PROCESS_GROUP,
768 OPT_LOG_STDOUT
770 struct poptOption long_options[] = {
771 POPT_AUTOHELP
772 {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon(default)" },
773 {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)" },
774 {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools & etc)" },
775 {"no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
776 {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
777 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
778 {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
779 POPT_COMMON_SAMBA
780 { NULL }
782 TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */
783 NTSTATUS status;
785 load_case_tables();
787 global_nmb_port = NMB_PORT;
789 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
790 while ((opt = poptGetNextOpt(pc)) != -1) {
791 switch (opt) {
792 case OPT_DAEMON:
793 is_daemon = true;
794 break;
795 case OPT_INTERACTIVE:
796 opt_interactive = true;
797 break;
798 case OPT_FORK:
799 Fork = false;
800 break;
801 case OPT_NO_PROCESS_GROUP:
802 no_process_group = true;
803 break;
804 case OPT_LOG_STDOUT:
805 log_stdout = true;
806 break;
807 default:
808 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
809 poptBadOption(pc, 0), poptStrerror(opt));
810 poptPrintUsage(pc, stderr, 0);
811 exit(1);
814 poptFreeContext(pc);
816 global_in_nmbd = true;
818 StartupTime = time(NULL);
820 sys_srandom(time(NULL) ^ sys_getpid());
822 if (!override_logfile) {
823 char *lfile = NULL;
824 if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
825 exit(1);
827 lp_set_logfile(lfile);
828 SAFE_FREE(lfile);
831 fault_setup((void (*)(void *))fault_continue );
832 dump_core_setup("nmbd");
834 /* POSIX demands that signals are inherited. If the invoking process has
835 * these signals masked, we will have problems, as we won't receive them. */
836 BlockSignals(False, SIGHUP);
837 BlockSignals(False, SIGUSR1);
838 BlockSignals(False, SIGTERM);
840 #if defined(SIGFPE)
841 /* we are never interested in SIGFPE */
842 BlockSignals(True,SIGFPE);
843 #endif
845 /* We no longer use USR2... */
846 #if defined(SIGUSR2)
847 BlockSignals(True, SIGUSR2);
848 #endif
850 if ( opt_interactive ) {
851 Fork = False;
852 log_stdout = True;
855 if ( log_stdout && Fork ) {
856 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
857 exit(1);
860 setup_logging( argv[0], log_stdout );
862 reopen_logs();
864 DEBUG(0,("nmbd version %s started.\n", samba_version_string()));
865 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
867 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
868 DEBUG(0, ("error opening config file\n"));
869 exit(1);
872 if (nmbd_messaging_context() == NULL) {
873 return 1;
876 if ( !reload_nmbd_services(False) )
877 return(-1);
879 if(!init_names())
880 return -1;
882 reload_nmbd_services( True );
884 if (strequal(lp_workgroup(),"*")) {
885 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
886 exit(1);
889 set_samba_nb_type();
891 if (!is_daemon && !is_a_socket(0)) {
892 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
893 is_daemon = True;
896 if (is_daemon && !opt_interactive) {
897 DEBUG( 2, ( "Becoming a daemon.\n" ) );
898 become_daemon(Fork, no_process_group, log_stdout);
901 #if HAVE_SETPGID
903 * If we're interactive we want to set our own process group for
904 * signal management.
906 if (opt_interactive && !no_process_group)
907 setpgid( (pid_t)0, (pid_t)0 );
908 #endif
910 if (nmbd_messaging_context() == NULL) {
911 return 1;
914 #ifndef SYNC_DNS
915 /* Setup the async dns. We do it here so it doesn't have all the other
916 stuff initialised and thus chewing memory and sockets */
917 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
918 start_async_dns();
920 #endif
922 if (!directory_exist(lp_lockdir())) {
923 mkdir(lp_lockdir(), 0755);
926 pidfile_create("nmbd");
928 status = reinit_after_fork(nmbd_messaging_context(),
929 nmbd_event_context(),
930 procid_self(), false);
932 if (!NT_STATUS_IS_OK(status)) {
933 DEBUG(0,("reinit_after_fork() failed\n"));
934 exit(1);
937 if (!nmbd_setup_sig_term_handler())
938 exit(1);
939 if (!nmbd_setup_sig_hup_handler())
940 exit(1);
942 /* get broadcast messages */
944 if (!serverid_register(procid_self(),
945 FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP)) {
946 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
947 exit(1);
950 messaging_register(nmbd_messaging_context(), NULL,
951 MSG_FORCE_ELECTION, nmbd_message_election);
952 #if 0
953 /* Until winsrepl is done. */
954 messaging_register(nmbd_messaging_context(), NULL,
955 MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
956 #endif
957 messaging_register(nmbd_messaging_context(), NULL,
958 MSG_SHUTDOWN, nmbd_terminate);
959 messaging_register(nmbd_messaging_context(), NULL,
960 MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
961 messaging_register(nmbd_messaging_context(), NULL,
962 MSG_SEND_PACKET, msg_nmbd_send_packet);
964 TimeInit();
966 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
968 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
969 kill_async_dns_child();
970 return 1;
973 /* Determine all the IP addresses we have. */
974 load_interfaces();
976 /* Create an nmbd subnet record for each of the above. */
977 if( False == create_subnets() ) {
978 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
979 kill_async_dns_child();
980 exit(1);
983 /* Load in any static local names. */
984 if (p_lmhosts) {
985 set_dyn_LMHOSTSFILE(p_lmhosts);
987 load_lmhosts_file(get_dyn_LMHOSTSFILE());
988 DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));
990 /* If we are acting as a WINS server, initialise data structures. */
991 if( !initialise_wins() ) {
992 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
993 kill_async_dns_child();
994 exit(1);
998 * Register nmbd primary workgroup and nmbd names on all
999 * the broadcast subnets, and on the WINS server (if specified).
1000 * Also initiate the startup of our primary workgroup (start
1001 * elections if we are setup as being able to be a local
1002 * master browser.
1005 if( False == register_my_workgroup_and_names() ) {
1006 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
1007 kill_async_dns_child();
1008 exit(1);
1011 if (!initialize_nmbd_proxy_logon()) {
1012 DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n"));
1013 kill_async_dns_child();
1014 exit(1);
1017 TALLOC_FREE(frame);
1018 process();
1020 if (dbf)
1021 x_fclose(dbf);
1022 kill_async_dns_child();
1023 return(0);