s3-net: add command rpc registry import
[Samba.git] / source3 / nmbd / nmbd.c
blob5678c8e848cf9cc37acfc6dc9a4c494acd031ae0
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"
26 #include "nmbd/nmbd.h"
28 int ClientNMB = -1;
29 int ClientDGRAM = -1;
30 int global_nmb_port = -1;
32 extern bool rescan_listen_set;
33 extern bool global_in_nmbd;
35 extern bool override_logfile;
37 /* have we found LanMan clients yet? */
38 bool found_lm_clients = False;
40 /* what server type are we currently */
42 time_t StartupTime = 0;
44 struct event_context *nmbd_event_context(void)
46 static struct event_context *ctx;
48 if (!ctx && !(ctx = event_context_init(NULL))) {
49 smb_panic("Could not init nmbd event context");
51 return ctx;
54 struct messaging_context *nmbd_messaging_context(void)
56 static struct messaging_context *ctx;
58 if (ctx == NULL) {
59 ctx = messaging_init(NULL, procid_self(),
60 nmbd_event_context());
62 if (ctx == NULL) {
63 DEBUG(0, ("Could not init nmbd messaging context.\n"));
65 return ctx;
68 /**************************************************************************** **
69 Handle a SIGTERM in band.
70 **************************************************************************** */
72 static void terminate(void)
74 DEBUG(0,("Got SIGTERM: going down...\n"));
76 /* Write out wins.dat file if samba is a WINS server */
77 wins_write_database(0,False);
79 /* Remove all SELF registered names from WINS */
80 release_wins_names();
82 /* Announce all server entries as 0 time-to-live, 0 type. */
83 announce_my_servers_removed();
85 /* If there was an async dns child - kill it. */
86 kill_async_dns_child();
88 gencache_stabilize();
89 serverid_deregister(procid_self());
91 pidfile_unlink();
93 exit(0);
96 static void nmbd_sig_term_handler(struct tevent_context *ev,
97 struct tevent_signal *se,
98 int signum,
99 int count,
100 void *siginfo,
101 void *private_data)
103 terminate();
106 static bool nmbd_setup_sig_term_handler(void)
108 struct tevent_signal *se;
110 se = tevent_add_signal(nmbd_event_context(),
111 nmbd_event_context(),
112 SIGTERM, 0,
113 nmbd_sig_term_handler,
114 NULL);
115 if (!se) {
116 DEBUG(0,("failed to setup SIGTERM handler"));
117 return false;
120 return true;
123 static void msg_reload_nmbd_services(struct messaging_context *msg,
124 void *private_data,
125 uint32_t msg_type,
126 struct server_id server_id,
127 DATA_BLOB *data);
129 static void nmbd_sig_hup_handler(struct tevent_context *ev,
130 struct tevent_signal *se,
131 int signum,
132 int count,
133 void *siginfo,
134 void *private_data)
136 DEBUG(0,("Got SIGHUP dumping debug info.\n"));
137 msg_reload_nmbd_services(nmbd_messaging_context(),
138 NULL, MSG_SMB_CONF_UPDATED,
139 procid_self(), NULL);
142 static bool nmbd_setup_sig_hup_handler(void)
144 struct tevent_signal *se;
146 se = tevent_add_signal(nmbd_event_context(),
147 nmbd_event_context(),
148 SIGHUP, 0,
149 nmbd_sig_hup_handler,
150 NULL);
151 if (!se) {
152 DEBUG(0,("failed to setup SIGHUP handler"));
153 return false;
156 return true;
159 /**************************************************************************** **
160 Handle a SHUTDOWN message from smbcontrol.
161 **************************************************************************** */
163 static void nmbd_terminate(struct messaging_context *msg,
164 void *private_data,
165 uint32_t msg_type,
166 struct server_id server_id,
167 DATA_BLOB *data)
169 terminate();
172 /**************************************************************************** **
173 Possibly continue after a fault.
174 **************************************************************************** */
176 static void fault_continue(void)
178 dump_core();
181 /**************************************************************************** **
182 Expire old names from the namelist and server list.
183 **************************************************************************** */
185 static void expire_names_and_servers(time_t t)
187 static time_t lastrun = 0;
189 if ( !lastrun )
190 lastrun = t;
191 if ( t < (lastrun + 5) )
192 return;
193 lastrun = t;
196 * Expire any timed out names on all the broadcast
197 * subnets and those registered with the WINS server.
198 * (nmbd_namelistdb.c)
201 expire_names(t);
204 * Go through all the broadcast subnets and for each
205 * workgroup known on that subnet remove any expired
206 * server names. If a workgroup has an empty serverlist
207 * and has itself timed out then remove the workgroup.
208 * (nmbd_workgroupdb.c)
211 expire_workgroups_and_servers(t);
214 /************************************************************************** **
215 Reload the list of network interfaces.
216 Doesn't return until a network interface is up.
217 ************************************************************************** */
219 static void reload_interfaces(time_t t)
221 static time_t lastt;
222 int n;
223 bool print_waiting_msg = true;
224 struct subnet_record *subrec;
226 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
227 return;
230 lastt = t;
232 if (!interfaces_changed()) {
233 return;
236 try_again:
238 /* the list of probed interfaces has changed, we may need to add/remove
239 some subnets */
240 load_interfaces();
242 /* find any interfaces that need adding */
243 for (n=iface_count() - 1; n >= 0; n--) {
244 char str[INET6_ADDRSTRLEN];
245 const struct interface *iface = get_interface(n);
246 struct in_addr ip, nmask;
248 if (!iface) {
249 DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
250 continue;
253 /* Ensure we're only dealing with IPv4 here. */
254 if (iface->ip.ss_family != AF_INET) {
255 DEBUG(2,("reload_interfaces: "
256 "ignoring non IPv4 interface.\n"));
257 continue;
260 ip = ((struct sockaddr_in *)(void *)&iface->ip)->sin_addr;
261 nmask = ((struct sockaddr_in *)(void *)
262 &iface->netmask)->sin_addr;
265 * We don't want to add a loopback interface, in case
266 * someone has added 127.0.0.1 for smbd, nmbd needs to
267 * ignore it here. JRA.
270 if (is_loopback_addr((struct sockaddr *)(void *)&iface->ip)) {
271 DEBUG(2,("reload_interfaces: Ignoring loopback "
272 "interface %s\n",
273 print_sockaddr(str, sizeof(str), &iface->ip) ));
274 continue;
277 for (subrec=subnetlist; subrec; subrec=subrec->next) {
278 if (ip_equal_v4(ip, subrec->myip) &&
279 ip_equal_v4(nmask, subrec->mask_ip)) {
280 break;
284 if (!subrec) {
285 /* it wasn't found! add it */
286 DEBUG(2,("Found new interface %s\n",
287 print_sockaddr(str,
288 sizeof(str), &iface->ip) ));
289 subrec = make_normal_subnet(iface);
290 if (subrec)
291 register_my_workgroup_one_subnet(subrec);
295 /* find any interfaces that need deleting */
296 for (subrec=subnetlist; subrec; subrec=subrec->next) {
297 for (n=iface_count() - 1; n >= 0; n--) {
298 struct interface *iface = get_interface(n);
299 struct in_addr ip, nmask;
300 if (!iface) {
301 continue;
303 /* Ensure we're only dealing with IPv4 here. */
304 if (iface->ip.ss_family != AF_INET) {
305 DEBUG(2,("reload_interfaces: "
306 "ignoring non IPv4 interface.\n"));
307 continue;
309 ip = ((struct sockaddr_in *)(void *)
310 &iface->ip)->sin_addr;
311 nmask = ((struct sockaddr_in *)(void *)
312 &iface->netmask)->sin_addr;
313 if (ip_equal_v4(ip, subrec->myip) &&
314 ip_equal_v4(nmask, subrec->mask_ip)) {
315 break;
318 if (n == -1) {
319 /* oops, an interface has disapeared. This is
320 tricky, we don't dare actually free the
321 interface as it could be being used, so
322 instead we just wear the memory leak and
323 remove it from the list of interfaces without
324 freeing it */
325 DEBUG(2,("Deleting dead interface %s\n",
326 inet_ntoa(subrec->myip)));
327 close_subnet(subrec);
331 rescan_listen_set = True;
333 /* We need to wait if there are no subnets... */
334 if (FIRST_SUBNET == NULL) {
335 void (*saved_handler)(int);
337 if (print_waiting_msg) {
338 DEBUG(0,("reload_interfaces: "
339 "No subnets to listen to. Waiting..\n"));
340 print_waiting_msg = false;
344 * Whilst we're waiting for an interface, allow SIGTERM to
345 * cause us to exit.
347 saved_handler = CatchSignal(SIGTERM, SIG_DFL);
349 /* We only count IPv4, non-loopback interfaces here. */
350 while (iface_count_v4_nl() == 0) {
351 sleep(5);
352 load_interfaces();
355 CatchSignal(SIGTERM, saved_handler);
358 * We got an interface, go back to blocking term.
361 goto try_again;
365 /**************************************************************************** **
366 Reload the services file.
367 **************************************************************************** */
369 static bool reload_nmbd_services(bool test)
371 bool ret;
373 set_remote_machine_name("nmbd", False);
375 if ( lp_loaded() ) {
376 const char *fname = lp_configfile();
377 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
378 set_dyn_CONFIGFILE(fname);
379 test = False;
383 if ( test && !lp_file_list_changed() )
384 return(True);
386 ret = lp_load(get_dyn_CONFIGFILE(), True , False, False, True);
388 /* perhaps the config filename is now set */
389 if ( !test ) {
390 DEBUG( 3, ( "services not loaded\n" ) );
391 reload_nmbd_services( True );
394 return(ret);
397 /**************************************************************************** **
398 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
399 **************************************************************************** */
401 static void msg_reload_nmbd_services(struct messaging_context *msg,
402 void *private_data,
403 uint32_t msg_type,
404 struct server_id server_id,
405 DATA_BLOB *data)
407 write_browse_list( 0, True );
408 dump_all_namelists();
409 reload_nmbd_services( True );
410 reopen_logs();
411 reload_interfaces(0);
414 static void msg_nmbd_send_packet(struct messaging_context *msg,
415 void *private_data,
416 uint32_t msg_type,
417 struct server_id src,
418 DATA_BLOB *data)
420 struct packet_struct *p = (struct packet_struct *)data->data;
421 struct subnet_record *subrec;
422 struct sockaddr_storage ss;
423 const struct sockaddr_storage *pss;
424 const struct in_addr *local_ip;
426 DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
428 if (data->length != sizeof(struct packet_struct)) {
429 DEBUG(2, ("Discarding invalid packet length from %u\n",
430 (unsigned int)procid_to_pid(&src)));
431 return;
434 if ((p->packet_type != NMB_PACKET) &&
435 (p->packet_type != DGRAM_PACKET)) {
436 DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
437 (unsigned int)procid_to_pid(&src), p->packet_type));
438 return;
441 in_addr_to_sockaddr_storage(&ss, p->ip);
442 pss = iface_ip((struct sockaddr *)(void *)&ss);
444 if (pss == NULL) {
445 DEBUG(2, ("Could not find ip for packet from %u\n",
446 (unsigned int)procid_to_pid(&src)));
447 return;
450 local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
451 subrec = FIRST_SUBNET;
453 p->recv_fd = -1;
454 p->send_fd = (p->packet_type == NMB_PACKET) ?
455 subrec->nmb_sock : subrec->dgram_sock;
457 for (subrec = FIRST_SUBNET; subrec != NULL;
458 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
459 if (ip_equal_v4(*local_ip, subrec->myip)) {
460 p->send_fd = (p->packet_type == NMB_PACKET) ?
461 subrec->nmb_sock : subrec->dgram_sock;
462 break;
466 if (p->packet_type == DGRAM_PACKET) {
467 p->port = 138;
468 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
469 p->packet.dgram.header.source_port = 138;
472 send_packet(p);
475 /**************************************************************************** **
476 The main select loop.
477 **************************************************************************** */
479 static void process(void)
481 bool run_election;
483 while( True ) {
484 time_t t = time(NULL);
485 TALLOC_CTX *frame = talloc_stackframe();
488 * Check all broadcast subnets to see if
489 * we need to run an election on any of them.
490 * (nmbd_elections.c)
493 run_election = check_elections();
496 * Read incoming UDP packets.
497 * (nmbd_packets.c)
500 if(listen_for_packets(run_election)) {
501 TALLOC_FREE(frame);
502 return;
506 * Process all incoming packets
507 * read above. This calls the success and
508 * failure functions registered when response
509 * packets arrrive, and also deals with request
510 * packets from other sources.
511 * (nmbd_packets.c)
514 run_packet_queue();
517 * Run any elections - initiate becoming
518 * a local master browser if we have won.
519 * (nmbd_elections.c)
522 run_elections(t);
525 * Send out any broadcast announcements
526 * of our server names. This also announces
527 * the workgroup name if we are a local
528 * master browser.
529 * (nmbd_sendannounce.c)
532 announce_my_server_names(t);
535 * Send out any LanMan broadcast announcements
536 * of our server names.
537 * (nmbd_sendannounce.c)
540 announce_my_lm_server_names(t);
543 * If we are a local master browser, periodically
544 * announce ourselves to the domain master browser.
545 * This also deals with syncronising the domain master
546 * browser server lists with ourselves as a local
547 * master browser.
548 * (nmbd_sendannounce.c)
551 announce_myself_to_domain_master_browser(t);
554 * Fullfill any remote announce requests.
555 * (nmbd_sendannounce.c)
558 announce_remote(t);
561 * Fullfill any remote browse sync announce requests.
562 * (nmbd_sendannounce.c)
565 browse_sync_remote(t);
568 * Scan the broadcast subnets, and WINS client
569 * namelists and refresh any that need refreshing.
570 * (nmbd_mynames.c)
573 refresh_my_names(t);
576 * Scan the subnet namelists and server lists and
577 * expire thos that have timed out.
578 * (nmbd.c)
581 expire_names_and_servers(t);
584 * Write out a snapshot of our current browse list into
585 * the browse.dat file. This is used by smbd to service
586 * incoming NetServerEnum calls - used to synchronise
587 * browse lists over subnets.
588 * (nmbd_serverlistdb.c)
591 write_browse_list(t, False);
594 * If we are a domain master browser, we have a list of
595 * local master browsers we should synchronise browse
596 * lists with (these are added by an incoming local
597 * master browser announcement packet). Expire any of
598 * these that are no longer current, and pull the server
599 * lists from each of these known local master browsers.
600 * (nmbd_browsesync.c)
603 dmb_expire_and_sync_browser_lists(t);
606 * Check that there is a local master browser for our
607 * workgroup for all our broadcast subnets. If one
608 * is not found, start an election (which we ourselves
609 * may or may not participate in, depending on the
610 * setting of the 'local master' parameter.
611 * (nmbd_elections.c)
614 check_master_browser_exists(t);
617 * If we are configured as a logon server, attempt to
618 * register the special NetBIOS names to become such
619 * (WORKGROUP<1c> name) on all broadcast subnets and
620 * with the WINS server (if used). If we are configured
621 * to become a domain master browser, attempt to register
622 * the special NetBIOS name (WORKGROUP<1b> name) to
623 * become such.
624 * (nmbd_become_dmb.c)
627 add_domain_names(t);
630 * If we are a WINS server, do any timer dependent
631 * processing required.
632 * (nmbd_winsserver.c)
635 initiate_wins_processing(t);
638 * If we are a domain master browser, attempt to contact the
639 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
640 * This will only work to a Samba WINS server.
641 * (nmbd_browsesync.c)
644 if (lp_enhanced_browsing())
645 collect_all_workgroup_names_from_wins_server(t);
648 * Go through the response record queue and time out or re-transmit
649 * and expired entries.
650 * (nmbd_packets.c)
653 retransmit_or_expire_response_records(t);
656 * check to see if any remote browse sync child processes have completed
659 sync_check_completion();
662 * regularly sync with any other DMBs we know about
665 if (lp_enhanced_browsing())
666 sync_all_dmbs(t);
669 * clear the unexpected packet queue
672 clear_unexpected(t);
674 /* check for new network interfaces */
676 reload_interfaces(t);
678 /* free up temp memory */
679 TALLOC_FREE(frame);
683 /**************************************************************************** **
684 Open the socket communication.
685 **************************************************************************** */
687 static bool open_sockets(bool isdaemon, int port)
689 struct sockaddr_storage ss;
690 const char *sock_addr = lp_socket_address();
693 * The sockets opened here will be used to receive broadcast
694 * packets *only*. Interface specific sockets are opened in
695 * make_subnet() in namedbsubnet.c. Thus we bind to the
696 * address "0.0.0.0". The parameter 'socket address' is
697 * now deprecated.
700 if (!interpret_string_addr(&ss, sock_addr,
701 AI_NUMERICHOST|AI_PASSIVE)) {
702 DEBUG(0,("open_sockets: unable to get socket address "
703 "from string %s", sock_addr));
704 return false;
706 if (ss.ss_family != AF_INET) {
707 DEBUG(0,("open_sockets: unable to use IPv6 socket"
708 "%s in nmbd\n",
709 sock_addr));
710 return false;
713 if (isdaemon) {
714 ClientNMB = open_socket_in(SOCK_DGRAM, port,
715 0, &ss,
716 true);
717 } else {
718 ClientNMB = 0;
721 if (ClientNMB == -1) {
722 return false;
725 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
726 3, &ss,
727 true);
729 if (ClientDGRAM == -1) {
730 if (ClientNMB != 0) {
731 close(ClientNMB);
733 return false;
736 /* we are never interested in SIGPIPE */
737 BlockSignals(True,SIGPIPE);
739 set_socket_options( ClientNMB, "SO_BROADCAST" );
740 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
742 /* Ensure we're non-blocking. */
743 set_blocking( ClientNMB, False);
744 set_blocking( ClientDGRAM, False);
746 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
747 return( True );
750 /**************************************************************************** **
751 main program
752 **************************************************************************** */
754 int main(int argc, const char *argv[])
756 static bool is_daemon;
757 static bool opt_interactive;
758 static bool Fork = true;
759 static bool no_process_group;
760 static bool log_stdout;
761 poptContext pc;
762 char *p_lmhosts = NULL;
763 int opt;
764 enum {
765 OPT_DAEMON = 1000,
766 OPT_INTERACTIVE,
767 OPT_FORK,
768 OPT_NO_PROCESS_GROUP,
769 OPT_LOG_STDOUT
771 struct poptOption long_options[] = {
772 POPT_AUTOHELP
773 {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon(default)" },
774 {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)" },
775 {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools & etc)" },
776 {"no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
777 {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
778 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
779 {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
780 POPT_COMMON_SAMBA
781 { NULL }
783 TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */
784 NTSTATUS status;
786 load_case_tables();
788 global_nmb_port = NMB_PORT;
790 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
791 while ((opt = poptGetNextOpt(pc)) != -1) {
792 switch (opt) {
793 case OPT_DAEMON:
794 is_daemon = true;
795 break;
796 case OPT_INTERACTIVE:
797 opt_interactive = true;
798 break;
799 case OPT_FORK:
800 Fork = false;
801 break;
802 case OPT_NO_PROCESS_GROUP:
803 no_process_group = true;
804 break;
805 case OPT_LOG_STDOUT:
806 log_stdout = true;
807 break;
808 default:
809 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
810 poptBadOption(pc, 0), poptStrerror(opt));
811 poptPrintUsage(pc, stderr, 0);
812 exit(1);
815 poptFreeContext(pc);
817 global_in_nmbd = true;
819 StartupTime = time(NULL);
821 sys_srandom(time(NULL) ^ sys_getpid());
823 if (!override_logfile) {
824 char *lfile = NULL;
825 if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
826 exit(1);
828 lp_set_logfile(lfile);
829 SAFE_FREE(lfile);
832 fault_setup((void (*)(void *))fault_continue );
833 dump_core_setup("nmbd");
835 /* POSIX demands that signals are inherited. If the invoking process has
836 * these signals masked, we will have problems, as we won't receive them. */
837 BlockSignals(False, SIGHUP);
838 BlockSignals(False, SIGUSR1);
839 BlockSignals(False, SIGTERM);
841 #if defined(SIGFPE)
842 /* we are never interested in SIGFPE */
843 BlockSignals(True,SIGFPE);
844 #endif
846 /* We no longer use USR2... */
847 #if defined(SIGUSR2)
848 BlockSignals(True, SIGUSR2);
849 #endif
851 if ( opt_interactive ) {
852 Fork = False;
853 log_stdout = True;
856 if ( log_stdout && Fork ) {
857 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
858 exit(1);
861 setup_logging( argv[0], log_stdout );
863 reopen_logs();
865 DEBUG(0,("nmbd version %s started.\n", samba_version_string()));
866 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
868 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
869 DEBUG(0, ("error opening config file\n"));
870 exit(1);
873 if (nmbd_messaging_context() == NULL) {
874 return 1;
877 if ( !reload_nmbd_services(False) )
878 return(-1);
880 if(!init_names())
881 return -1;
883 reload_nmbd_services( True );
885 if (strequal(lp_workgroup(),"*")) {
886 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
887 exit(1);
890 set_samba_nb_type();
892 if (!is_daemon && !is_a_socket(0)) {
893 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
894 is_daemon = True;
897 if (is_daemon && !opt_interactive) {
898 DEBUG( 2, ( "Becoming a daemon.\n" ) );
899 become_daemon(Fork, no_process_group, log_stdout);
902 #if HAVE_SETPGID
904 * If we're interactive we want to set our own process group for
905 * signal management.
907 if (opt_interactive && !no_process_group)
908 setpgid( (pid_t)0, (pid_t)0 );
909 #endif
911 if (nmbd_messaging_context() == NULL) {
912 return 1;
915 #ifndef SYNC_DNS
916 /* Setup the async dns. We do it here so it doesn't have all the other
917 stuff initialised and thus chewing memory and sockets */
918 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
919 start_async_dns();
921 #endif
923 if (!directory_exist(lp_lockdir())) {
924 mkdir(lp_lockdir(), 0755);
927 pidfile_create("nmbd");
929 status = reinit_after_fork(nmbd_messaging_context(),
930 nmbd_event_context(),
931 procid_self(), false);
933 if (!NT_STATUS_IS_OK(status)) {
934 DEBUG(0,("reinit_after_fork() failed\n"));
935 exit(1);
938 if (!nmbd_setup_sig_term_handler())
939 exit(1);
940 if (!nmbd_setup_sig_hup_handler())
941 exit(1);
943 /* get broadcast messages */
945 if (!serverid_register(procid_self(),
946 FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP)) {
947 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
948 exit(1);
951 messaging_register(nmbd_messaging_context(), NULL,
952 MSG_FORCE_ELECTION, nmbd_message_election);
953 #if 0
954 /* Until winsrepl is done. */
955 messaging_register(nmbd_messaging_context(), NULL,
956 MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
957 #endif
958 messaging_register(nmbd_messaging_context(), NULL,
959 MSG_SHUTDOWN, nmbd_terminate);
960 messaging_register(nmbd_messaging_context(), NULL,
961 MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
962 messaging_register(nmbd_messaging_context(), NULL,
963 MSG_SEND_PACKET, msg_nmbd_send_packet);
965 TimeInit();
967 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
969 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
970 kill_async_dns_child();
971 return 1;
974 /* Determine all the IP addresses we have. */
975 load_interfaces();
977 /* Create an nmbd subnet record for each of the above. */
978 if( False == create_subnets() ) {
979 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
980 kill_async_dns_child();
981 exit(1);
984 /* Load in any static local names. */
985 if (p_lmhosts) {
986 set_dyn_LMHOSTSFILE(p_lmhosts);
988 load_lmhosts_file(get_dyn_LMHOSTSFILE());
989 DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));
991 /* If we are acting as a WINS server, initialise data structures. */
992 if( !initialise_wins() ) {
993 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
994 kill_async_dns_child();
995 exit(1);
999 * Register nmbd primary workgroup and nmbd names on all
1000 * the broadcast subnets, and on the WINS server (if specified).
1001 * Also initiate the startup of our primary workgroup (start
1002 * elections if we are setup as being able to be a local
1003 * master browser.
1006 if( False == register_my_workgroup_and_names() ) {
1007 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
1008 kill_async_dns_child();
1009 exit(1);
1012 if (!initialize_nmbd_proxy_logon()) {
1013 DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n"));
1014 kill_async_dns_child();
1015 exit(1);
1018 TALLOC_FREE(frame);
1019 process();
1021 if (dbf)
1022 x_fclose(dbf);
1023 kill_async_dns_child();
1024 return(0);