b9d78a8ba9e0668b52c82dd161e3dd3efa9b2436
[samba.git] / source / nmbd / nmbd.c
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)
7    
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.
12    
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.
17    
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/>.
20    
21 */
22
23 #include "includes.h"
24
25 int ClientNMB       = -1;
26 int ClientDGRAM     = -1;
27 int global_nmb_port = -1;
28
29 extern BOOL rescan_listen_set;
30 extern struct in_addr loopback_ip;
31 extern BOOL global_in_nmbd;
32
33 extern BOOL override_logfile;
34
35 /* have we found LanMan clients yet? */
36 BOOL found_lm_clients = False;
37
38 /* what server type are we currently */
39
40 time_t StartupTime = 0;
41
42 struct event_context *nmbd_event_context(void)
43 {
44         static struct event_context *ctx;
45
46         if (!ctx && !(ctx = event_context_init(NULL))) {
47                 smb_panic("Could not init nmbd event context");
48         }
49         return ctx;
50 }
51
52 struct messaging_context *nmbd_messaging_context(void)
53 {
54         static struct messaging_context *ctx;
55
56         if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
57                                            nmbd_event_context()))) {
58                 smb_panic("Could not init nmbd messaging context");
59         }
60         return ctx;
61 }
62
63 /**************************************************************************** **
64  Handle a SIGTERM in band.
65  **************************************************************************** */
66
67 static void terminate(void)
68 {
69         DEBUG(0,("Got SIGTERM: going down...\n"));
70   
71         /* Write out wins.dat file if samba is a WINS server */
72         wins_write_database(0,False);
73   
74         /* Remove all SELF registered names from WINS */
75         release_wins_names();
76   
77         /* Announce all server entries as 0 time-to-live, 0 type. */
78         announce_my_servers_removed();
79
80         /* If there was an async dns child - kill it. */
81         kill_async_dns_child();
82
83         exit(0);
84 }
85
86 /**************************************************************************** **
87  Handle a SHUTDOWN message from smbcontrol.
88  **************************************************************************** */
89
90 static void nmbd_terminate(struct messaging_context *msg,
91                            void *private_data,
92                            uint32_t msg_type,
93                            struct server_id server_id,
94                            DATA_BLOB *data)
95 {
96         terminate();
97 }
98
99 /**************************************************************************** **
100  Catch a SIGTERM signal.
101  **************************************************************************** */
102
103 static SIG_ATOMIC_T got_sig_term;
104
105 static void sig_term(int sig)
106 {
107         got_sig_term = 1;
108         sys_select_signal(SIGTERM);
109 }
110
111 /**************************************************************************** **
112  Catch a SIGHUP signal.
113  **************************************************************************** */
114
115 static SIG_ATOMIC_T reload_after_sighup;
116
117 static void sig_hup(int sig)
118 {
119         reload_after_sighup = 1;
120         sys_select_signal(SIGHUP);
121 }
122
123 /**************************************************************************** **
124  Possibly continue after a fault.
125  **************************************************************************** */
126
127 static void fault_continue(void)
128 {
129         dump_core();
130 }
131
132 /**************************************************************************** **
133  Expire old names from the namelist and server list.
134  **************************************************************************** */
135
136 static void expire_names_and_servers(time_t t)
137 {
138         static time_t lastrun = 0;
139   
140         if ( !lastrun )
141                 lastrun = t;
142         if ( t < (lastrun + 5) )
143                 return;
144         lastrun = t;
145
146         /*
147          * Expire any timed out names on all the broadcast
148          * subnets and those registered with the WINS server.
149          * (nmbd_namelistdb.c)
150          */
151
152         expire_names(t);
153
154         /*
155          * Go through all the broadcast subnets and for each
156          * workgroup known on that subnet remove any expired
157          * server names. If a workgroup has an empty serverlist
158          * and has itself timed out then remove the workgroup.
159          * (nmbd_workgroupdb.c)
160          */
161
162         expire_workgroups_and_servers(t);
163 }
164
165 /************************************************************************** **
166  Reload the list of network interfaces.
167  ************************************************************************** */
168
169 static BOOL reload_interfaces(time_t t)
170 {
171         static time_t lastt;
172         int n;
173         struct subnet_record *subrec;
174
175         if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
176         lastt = t;
177
178         if (!interfaces_changed()) return False;
179
180         /* the list of probed interfaces has changed, we may need to add/remove
181            some subnets */
182         load_interfaces();
183
184         /* find any interfaces that need adding */
185         for (n=iface_count() - 1; n >= 0; n--) {
186                 struct interface *iface = get_interface(n);
187
188                 if (!iface) {
189                         DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
190                         continue;
191                 }
192
193                 /*
194                  * We don't want to add a loopback interface, in case
195                  * someone has added 127.0.0.1 for smbd, nmbd needs to
196                  * ignore it here. JRA.
197                  */
198
199                 if (ip_equal(iface->ip, loopback_ip)) {
200                         DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
201                         continue;
202                 }
203
204                 for (subrec=subnetlist; subrec; subrec=subrec->next) {
205                         if (ip_equal(iface->ip, subrec->myip) &&
206                             ip_equal(iface->nmask, subrec->mask_ip)) break;
207                 }
208
209                 if (!subrec) {
210                         /* it wasn't found! add it */
211                         DEBUG(2,("Found new interface %s\n", 
212                                  inet_ntoa(iface->ip)));
213                         subrec = make_normal_subnet(iface);
214                         if (subrec)
215                                 register_my_workgroup_one_subnet(subrec);
216                 }
217         }
218
219         /* find any interfaces that need deleting */
220         for (subrec=subnetlist; subrec; subrec=subrec->next) {
221                 for (n=iface_count() - 1; n >= 0; n--) {
222                         struct interface *iface = get_interface(n);
223                         if (ip_equal(iface->ip, subrec->myip) &&
224                             ip_equal(iface->nmask, subrec->mask_ip)) break;
225                 }
226                 if (n == -1) {
227                         /* oops, an interface has disapeared. This is
228                          tricky, we don't dare actually free the
229                          interface as it could be being used, so
230                          instead we just wear the memory leak and
231                          remove it from the list of interfaces without
232                          freeing it */
233                         DEBUG(2,("Deleting dead interface %s\n", 
234                                  inet_ntoa(subrec->myip)));
235                         close_subnet(subrec);
236                 }
237         }
238         
239         rescan_listen_set = True;
240
241         /* We need to shutdown if there are no subnets... */
242         if (FIRST_SUBNET == NULL) {
243                 DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
244                 return True;
245         }
246         return False;
247 }
248
249 /**************************************************************************** **
250  Reload the services file.
251  **************************************************************************** */
252
253 static BOOL reload_nmbd_services(BOOL test)
254 {
255         BOOL ret;
256
257         set_remote_machine_name("nmbd", False);
258
259         if ( lp_loaded() ) {
260                 pstring fname;
261                 pstrcpy( fname,lp_configfile());
262                 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
263                         pstrcpy(dyn_CONFIGFILE,fname);
264                         test = False;
265                 }
266         }
267
268         if ( test && !lp_file_list_changed() )
269                 return(True);
270
271         ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
272
273         /* perhaps the config filename is now set */
274         if ( !test ) {
275                 DEBUG( 3, ( "services not loaded\n" ) );
276                 reload_nmbd_services( True );
277         }
278
279         return(ret);
280 }
281
282 /**************************************************************************** **
283  * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
284  * We use buf here to return BOOL result to process() when reload_interfaces()
285  * detects that there are no subnets.
286  **************************************************************************** */
287
288 static void msg_reload_nmbd_services(struct messaging_context *msg,
289                                      void *private_data,
290                                      uint32_t msg_type,
291                                      struct server_id server_id,
292                                      DATA_BLOB *data)
293 {
294         write_browse_list( 0, True );
295         dump_all_namelists();
296         reload_nmbd_services( True );
297         reopen_logs();
298         
299         if (data->data) {
300                 /* We were called from process() */
301                 /* If reload_interfaces() returned True */
302                 /* we need to shutdown if there are no subnets... */
303                 /* pass this info back to process() */
304                 *((BOOL*)data->data) = reload_interfaces(0);  
305         }
306 }
307
308 static void msg_nmbd_send_packet(struct messaging_context *msg,
309                                  void *private_data,
310                                  uint32_t msg_type,
311                                  struct server_id src,
312                                  DATA_BLOB *data)
313 {
314         struct packet_struct *p = (struct packet_struct *)data->data;
315         struct subnet_record *subrec;
316         struct in_addr *local_ip;
317
318         DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
319
320         if (data->length != sizeof(struct packet_struct)) {
321                 DEBUG(2, ("Discarding invalid packet length from %d\n",
322                           procid_to_pid(&src)));
323                 return;
324         }
325
326         if ((p->packet_type != NMB_PACKET) &&
327             (p->packet_type != DGRAM_PACKET)) {
328                 DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
329                           procid_to_pid(&src), p->packet_type));
330                 return;
331         }
332
333         local_ip = iface_ip(p->ip);
334
335         if (local_ip == NULL) {
336                 DEBUG(2, ("Could not find ip for packet from %d\n",
337                           procid_to_pid(&src)));
338                 return;
339         }
340
341         subrec = FIRST_SUBNET;
342
343         p->fd = (p->packet_type == NMB_PACKET) ?
344                 subrec->nmb_sock : subrec->dgram_sock;
345
346         for (subrec = FIRST_SUBNET; subrec != NULL;
347              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
348                 if (ip_equal(*local_ip, subrec->myip)) {
349                         p->fd = (p->packet_type == NMB_PACKET) ?
350                                 subrec->nmb_sock : subrec->dgram_sock;
351                         break;
352                 }
353         }
354
355         if (p->packet_type == DGRAM_PACKET) {
356                 p->port = 138;
357                 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
358                 p->packet.dgram.header.source_port = 138;
359         }
360
361         send_packet(p);
362 }
363
364 /**************************************************************************** **
365  The main select loop.
366  **************************************************************************** */
367
368 static void process(void)
369 {
370         BOOL run_election;
371         BOOL no_subnets;
372
373         while( True ) {
374                 time_t t = time(NULL);
375                 TALLOC_CTX *frame = talloc_stackframe();
376
377                 /* Check for internal messages */
378
379                 message_dispatch(nmbd_messaging_context());
380
381                 /*
382                  * Check all broadcast subnets to see if
383                  * we need to run an election on any of them.
384                  * (nmbd_elections.c)
385                  */
386
387                 run_election = check_elections();
388
389                 /*
390                  * Read incoming UDP packets.
391                  * (nmbd_packets.c)
392                  */
393
394                 if(listen_for_packets(run_election)) {
395                         TALLOC_FREE(frame);
396                         return;
397                 }
398
399                 /*
400                  * Handle termination inband.
401                  */
402
403                 if (got_sig_term) {
404                         got_sig_term = 0;
405                         terminate();
406                 }
407
408                 /*
409                  * Process all incoming packets
410                  * read above. This calls the success and
411                  * failure functions registered when response
412                  * packets arrrive, and also deals with request
413                  * packets from other sources.
414                  * (nmbd_packets.c)
415                  */
416
417                 run_packet_queue();
418
419                 /*
420                  * Run any elections - initiate becoming
421                  * a local master browser if we have won.
422                  * (nmbd_elections.c)
423                  */
424
425                 run_elections(t);
426
427                 /*
428                  * Send out any broadcast announcements
429                  * of our server names. This also announces
430                  * the workgroup name if we are a local
431                  * master browser.
432                  * (nmbd_sendannounce.c)
433                  */
434
435                 announce_my_server_names(t);
436
437                 /*
438                  * Send out any LanMan broadcast announcements
439                  * of our server names.
440                  * (nmbd_sendannounce.c)
441                  */
442
443                 announce_my_lm_server_names(t);
444
445                 /*
446                  * If we are a local master browser, periodically
447                  * announce ourselves to the domain master browser.
448                  * This also deals with syncronising the domain master
449                  * browser server lists with ourselves as a local
450                  * master browser.
451                  * (nmbd_sendannounce.c)
452                  */
453
454                 announce_myself_to_domain_master_browser(t);
455
456                 /*
457                  * Fullfill any remote announce requests.
458                  * (nmbd_sendannounce.c)
459                  */
460
461                 announce_remote(t);
462
463                 /*
464                  * Fullfill any remote browse sync announce requests.
465                  * (nmbd_sendannounce.c)
466                  */
467
468                 browse_sync_remote(t);
469
470                 /*
471                  * Scan the broadcast subnets, and WINS client
472                  * namelists and refresh any that need refreshing.
473                  * (nmbd_mynames.c)
474                  */
475
476                 refresh_my_names(t);
477
478                 /*
479                  * Scan the subnet namelists and server lists and
480                  * expire thos that have timed out.
481                  * (nmbd.c)
482                  */
483
484                 expire_names_and_servers(t);
485
486                 /*
487                  * Write out a snapshot of our current browse list into
488                  * the browse.dat file. This is used by smbd to service
489                  * incoming NetServerEnum calls - used to synchronise
490                  * browse lists over subnets.
491                  * (nmbd_serverlistdb.c)
492                  */
493
494                 write_browse_list(t, False);
495
496                 /*
497                  * If we are a domain master browser, we have a list of
498                  * local master browsers we should synchronise browse
499                  * lists with (these are added by an incoming local
500                  * master browser announcement packet). Expire any of
501                  * these that are no longer current, and pull the server
502                  * lists from each of these known local master browsers.
503                  * (nmbd_browsesync.c)
504                  */
505
506                 dmb_expire_and_sync_browser_lists(t);
507
508                 /*
509                  * Check that there is a local master browser for our
510                  * workgroup for all our broadcast subnets. If one
511                  * is not found, start an election (which we ourselves
512                  * may or may not participate in, depending on the
513                  * setting of the 'local master' parameter.
514                  * (nmbd_elections.c)
515                  */
516
517                 check_master_browser_exists(t);
518
519                 /*
520                  * If we are configured as a logon server, attempt to
521                  * register the special NetBIOS names to become such
522                  * (WORKGROUP<1c> name) on all broadcast subnets and
523                  * with the WINS server (if used). If we are configured
524                  * to become a domain master browser, attempt to register
525                  * the special NetBIOS name (WORKGROUP<1b> name) to
526                  * become such.
527                  * (nmbd_become_dmb.c)
528                  */
529
530                 add_domain_names(t);
531
532                 /*
533                  * If we are a WINS server, do any timer dependent
534                  * processing required.
535                  * (nmbd_winsserver.c)
536                  */
537
538                 initiate_wins_processing(t);
539
540                 /*
541                  * If we are a domain master browser, attempt to contact the
542                  * WINS server to get a list of all known WORKGROUPS/DOMAINS.
543                  * This will only work to a Samba WINS server.
544                  * (nmbd_browsesync.c)
545                  */
546
547                 if (lp_enhanced_browsing())
548                         collect_all_workgroup_names_from_wins_server(t);
549
550                 /*
551                  * Go through the response record queue and time out or re-transmit
552                  * and expired entries.
553                  * (nmbd_packets.c)
554                  */
555
556                 retransmit_or_expire_response_records(t);
557
558                 /*
559                  * check to see if any remote browse sync child processes have completed
560                  */
561
562                 sync_check_completion();
563
564                 /*
565                  * regularly sync with any other DMBs we know about 
566                  */
567
568                 if (lp_enhanced_browsing())
569                         sync_all_dmbs(t);
570
571                 /*
572                  * clear the unexpected packet queue 
573                  */
574
575                 clear_unexpected(t);
576
577                 /*
578                  * Reload the services file if we got a sighup.
579                  */
580
581                 if(reload_after_sighup) {
582                         DATA_BLOB blob = data_blob_const(&no_subnets,
583                                                          sizeof(no_subnets));
584                         DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
585                         msg_reload_nmbd_services(nmbd_messaging_context(),
586                                                  NULL, MSG_SMB_CONF_UPDATED,
587                                                  procid_self(), &blob);
588
589                         if(no_subnets) {
590                                 TALLOC_FREE(frame);
591                                 return;
592                         }
593                         reload_after_sighup = 0;
594                 }
595
596                 /* check for new network interfaces */
597
598                 if(reload_interfaces(t)) {
599                         TALLOC_FREE(frame);
600                         return;
601                 }
602
603                 /* free up temp memory */
604                 TALLOC_FREE(frame);
605         }
606 }
607
608 /**************************************************************************** **
609  Open the socket communication.
610  **************************************************************************** */
611
612 static BOOL open_sockets(enum smb_server_mode server_mode, int port)
613 {
614         /*
615          * The sockets opened here will be used to receive broadcast
616          * packets *only*. Interface specific sockets are opened in
617          * make_subnet() in namedbsubnet.c. Thus we bind to the
618          * address "0.0.0.0". The parameter 'socket address' is
619          * now deprecated.
620          */
621
622         if ( server_mode == SERVER_MODE_INETD ) {
623                 ClientNMB = 0;
624         } else {
625                 ClientNMB = open_socket_in(SOCK_DGRAM, port,
626                                            0, interpret_addr(lp_socket_address()),
627                                            True);
628         }
629   
630         ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
631                                            3, interpret_addr(lp_socket_address()),
632                                            True);
633
634         if ( ClientNMB == -1 )
635                 return( False );
636
637         /* we are never interested in SIGPIPE */
638         BlockSignals(True,SIGPIPE);
639
640         set_socket_options( ClientNMB,   "SO_BROADCAST" );
641         set_socket_options( ClientDGRAM, "SO_BROADCAST" );
642
643         /* Ensure we're non-blocking. */
644         set_blocking( ClientNMB, False);
645         set_blocking( ClientDGRAM, False);
646
647         DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
648         return( True );
649 }
650
651 /**************************************************************************** **
652  main program
653  **************************************************************************** */
654  int main(int argc, const char *argv[])
655 {
656         pstring logfile;
657         poptContext pc;
658         const char *p_lmhosts = dyn_LMHOSTSFILE;
659         BOOL no_process_group = False;
660         BOOL log_stdout = False;
661         enum smb_server_mode server_mode = SERVER_MODE_DAEMON;
662         int opt;
663
664         struct poptOption long_options[] = {
665         POPT_AUTOHELP
666         {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON,
667                 "Become a daemon(default)" },
668         {"interactive", 'i', POPT_ARG_VAL, &server_mode,
669                 SERVER_MODE_INTERACTIVE, "Run interactive (not a daemon)" },
670         {"foreground", 'F', POPT_ARG_VAL, &server_mode,
671                 SERVER_MODE_FOREGROUND, "Run daemon in foreground (for daemontools & etc)" },
672         {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
673         {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
674         {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
675         {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
676         POPT_COMMON_SAMBA
677         { NULL }
678         };
679
680         load_case_tables();
681
682         global_nmb_port = NMB_PORT;
683
684         pc = poptGetContext("nmbd", argc, argv, long_options, 0);
685         while ((opt = poptGetNextOpt(pc)) != -1) {
686                 switch (opt) {
687                 default:
688                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
689                                   poptBadOption(pc, 0), poptStrerror(opt));
690                         poptPrintUsage(pc, stderr, 0);
691                         exit(1);
692                 }
693         };
694         poptFreeContext(pc);
695
696         global_in_nmbd = True;
697         
698         StartupTime = time(NULL);
699         
700         sys_srandom(time(NULL) ^ sys_getpid());
701         
702         if (!override_logfile) {
703                 slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
704                 lp_set_logfile(logfile);
705         }
706         
707         fault_setup((void (*)(void *))fault_continue );
708         dump_core_setup("nmbd");
709         
710         /* POSIX demands that signals are inherited. If the invoking process has
711          * these signals masked, we will have problems, as we won't receive them. */
712         BlockSignals(False, SIGHUP);
713         BlockSignals(False, SIGUSR1);
714         BlockSignals(False, SIGTERM);
715         
716         CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
717         CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
718         
719 #if defined(SIGFPE)
720         /* we are never interested in SIGFPE */
721         BlockSignals(True,SIGFPE);
722 #endif
723
724         /* We no longer use USR2... */
725 #if defined(SIGUSR2)
726         BlockSignals(True, SIGUSR2);
727 #endif
728
729         if (server_mode == SERVER_MODE_INTERACTIVE) {
730                 log_stdout = True;
731         }
732
733         if (log_stdout && server_mode == SERVER_MODE_DAEMON) {
734                 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
735                 exit(1);
736         }
737
738         setup_logging( argv[0], log_stdout );
739
740         reopen_logs();
741
742         DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
743         DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
744
745         if ( !reload_nmbd_services(False) )
746                 return(-1);
747
748         if(!init_names())
749                 return -1;
750
751         reload_nmbd_services( True );
752
753         if (strequal(lp_workgroup(),"*")) {
754                 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
755                 exit(1);
756         }
757
758         set_samba_nb_type();
759
760         if (is_a_socket(0)) {
761                 if (server_mode == SERVER_MODE_DAEMON) {
762                         DEBUG(0,("standard input is a socket, "
763                                     "assuming -F option\n"));
764                 }
765                 server_mode = SERVER_MODE_INETD;
766         }
767
768         if (server_mode == SERVER_MODE_DAEMON) {
769                 DEBUG( 2, ( "Becoming a daemon.\n" ) );
770                 become_daemon(True, no_process_group);
771         } else if (server_mode == SERVER_MODE_FOREGROUND) {
772                 become_daemon(False, no_process_group);
773         }
774
775 #if HAVE_SETPGID
776         /*
777          * If we're interactive we want to set our own process group for 
778          * signal management.
779          */
780         if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group)
781                 setpgid( (pid_t)0, (pid_t)0 );
782 #endif
783
784         if (nmbd_messaging_context() == NULL) {
785                 return 1;
786         }
787
788 #ifndef SYNC_DNS
789         /* Setup the async dns. We do it here so it doesn't have all the other
790                 stuff initialised and thus chewing memory and sockets */
791         if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
792                 start_async_dns();
793         }
794 #endif
795
796         if (!directory_exist(lp_lockdir(), NULL)) {
797                 mkdir(lp_lockdir(), 0755);
798         }
799
800         pidfile_create("nmbd");
801         messaging_register(nmbd_messaging_context(), NULL,
802                            MSG_FORCE_ELECTION, nmbd_message_election);
803 #if 0
804         /* Until winsrepl is done. */
805         messaging_register(nmbd_messaging_context(), NULL,
806                            MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
807 #endif
808         messaging_register(nmbd_messaging_context(), NULL,
809                            MSG_SHUTDOWN, nmbd_terminate);
810         messaging_register(nmbd_messaging_context(), NULL,
811                            MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
812         messaging_register(nmbd_messaging_context(), NULL,
813                            MSG_SEND_PACKET, msg_nmbd_send_packet);
814
815         TimeInit();
816
817         DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
818
819         if ( !open_sockets( server_mode, global_nmb_port ) ) {
820                 kill_async_dns_child();
821                 return 1;
822         }
823
824         /* Determine all the IP addresses we have. */
825         load_interfaces();
826
827         /* Create an nmbd subnet record for each of the above. */
828         if( False == create_subnets() ) {
829                 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
830                 kill_async_dns_child();
831                 exit(1);
832         }
833
834         /* Load in any static local names. */ 
835         load_lmhosts_file(p_lmhosts);
836         DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));
837
838         /* If we are acting as a WINS server, initialise data structures. */
839         if( !initialise_wins() ) {
840                 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
841                 kill_async_dns_child();
842                 exit(1);
843         }
844
845         /* 
846          * Register nmbd primary workgroup and nmbd names on all
847          * the broadcast subnets, and on the WINS server (if specified).
848          * Also initiate the startup of our primary workgroup (start
849          * elections if we are setup as being able to be a local
850          * master browser.
851          */
852
853         if( False == register_my_workgroup_and_names() ) {
854                 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
855                 kill_async_dns_child();
856                 exit(1);
857         }
858
859         /* We can only take signals in the select. */
860         BlockSignals( True, SIGTERM );
861
862         process();
863
864         if (dbf)
865                 x_fclose(dbf);
866         kill_async_dns_child();
867         return(0);
868 }