sync 3.0 branch with head
[tprouty/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    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 pstring global_myname;
30 extern fstring global_myworkgroup;
31 extern char **my_netbios_names;
32
33 extern BOOL global_in_nmbd;
34
35 /* are we running as a daemon ? */
36 static BOOL is_daemon = False;
37
38 /* have we found LanMan clients yet? */
39 BOOL found_lm_clients = False;
40
41 /* what server type are we currently */
42
43 time_t StartupTime = 0;
44
45 /**************************************************************************** **
46  Handle a SIGTERM in band.
47  **************************************************************************** */
48
49 static void terminate(void)
50 {
51         DEBUG(0,("Got SIGTERM: going down...\n"));
52   
53         /* Write out wins.dat file if samba is a WINS server */
54         wins_write_database(False);
55   
56         /* Remove all SELF registered names from WINS */
57         release_wins_names();
58   
59         /* Announce all server entries as 0 time-to-live, 0 type. */
60         announce_my_servers_removed();
61
62         /* If there was an async dns child - kill it. */
63         kill_async_dns_child();
64
65         exit(0);
66 }
67
68 /**************************************************************************** **
69  Handle a SHUTDOWN message from smbcontrol.
70  **************************************************************************** */
71
72 static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len)
73 {
74         terminate();
75 }
76
77 /**************************************************************************** **
78  Catch a SIGTERM signal.
79  **************************************************************************** */
80
81 static SIG_ATOMIC_T got_sig_term;
82
83 static void sig_term(int sig)
84 {
85         got_sig_term = 1;
86         sys_select_signal();
87 }
88
89 /**************************************************************************** **
90  Catch a SIGHUP signal.
91  **************************************************************************** */
92
93 static SIG_ATOMIC_T reload_after_sighup;
94
95 static void sig_hup(int sig)
96 {
97         reload_after_sighup = 1;
98         sys_select_signal();
99 }
100
101 #if DUMP_CORE
102 /**************************************************************************** **
103  Prepare to dump a core file - carefully!
104  **************************************************************************** */
105
106 static BOOL dump_core(void)
107 {
108         char *p;
109         pstring dname;
110         pstrcpy( dname, lp_logfile() );
111         if ((p=strrchr_m(dname,'/')))
112                 *p=0;
113         pstrcat( dname, "/corefiles" );
114         mkdir( dname, 0700 );
115         sys_chown( dname, getuid(), getgid() );
116         chmod( dname, 0700 );
117         if ( chdir(dname) )
118                 return( False );
119         umask( ~(0700) );
120
121 #ifdef HAVE_GETRLIMIT
122 #ifdef RLIMIT_CORE
123         {
124                 struct rlimit rlp;
125                 getrlimit( RLIMIT_CORE, &rlp );
126                 rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
127                 setrlimit( RLIMIT_CORE, &rlp );
128                 getrlimit( RLIMIT_CORE, &rlp );
129                 DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
130         }
131 #endif
132 #endif
133
134
135         DEBUG(0,("Dumping core in %s\n",dname));
136         abort();
137         return( True );
138 }
139 #endif
140
141 /**************************************************************************** **
142  Possibly continue after a fault.
143  **************************************************************************** */
144
145 static void fault_continue(void)
146 {
147 #if DUMP_CORE
148         dump_core();
149 #endif
150 }
151
152 /**************************************************************************** **
153  Expire old names from the namelist and server list.
154  **************************************************************************** */
155
156 static void expire_names_and_servers(time_t t)
157 {
158         static time_t lastrun = 0;
159   
160         if ( !lastrun )
161                 lastrun = t;
162         if ( t < (lastrun + 5) )
163                 return;
164         lastrun = t;
165
166         /*
167          * Expire any timed out names on all the broadcast
168          * subnets and those registered with the WINS server.
169          * (nmbd_namelistdb.c)
170          */
171
172         expire_names(t);
173
174         /*
175          * Go through all the broadcast subnets and for each
176          * workgroup known on that subnet remove any expired
177          * server names. If a workgroup has an empty serverlist
178          * and has itself timed out then remove the workgroup.
179          * (nmbd_workgroupdb.c)
180          */
181
182         expire_workgroups_and_servers(t);
183 }
184
185 /************************************************************************** **
186  Reload the list of network interfaces.
187  ************************************************************************** */
188
189 static BOOL reload_interfaces(time_t t)
190 {
191         static time_t lastt;
192         int n;
193         struct subnet_record *subrec;
194         extern BOOL rescan_listen_set;
195         extern struct in_addr loopback_ip;
196
197         if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
198         lastt = t;
199
200         if (!interfaces_changed()) return False;
201
202         /* the list of probed interfaces has changed, we may need to add/remove
203            some subnets */
204         load_interfaces();
205
206         /* find any interfaces that need adding */
207         for (n=iface_count() - 1; n >= 0; n--) {
208                 struct interface *iface = get_interface(n);
209
210                 /*
211                  * We don't want to add a loopback interface, in case
212                  * someone has added 127.0.0.1 for smbd, nmbd needs to
213                  * ignore it here. JRA.
214                  */
215
216                 if (ip_equal(iface->ip, loopback_ip)) {
217                         DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
218                         continue;
219                 }
220
221                 for (subrec=subnetlist; subrec; subrec=subrec->next) {
222                         if (ip_equal(iface->ip, subrec->myip) &&
223                             ip_equal(iface->nmask, subrec->mask_ip)) break;
224                 }
225
226                 if (!subrec) {
227                         /* it wasn't found! add it */
228                         DEBUG(2,("Found new interface %s\n", 
229                                  inet_ntoa(iface->ip)));
230                         subrec = make_normal_subnet(iface);
231                         if (subrec) register_my_workgroup_one_subnet(subrec);
232                 }
233         }
234
235         /* find any interfaces that need deleting */
236         for (subrec=subnetlist; subrec; subrec=subrec->next) {
237                 for (n=iface_count() - 1; n >= 0; n--) {
238                         struct interface *iface = get_interface(n);
239                         if (ip_equal(iface->ip, subrec->myip) &&
240                             ip_equal(iface->nmask, subrec->mask_ip)) break;
241                 }
242                 if (n == -1) {
243                         /* oops, an interface has disapeared. This is
244                          tricky, we don't dare actually free the
245                          interface as it could be being used, so
246                          instead we just wear the memory leak and
247                          remove it from the list of interfaces without
248                          freeing it */
249                         DEBUG(2,("Deleting dead interface %s\n", 
250                                  inet_ntoa(subrec->myip)));
251                         close_subnet(subrec);
252                 }
253         }
254         
255         rescan_listen_set = True;
256
257         /* We need to shutdown if there are no subnets... */
258         if (FIRST_SUBNET == NULL) {
259                 DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
260                 return True;
261         }
262         return False;
263 }
264
265 /**************************************************************************** **
266  Reload the services file.
267  **************************************************************************** */
268
269 static BOOL reload_nmbd_services(BOOL test)
270 {
271         BOOL ret;
272
273         set_remote_machine_name("nmbd");
274
275         if ( lp_loaded() ) {
276                 pstring fname;
277                 pstrcpy( fname,lp_configfile());
278                 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
279                         pstrcpy(dyn_CONFIGFILE,fname);
280                         test = False;
281                 }
282         }
283
284         if ( test && !lp_file_list_changed() )
285                 return(True);
286
287         ret = lp_load( dyn_CONFIGFILE, True , False, False);
288
289         /* perhaps the config filename is now set */
290         if ( !test ) {
291                 DEBUG( 3, ( "services not loaded\n" ) );
292                 reload_nmbd_services( True );
293         }
294
295         return(ret);
296 }
297
298 /**************************************************************************** **
299  The main select loop.
300  **************************************************************************** */
301
302 static void process(void)
303 {
304         BOOL run_election;
305
306         while( True ) {
307                 time_t t = time(NULL);
308
309                 /* Check for internal messages */
310
311                 message_dispatch();
312
313                 /*
314                  * Check all broadcast subnets to see if
315                  * we need to run an election on any of them.
316                  * (nmbd_elections.c)
317                  */
318
319                 run_election = check_elections();
320
321                 /*
322                  * Read incoming UDP packets.
323                  * (nmbd_packets.c)
324                  */
325
326                 if(listen_for_packets(run_election))
327                         return;
328
329                 /*
330                  * Handle termination inband.
331                  */
332
333                 if (got_sig_term) {
334                         got_sig_term = 0;
335                         terminate();
336                 }
337
338                 /*
339                  * Process all incoming packets
340                  * read above. This calls the success and
341                  * failure functions registered when response
342                  * packets arrrive, and also deals with request
343                  * packets from other sources.
344                  * (nmbd_packets.c)
345                  */
346
347                 run_packet_queue();
348
349                 /*
350                  * Run any elections - initiate becoming
351                  * a local master browser if we have won.
352                  * (nmbd_elections.c)
353                  */
354
355                 run_elections(t);
356
357                 /*
358                  * Send out any broadcast announcements
359                  * of our server names. This also announces
360                  * the workgroup name if we are a local
361                  * master browser.
362                  * (nmbd_sendannounce.c)
363                  */
364
365                 announce_my_server_names(t);
366
367                 /*
368                  * Send out any LanMan broadcast announcements
369                  * of our server names.
370                  * (nmbd_sendannounce.c)
371                  */
372
373                 announce_my_lm_server_names(t);
374
375                 /*
376                  * If we are a local master browser, periodically
377                  * announce ourselves to the domain master browser.
378                  * This also deals with syncronising the domain master
379                  * browser server lists with ourselves as a local
380                  * master browser.
381                  * (nmbd_sendannounce.c)
382                  */
383
384                 announce_myself_to_domain_master_browser(t);
385
386                 /*
387                  * Fullfill any remote announce requests.
388                  * (nmbd_sendannounce.c)
389                  */
390
391                 announce_remote(t);
392
393                 /*
394                  * Fullfill any remote browse sync announce requests.
395                  * (nmbd_sendannounce.c)
396                  */
397
398                 browse_sync_remote(t);
399
400                 /*
401                  * Scan the broadcast subnets, and WINS client
402                  * namelists and refresh any that need refreshing.
403                  * (nmbd_mynames.c)
404                  */
405
406                 refresh_my_names(t);
407
408                 /*
409                  * Scan the subnet namelists and server lists and
410                  * expire thos that have timed out.
411                  * (nmbd.c)
412                  */
413
414                 expire_names_and_servers(t);
415
416                 /*
417                  * Write out a snapshot of our current browse list into
418                  * the browse.dat file. This is used by smbd to service
419                  * incoming NetServerEnum calls - used to synchronise
420                  * browse lists over subnets.
421                  * (nmbd_serverlistdb.c)
422                  */
423
424                 write_browse_list(t, False);
425
426                 /*
427                  * If we are a domain master browser, we have a list of
428                  * local master browsers we should synchronise browse
429                  * lists with (these are added by an incoming local
430                  * master browser announcement packet). Expire any of
431                  * these that are no longer current, and pull the server
432                  * lists from each of these known local master browsers.
433                  * (nmbd_browsesync.c)
434                  */
435
436                 dmb_expire_and_sync_browser_lists(t);
437
438                 /*
439                  * Check that there is a local master browser for our
440                  * workgroup for all our broadcast subnets. If one
441                  * is not found, start an election (which we ourselves
442                  * may or may not participate in, depending on the
443                  * setting of the 'local master' parameter.
444                  * (nmbd_elections.c)
445                  */
446
447                 check_master_browser_exists(t);
448
449                 /*
450                  * If we are configured as a logon server, attempt to
451                  * register the special NetBIOS names to become such
452                  * (WORKGROUP<1c> name) on all broadcast subnets and
453                  * with the WINS server (if used). If we are configured
454                  * to become a domain master browser, attempt to register
455                  * the special NetBIOS name (WORKGROUP<1b> name) to
456                  * become such.
457                  * (nmbd_become_dmb.c)
458                  */
459
460                 add_domain_names(t);
461
462                 /*
463                  * If we are a WINS server, do any timer dependent
464                  * processing required.
465                  * (nmbd_winsserver.c)
466                  */
467
468                 initiate_wins_processing(t);
469
470                 /*
471                  * If we are a domain master browser, attempt to contact the
472                  * WINS server to get a list of all known WORKGROUPS/DOMAINS.
473                  * This will only work to a Samba WINS server.
474                  * (nmbd_browsesync.c)
475                  */
476
477                 if (lp_enhanced_browsing())
478                         collect_all_workgroup_names_from_wins_server(t);
479
480                 /*
481                  * Go through the response record queue and time out or re-transmit
482                  * and expired entries.
483                  * (nmbd_packets.c)
484                  */
485
486                 retransmit_or_expire_response_records(t);
487
488                 /*
489                  * check to see if any remote browse sync child processes have completed
490                  */
491
492                 sync_check_completion();
493
494                 /*
495                  * regularly sync with any other DMBs we know about 
496                  */
497
498                 if (lp_enhanced_browsing())
499                         sync_all_dmbs(t);
500
501                 /*
502                  * clear the unexpected packet queue 
503                  */
504
505                 clear_unexpected(t);
506
507                 /*
508                  * Reload the services file if we got a sighup.
509                  */
510
511                 if(reload_after_sighup) {
512                         DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
513                         write_browse_list( 0, True );
514                         dump_all_namelists();
515                         reload_nmbd_services( True );
516                         reopen_logs();
517                         if(reload_interfaces(0))
518                                 return;
519                         reload_after_sighup = 0;
520                 }
521
522                 /* check for new network interfaces */
523
524                 if(reload_interfaces(t))
525                         return;
526
527                 /* free up temp memory */
528                         lp_talloc_free();
529         }
530 }
531
532 /**************************************************************************** **
533  Open the socket communication.
534  **************************************************************************** */
535
536 static BOOL open_sockets(BOOL isdaemon, int port)
537 {
538         /*
539          * The sockets opened here will be used to receive broadcast
540          * packets *only*. Interface specific sockets are opened in
541          * make_subnet() in namedbsubnet.c. Thus we bind to the
542          * address "0.0.0.0". The parameter 'socket address' is
543          * now deprecated.
544          */
545
546         if ( isdaemon )
547                 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
548         else
549                 ClientNMB = 0;
550   
551         ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
552
553         if ( ClientNMB == -1 )
554                 return( False );
555
556         /* we are never interested in SIGPIPE */
557         BlockSignals(True,SIGPIPE);
558
559         set_socket_options( ClientNMB,   "SO_BROADCAST" );
560         set_socket_options( ClientDGRAM, "SO_BROADCAST" );
561
562         DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
563         return( True );
564 }
565
566 /**************************************************************************** **
567  Initialise connect, service and file structs.
568  **************************************************************************** */
569
570 static BOOL init_structs(void)
571 {
572   extern fstring local_machine;
573   char *p, **ptr;
574   int namecount;
575   int n;
576   int nodup;
577   char *nbname;
578
579   if (! *global_myname)
580   {
581     fstrcpy( global_myname, myhostname() );
582     p = strchr_m( global_myname, '.' );
583     if (p)
584       *p = 0;
585   }
586   strupper( global_myname );
587
588   /* Add any NETBIOS name aliases. Ensure that the first entry
589      is equal to global_myname.
590    */
591   /* Work out the max number of netbios aliases that we have */
592   ptr = lp_netbios_aliases();
593   namecount = 0;
594   if (ptr)
595     for( ; *ptr; namecount++,ptr++ )
596       ;
597   if ( *global_myname )
598     namecount++;
599
600   /* Allocate space for the netbios aliases */
601   my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
602   if( NULL == my_netbios_names )
603   {
604      DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
605      return( False );
606   }
607  
608   /* Use the global_myname string first */
609   namecount=0;
610   if ( *global_myname )
611     my_netbios_names[namecount++] = global_myname;
612   
613   ptr = lp_netbios_aliases();
614   if (ptr)
615   {
616     while ( *ptr )
617     {
618       nbname = strdup(*ptr);
619       if (nbname == NULL)
620       {
621         DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
622         return False;
623       }
624       strupper( nbname );
625       /* Look for duplicates */
626       nodup=1;
627       for( n=0; n<namecount; n++ )
628       {
629         if( 0 == strcmp( nbname, my_netbios_names[n] ) )
630           nodup=0;
631       }
632       if (nodup)
633         my_netbios_names[namecount++] = nbname;
634       else
635         SAFE_FREE(nbname);
636
637       ptr++;
638     }
639   }
640   
641   /* Terminate name list */
642   my_netbios_names[namecount++] = NULL;
643   
644   fstrcpy( local_machine, global_myname );
645   trim_string( local_machine, " ", " " );
646   p = strchr_m( local_machine, ' ' );
647   if (p)
648     *p = 0;
649   strlower( local_machine );
650
651   DEBUG( 5, ("Netbios name list:-\n") );
652   for( n=0; my_netbios_names[n]; n++ )
653     DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
654
655   return( True );
656 }
657
658 /**************************************************************************** **
659  Usage on the program.
660  **************************************************************************** */
661
662 static void usage(char *pname)
663 {
664
665   printf( "Usage: %s [-DaiohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
666   printf( "       [-n name] [-p port] [-s configuration file]\n" );
667   printf( "\t-D                    Become a daemon (default)\n" );
668   printf( "\t-a                    Append to log file (default)\n" );
669   printf( "\t-i                    Run interactive (not a daemon)\n" );
670   printf( "\t-o                    Overwrite log file, don't append\n" );
671   printf( "\t-h                    Print usage\n" );
672   printf( "\t-V                    Print version\n" );
673   printf( "\t-H hosts file         Load a netbios hosts file\n" );
674   printf( "\t-d debuglevel         Set the debuglevel\n" );
675   printf( "\t-l log basename.      Basename for log/debug files\n" );
676   printf( "\t-n netbiosname.       Primary netbios name\n" );
677   printf( "\t-p port               Listen on the specified port\n" );
678   printf( "\t-s configuration file Configuration file name\n" );
679   printf( "\n");
680 }
681
682
683 /**************************************************************************** **
684  main program
685  **************************************************************************** */
686  int main(int argc,char *argv[])
687 {
688   int opt;
689   extern char *optarg;
690   extern BOOL  append_log;
691   BOOL opt_interactive = False;
692   pstring logfile;
693
694   append_log = True;  /* Default, override with '-o' option. */
695
696   global_nmb_port = NMB_PORT;
697   global_in_nmbd = True;
698
699   StartupTime = time(NULL);
700
701   sys_srandom(time(NULL) ^ sys_getpid());
702
703   slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
704   lp_set_logfile(logfile);
705
706   /* this is for people who can't start the program correctly */
707   while (argc > 1 && (*argv[1] != '-'))
708   {
709     argv++;
710     argc--;
711   }
712
713   fault_setup((void (*)(void *))fault_continue );
714
715   /* POSIX demands that signals are inherited. If the invoking process has
716    * these signals masked, we will have problems, as we won't recieve them. */
717   BlockSignals(False, SIGHUP);
718   BlockSignals(False, SIGUSR1);
719   BlockSignals(False, SIGTERM);
720
721   CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
722   CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
723
724 #if defined(SIGFPE)
725   /* we are never interested in SIGFPE */
726   BlockSignals(True,SIGFPE);
727 #endif
728
729   /* We no longer use USR2... */
730 #if defined(SIGUSR2)
731   BlockSignals(True, SIGUSR2);
732 #endif
733
734   while( EOF != 
735          (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:i" )) )
736     {
737       switch (opt)
738         {
739         case 's':
740           pstrcpy(dyn_CONFIGFILE, optarg);
741           break;          
742         case 'N':
743         case 'B':
744         case 'I':
745         case 'C':
746         case 'G':
747           DEBUG(0,("Obsolete option '%c' used\n",opt));
748           break;
749         case 'i':
750           opt_interactive = True;
751           break;
752         case 'H':
753           pstrcpy(dyn_LMHOSTSFILE, optarg);
754           break;
755         case 'n':
756           pstrcpy(global_myname,optarg);
757           strupper(global_myname);
758           break;
759         case 'l':
760           slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", optarg);
761           lp_set_logfile(logfile);
762           break;
763         case 'a':
764           append_log = True;
765           break;
766         case 'o':
767           append_log = False;
768           break;
769         case 'D':
770           is_daemon = True;
771           break;
772         case 'd':
773           DEBUGLEVEL = atoi(optarg);
774           break;
775         case 'p':
776           global_nmb_port = atoi(optarg);
777           break;
778         case 'h':
779           usage(argv[0]);
780           exit(0);
781           break;
782         case 'V':
783           printf( "Version %s\n", VERSION );
784           exit(0);
785           break;
786         default:
787           if( !is_a_socket(0) )
788           {
789             DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
790             usage(argv[0]);
791             exit(0);
792           }
793           break;
794         }
795     }
796
797   setup_logging( argv[0], opt_interactive );
798
799   reopen_logs();
800
801   DEBUG( 0, ( "Netbios nameserver version %s started.\n", VERSION ) );
802   DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2002\n" ) );
803
804   if ( !reload_nmbd_services(False) )
805     return(-1);
806
807   if(!init_structs())
808     return -1;
809
810   reload_nmbd_services( True );
811
812   fstrcpy( global_myworkgroup, lp_workgroup() );
813
814   if (strequal(global_myworkgroup,"*"))
815   {
816     DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
817     exit(1);
818   }
819
820   set_samba_nb_type();
821
822   if (!is_daemon && !is_a_socket(0))
823   {
824     DEBUG(0,("standard input is not a socket, assuming -D option\n"));
825     is_daemon = True;
826   }
827   
828   if (is_daemon && !opt_interactive)
829   {
830     DEBUG( 2, ( "Becoming a daemon.\n" ) );
831     become_daemon();
832   }
833
834 #if HAVE_SETPGID
835   /*
836    * If we're interactive we want to set our own process group for 
837    * signal management.
838    */
839   if (opt_interactive)
840     setpgid( (pid_t)0, (pid_t)0 );
841 #endif
842
843 #ifndef SYNC_DNS
844   /* Setup the async dns. We do it here so it doesn't have all the other
845      stuff initialised and thus chewing memory and sockets */
846   if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
847           start_async_dns();
848   }
849 #endif
850
851   if (!directory_exist(lp_lockdir(), NULL)) {
852           mkdir(lp_lockdir(), 0755);
853   }
854
855   pidfile_create("nmbd");
856   message_init();
857   message_register(MSG_FORCE_ELECTION, nmbd_message_election);
858   message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
859   message_register(MSG_SHUTDOWN, nmbd_terminate);
860
861   DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
862
863   if ( !open_sockets( is_daemon, global_nmb_port ) ) {
864     kill_async_dns_child();
865     return 1;
866   }
867
868   /* Determine all the IP addresses we have. */
869   load_interfaces();
870
871   /* Create an nmbd subnet record for each of the above. */
872   if( False == create_subnets() )
873   {
874     DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
875     kill_async_dns_child();
876     exit(1);
877   }
878
879   /* Load in any static local names. */ 
880   load_lmhosts_file(dyn_LMHOSTSFILE);
881   DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
882
883   /* If we are acting as a WINS server, initialise data structures. */
884   if( !initialise_wins() )
885   {
886     DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
887     kill_async_dns_child();
888     exit(1);
889   }
890
891   /* 
892    * Register nmbd primary workgroup and nmbd names on all
893    * the broadcast subnets, and on the WINS server (if specified).
894    * Also initiate the startup of our primary workgroup (start
895    * elections if we are setup as being able to be a local
896    * master browser.
897    */
898
899   if( False == register_my_workgroup_and_names() )
900   {
901     DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
902     kill_async_dns_child();
903     exit(1);
904   }
905
906   /* We can only take signals in the select. */
907   BlockSignals( True, SIGTERM );
908
909   process();
910
911   if (dbf)
912     x_fclose(dbf);
913   kill_async_dns_child();
914   return(0);
915 }