b59a626fff75d93e31973b8791498a12ae231843
[kai/samba.git] / source / nmbd / nmbd.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1998
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    Revision History:
22
23    14 jan 96: lkcl@pires.co.uk
24    added multiple workgroup domain master support
25
26 */
27
28 #include "includes.h"
29
30 extern int DEBUGLEVEL;
31
32 extern pstring debugf;
33 pstring servicesf = CONFIGFILE;
34
35 int ClientNMB       = -1;
36 int ClientDGRAM     = -1;
37 int global_nmb_port = -1;
38
39 static pstring host_file;
40 extern pstring global_myname;
41 extern fstring global_myworkgroup;
42 extern char **my_netbios_names;
43
44 extern BOOL global_in_nmbd;
45
46 /* are we running as a daemon ? */
47 static BOOL is_daemon = False;
48
49 /* have we found LanMan clients yet? */
50 BOOL found_lm_clients = False;
51
52 /* what server type are we currently */
53
54 time_t StartupTime = 0;
55
56 extern struct in_addr ipzero;
57
58 /**************************************************************************** **
59   catch a sigterm
60  **************************************************************************** */
61 static void sig_term(int sig)
62 {
63   BlockSignals(True,SIGTERM);
64   
65   DEBUG(0,("Got SIGTERM: going down...\n"));
66   
67   /* Write out wins.dat file if samba is a WINS server */
68   wins_write_database(False);
69   
70   /* Remove all SELF registered names. */
71   release_my_names();
72   
73   /* Announce all server entries as 0 time-to-live, 0 type. */
74   announce_my_servers_removed();
75
76   /* If there was an async dns child - kill it. */
77   kill_async_dns_child();
78
79   exit(0);
80
81 } /* sig_term */
82
83 /**************************************************************************** **
84  catch a sighup
85  **************************************************************************** */
86 static VOLATILE SIG_ATOMIC_T reload_after_sighup = False;
87
88 static void sig_hup(int sig)
89 {
90   BlockSignals( True, SIGHUP );
91
92   DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
93
94   write_browse_list( 0, True );
95
96   dump_all_namelists();
97
98   reload_after_sighup = True;
99
100   BlockSignals(False,SIGHUP);
101
102 } /* sig_hup */
103
104
105 #if DUMP_CORE
106 /**************************************************************************** **
107  prepare to dump a core file - carefully!
108  **************************************************************************** */
109 static BOOL dump_core(void)
110 {
111   char *p;
112   pstring dname;
113   pstrcpy( dname, debugf );
114   if ((p=strrchr(dname,'/')))
115     *p=0;
116   pstrcat( dname, "/corefiles" );
117   mkdir( dname, 0700 );
118   sys_chown( dname, getuid(), getgid() );
119   chmod( dname, 0700 );
120   if ( chdir(dname) )
121     return( False );
122   umask( ~(0700) );
123
124 #ifdef HAVE_GETRLIMIT
125 #ifdef RLIMIT_CORE
126   {
127     struct rlimit rlp;
128     getrlimit( RLIMIT_CORE, &rlp );
129     rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
130     setrlimit( RLIMIT_CORE, &rlp );
131     getrlimit( RLIMIT_CORE, &rlp );
132     DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
133   }
134 #endif
135 #endif
136
137
138   DEBUG(0,("Dumping core in %s\n",dname));
139   abort();
140   return( True );
141 } /* dump_core */
142 #endif
143
144
145 /**************************************************************************** **
146  possibly continue after a fault
147  **************************************************************************** */
148 static void fault_continue(void)
149 {
150 #if DUMP_CORE
151   dump_core();
152 #endif
153 } /* fault_continue */
154
155 /**************************************************************************** **
156  expire old names from the namelist and server list
157  **************************************************************************** */
158 static void expire_names_and_servers(time_t t)
159 {
160   static time_t lastrun = 0;
161   
162   if ( !lastrun )
163     lastrun = t;
164   if ( t < (lastrun + 5) )
165     return;
166   lastrun = t;
167
168   /*
169    * Expire any timed out names on all the broadcast
170    * subnets and those registered with the WINS server.
171    * (nmbd_namelistdb.c)
172    */
173   expire_names(t);
174
175   /*
176    * Go through all the broadcast subnets and for each
177    * workgroup known on that subnet remove any expired
178    * server names. If a workgroup has an empty serverlist
179    * and has itself timed out then remove the workgroup.
180    * (nmbd_workgroupdb.c)
181    */
182   expire_workgroups_and_servers(t);
183 } /* expire_names_and_servers */
184
185
186 /************************************************************************** **
187 reload the list of network interfaces
188  ************************************************************************** */
189 static void 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;
198         lastt = t;
199
200         if (!interfaces_changed()) return;
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
258
259
260 /**************************************************************************** **
261   reload the services file
262  **************************************************************************** */
263 static BOOL reload_nmbd_services(BOOL test)
264 {
265   BOOL ret;
266   extern fstring remote_machine;
267
268   fstrcpy( remote_machine, "nmb" );
269
270   if ( lp_loaded() )
271   {
272     pstring fname;
273     pstrcpy( fname,lp_configfile());
274     if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
275     {
276       pstrcpy(servicesf,fname);
277       test = False;
278     }
279   }
280
281   if ( test && !lp_file_list_changed() )
282     return(True);
283
284   ret = lp_load( servicesf, True , False, False);
285
286   /* perhaps the config filename is now set */
287   if ( !test )
288   {
289     DEBUG( 3, ( "services not loaded\n" ) );
290     reload_nmbd_services( True );
291   }
292
293   /* Do a sanity check for a misconfigured nmbd */
294   if( lp_wins_support() && *lp_wins_server() )
295   {
296     DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
297 cannot be set in the smb.conf file. nmbd aborting.\n"));
298     exit(10);
299   }
300
301   return(ret);
302 } /* reload_nmbd_services */
303
304 /**************************************************************************** **
305  The main select loop.
306  **************************************************************************** */
307 static void process(void)
308 {
309   BOOL run_election;
310
311   while( True )
312   {
313     time_t t = time(NULL);
314
315     /*
316      * Check all broadcast subnets to see if
317      * we need to run an election on any of them.
318      * (nmbd_elections.c)
319      */
320     run_election = check_elections();
321
322     /*
323      * Read incoming UDP packets.
324      * (nmbd_packets.c)
325      */
326     if(listen_for_packets(run_election))
327       return;
328
329     /*
330      * Process all incoming packets
331      * read above. This calls the success and
332      * failure functions registered when response
333      * packets arrrive, and also deals with request
334      * packets from other sources.
335      * (nmbd_packets.c)
336      */
337     run_packet_queue();
338
339     /*
340      * Run any elections - initiate becoming
341      * a local master browser if we have won.
342      * (nmbd_elections.c)
343      */
344     run_elections(t);
345
346     /*
347      * Send out any broadcast announcements
348      * of our server names. This also announces
349      * the workgroup name if we are a local
350      * master browser.
351      * (nmbd_sendannounce.c)
352      */
353     announce_my_server_names(t);
354
355     /*
356      * Send out any LanMan broadcast announcements
357      * of our server names.
358      * (nmbd_sendannounce.c)
359      */
360     announce_my_lm_server_names(t);
361
362     /*
363      * If we are a local master browser, periodically
364      * announce ourselves to the domain master browser.
365      * This also deals with syncronising the domain master
366      * browser server lists with ourselves as a local
367      * master browser.
368      * (nmbd_sendannounce.c)
369      */
370     announce_myself_to_domain_master_browser(t);
371
372     /*
373      * Fullfill any remote announce requests.
374      * (nmbd_sendannounce.c)
375      */
376     announce_remote(t);
377
378     /*
379      * Fullfill any remote browse sync announce requests.
380      * (nmbd_sendannounce.c)
381      */
382     browse_sync_remote(t);
383
384     /*
385      * Scan the broadcast subnets, and WINS client
386      * namelists and refresh any that need refreshing.
387      * (nmbd_mynames.c)
388      */
389     refresh_my_names(t);
390
391     /*
392      * Scan the subnet namelists and server lists and
393      * expire thos that have timed out.
394      * (nmbd.c)
395      */
396     expire_names_and_servers(t);
397
398     /*
399      * Write out a snapshot of our current browse list into
400      * the browse.dat file. This is used by smbd to service
401      * incoming NetServerEnum calls - used to synchronise
402      * browse lists over subnets.
403      * (nmbd_serverlistdb.c)
404      */
405     write_browse_list(t, False);
406
407     /*
408      * If we are a domain master browser, we have a list of
409      * local master browsers we should synchronise browse
410      * lists with (these are added by an incoming local
411      * master browser announcement packet). Expire any of
412      * these that are no longer current, and pull the server
413      * lists from each of these known local master browsers.
414      * (nmbd_browsesync.c)
415      */
416     dmb_expire_and_sync_browser_lists(t);
417
418     /*
419      * Check that there is a local master browser for our
420      * workgroup for all our broadcast subnets. If one
421      * is not found, start an election (which we ourselves
422      * may or may not participate in, depending on the
423      * setting of the 'local master' parameter.
424      * (nmbd_elections.c)
425      */
426     check_master_browser_exists(t);
427
428     /*
429      * If we are configured as a logon server, attempt to
430      * register the special NetBIOS names to become such
431      * (WORKGROUP<1c> name) on all broadcast subnets and
432      * with the WINS server (if used). If we are configured
433      * to become a domain master browser, attempt to register
434      * the special NetBIOS name (WORKGROUP<1b> name) to
435      * become such.
436      * (nmbd_become_dmb.c)
437      */
438     add_domain_names(t);
439
440     /*
441      * If we are a WINS server, do any timer dependent
442      * processing required.
443      * (nmbd_winsserver.c)
444      */
445     initiate_wins_processing(t);
446
447     /*
448      * If we are a domain master browser, attempt to contact the
449      * WINS server to get a list of all known WORKGROUPS/DOMAINS.
450      * This will only work to a Samba WINS server.
451      * (nmbd_browsesync.c)
452      */
453     collect_all_workgroup_names_from_wins_server(t);
454
455     /*
456      * Go through the response record queue and time out or re-transmit
457      * and expired entries.
458      * (nmbd_packets.c)
459      */
460     retransmit_or_expire_response_records(t);
461
462     /*
463      * check to see if any remote browse sync child processes have completed
464      */
465     sync_check_completion();
466
467     /*
468      * regularly sync with any other DMBs we know about 
469      */
470     sync_all_dmbs(t);
471
472     /*
473      * clear the unexpected packet queue 
474      */
475     clear_unexpected(t);
476
477     /*
478      * Reload the services file if we got a sighup.
479      */
480
481     if(reload_after_sighup) {
482             reload_nmbd_services( True );
483             reopen_logs();
484             reload_interfaces(0);
485             reload_after_sighup = False;
486     }
487
488     /* check for new network interfaces */
489     reload_interfaces(t);
490
491     /* free up temp memory */
492     lp_talloc_free();
493   }
494 } /* process */
495
496
497 /**************************************************************************** **
498  open the socket communication
499  **************************************************************************** */
500 static BOOL open_sockets(BOOL isdaemon, int port)
501 {
502   /* The sockets opened here will be used to receive broadcast
503      packets *only*. Interface specific sockets are opened in
504      make_subnet() in namedbsubnet.c. Thus we bind to the
505      address "0.0.0.0". The parameter 'socket address' is
506      now deprecated.
507    */
508
509   if ( isdaemon )
510     ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
511   else
512     ClientNMB = 0;
513   
514   ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
515
516   if ( ClientNMB == -1 )
517     return( False );
518
519   /* we are never interested in SIGPIPE */
520   BlockSignals(True,SIGPIPE);
521
522   set_socket_options( ClientNMB,   "SO_BROADCAST" );
523   set_socket_options( ClientDGRAM, "SO_BROADCAST" );
524
525   DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
526   return( True );
527 } /* open_sockets */
528
529
530 /**************************************************************************** **
531  initialise connect, service and file structs
532  **************************************************************************** */
533 static BOOL init_structs(void)
534 {
535   extern fstring local_machine;
536   char *p, *ptr;
537   int namecount;
538   int n;
539   int nodup;
540   pstring nbname;
541
542   if (! *global_myname)
543   {
544     fstrcpy( global_myname, myhostname() );
545     p = strchr( global_myname, '.' );
546     if (p)
547       *p = 0;
548   }
549   strupper( global_myname );
550
551   /* Add any NETBIOS name aliases. Ensure that the first entry
552      is equal to global_myname.
553    */
554   /* Work out the max number of netbios aliases that we have */
555   ptr = lp_netbios_aliases();
556   for( namecount=0; next_token(&ptr,nbname,NULL, sizeof(nbname)); namecount++ )
557     ;
558   if ( *global_myname )
559     namecount++;
560
561   /* Allocate space for the netbios aliases */
562   my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
563   if( NULL == my_netbios_names )
564   {
565      DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
566      return( False );
567   }
568  
569   /* Use the global_myname string first */
570   namecount=0;
571   if ( *global_myname )
572     my_netbios_names[namecount++] = global_myname;
573   
574   ptr = lp_netbios_aliases();
575   while ( next_token( &ptr, nbname, NULL, sizeof(nbname) ) )
576   {
577     strupper( nbname );
578     /* Look for duplicates */
579     nodup=1;
580     for( n=0; n<namecount; n++ )
581     {
582       if( 0 == strcmp( nbname, my_netbios_names[n] ) )
583         nodup=0;
584     }
585     if (nodup)
586       my_netbios_names[namecount++] = strdup( nbname );
587   }
588   
589   /* Check the strdups succeeded. */
590   for( n = 0; n < namecount; n++ )
591     if( NULL == my_netbios_names[n] )
592     {
593       DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
594       return False;
595     }
596   
597   /* Terminate name list */
598   my_netbios_names[namecount++] = NULL;
599   
600   fstrcpy( local_machine, global_myname );
601   trim_string( local_machine, " ", " " );
602   p = strchr( local_machine, ' ' );
603   if (p)
604     *p = 0;
605   strlower( local_machine );
606
607   DEBUG( 5, ("Netbios name list:-\n") );
608   for( n=0; my_netbios_names[n]; n++ )
609     DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
610
611   return( True );
612 } /* init_structs */
613
614 /**************************************************************************** **
615  usage on the program
616  **************************************************************************** */
617 static void usage(char *pname)
618 {
619
620   printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
621   printf( "       [-n name] [-p port] [-s configuration file]\n" );
622   printf( "\t-D                    Become a daemon\n" );
623   printf( "\t-a                    Append to log file (default)\n" );
624   printf( "\t-o                    Overwrite log file, don't append\n" );
625   printf( "\t-h                    Print usage\n" );
626   printf( "\t-V                    Print version\n" );
627   printf( "\t-H hosts file         Load a netbios hosts file\n" );
628   printf( "\t-d debuglevel         Set the debuglevel\n" );
629   printf( "\t-l log basename.      Basename for log/debug files\n" );
630   printf( "\t-n netbiosname.       Primary netbios name\n" );
631   printf( "\t-p port               Listen on the specified port\n" );
632   printf( "\t-s configuration file Configuration file name\n" );
633   printf( "\n");
634 } /* usage */
635
636
637 /**************************************************************************** **
638  main program
639  **************************************************************************** */
640  int main(int argc,char *argv[])
641 {
642   int opt;
643   extern FILE *dbf;
644   extern char *optarg;
645   extern BOOL  append_log;
646
647   append_log = True;  /* Default, override with '-o' option. */
648
649   global_nmb_port = NMB_PORT;
650   *host_file = 0;
651   global_in_nmbd = True;
652
653   StartupTime = time(NULL);
654
655   sys_srandom(time(NULL) ^ sys_getpid());
656
657   TimeInit();
658
659   pstrcpy( debugf, NMBLOGFILE );
660
661   setup_logging( argv[0], False );
662
663   charset_initialise();
664
665 #ifdef LMHOSTSFILE
666   pstrcpy( host_file, LMHOSTSFILE );
667 #endif
668
669   /* this is for people who can't start the program correctly */
670   while (argc > 1 && (*argv[1] != '-'))
671   {
672     argv++;
673     argc--;
674   }
675
676   fault_setup((void (*)(void *))fault_continue );
677
678   CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
679   CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
680
681 #if defined(SIGFPE)
682   /* we are never interested in SIGFPE */
683   BlockSignals(True,SIGFPE);
684 #endif
685
686   /* Setup the signals that allow the debug log level
687      to by dynamically changed. */
688
689   /* If we are using the malloc debug code we can't use
690      SIGUSR1 and SIGUSR2 to do debug level changes. */
691 #if defined(SIGUSR1)
692   CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
693 #endif /* SIGUSR1 */
694
695 #if defined(SIGUSR2)
696   CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
697 #endif /* SIGUSR2 */
698
699   while( EOF != 
700          (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:" )) )
701     {
702       switch (opt)
703         {
704         case 's':
705           pstrcpy(servicesf,optarg);
706           break;          
707         case 'N':
708         case 'B':
709         case 'I':
710         case 'C':
711         case 'G':
712           DEBUG(0,("Obsolete option '%c' used\n",opt));
713           break;
714         case 'H':
715           pstrcpy(host_file,optarg);
716           break;
717         case 'n':
718           pstrcpy(global_myname,optarg);
719           strupper(global_myname);
720           break;
721         case 'l':
722           slprintf(debugf,sizeof(debugf)-1, "%s.nmb",optarg);
723           break;
724         case 'a':
725           append_log = True;
726           break;
727         case 'o':
728           append_log = False;
729           break;
730         case 'D':
731           is_daemon = True;
732           break;
733         case 'd':
734           DEBUGLEVEL = atoi(optarg);
735           break;
736         case 'p':
737           global_nmb_port = atoi(optarg);
738           break;
739         case 'h':
740           usage(argv[0]);
741           exit(0);
742           break;
743         case 'V':
744           printf( "Version %s\n", VERSION );
745           exit(0);
746           break;
747         default:
748           if( !is_a_socket(0) )
749           {
750             DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
751             usage(argv[0]);
752             exit(0);
753           }
754           break;
755         }
756     }
757
758   reopen_logs();
759
760   DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
761   DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
762
763   if ( !reload_nmbd_services(False) )
764     return(-1);
765
766   codepage_initialise(lp_client_code_page());
767
768   if(!init_structs())
769     return -1;
770
771   reload_nmbd_services( True );
772
773   fstrcpy( global_myworkgroup, lp_workgroup() );
774
775   if (strequal(global_myworkgroup,"*"))
776   {
777     DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
778     exit(1);
779   }
780
781   set_samba_nb_type();
782
783   if (!is_daemon && !is_a_socket(0))
784   {
785     DEBUG(0,("standard input is not a socket, assuming -D option\n"));
786     is_daemon = True;
787   }
788   
789   if (is_daemon)
790   {
791     DEBUG( 2, ( "Becoming a daemon.\n" ) );
792     become_daemon();
793   }
794
795 #ifndef SYNC_DNS
796   /* Setup the async dns. We do it here so it doesn't have all the other
797      stuff initialised and thus chewing memory and sockets */
798   if(lp_we_are_a_wins_server()) {
799           start_async_dns();
800   }
801 #endif
802
803   if (!directory_exist(lp_lockdir(), NULL)) {
804           mkdir(lp_lockdir(), 0755);
805   }
806
807   pidfile_create("nmbd");
808
809   DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
810
811   if ( !open_sockets( is_daemon, global_nmb_port ) )
812     return 1;
813
814   /* Determine all the IP addresses we have. */
815   load_interfaces();
816
817   /* Create an nmbd subnet record for each of the above. */
818   if( False == create_subnets() )
819   {
820     DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
821     exit(1);
822   }
823
824   /* Load in any static local names. */ 
825   if ( *host_file )
826   {
827     load_lmhosts_file(host_file);
828     DEBUG(3,("Loaded hosts file\n"));
829   }
830
831   /* If we are acting as a WINS server, initialise data structures. */
832   if( !initialise_wins() )
833   {
834     DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
835     exit(1);
836   }
837
838   /* 
839    * Register nmbd primary workgroup and nmbd names on all
840    * the broadcast subnets, and on the WINS server (if specified).
841    * Also initiate the startup of our primary workgroup (start
842    * elections if we are setup as being able to be a local
843    * master browser.
844    */
845
846   if( False == register_my_workgroup_and_names() )
847   {
848     DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
849     exit(1);
850   }
851
852   /* We can only take signals in the select. */
853   BlockSignals( True, SIGTERM );
854 #if defined(SIGUSR1)
855   BlockSignals( True, SIGUSR1);
856 #endif /* SIGUSR1 */
857 #if defined(SIGUSR2)
858   BlockSignals( True, SIGUSR2);
859 #endif /* SIGUSR2 */
860
861   process();
862
863   if (dbf)
864     fclose(dbf);
865   return(0);
866 } /* main */
867