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