The big character set handling changeover!
[tprouty/samba.git] / source3 / 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 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
267 /**************************************************************************** **
268   reload the services file
269  **************************************************************************** */
270 static BOOL reload_nmbd_services(BOOL test)
271 {
272   BOOL ret;
273   extern fstring remote_machine;
274
275   fstrcpy( remote_machine, "nmbd" );
276
277   if ( lp_loaded() )
278   {
279     pstring fname;
280     pstrcpy( fname,lp_configfile());
281     if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
282     {
283       pstrcpy(servicesf,fname);
284       test = False;
285     }
286   }
287
288   if ( test && !lp_file_list_changed() )
289     return(True);
290
291   ret = lp_load( servicesf, True , False, False);
292
293   /* perhaps the config filename is now set */
294   if ( !test )
295   {
296     DEBUG( 3, ( "services not loaded\n" ) );
297     reload_nmbd_services( True );
298   }
299
300   /* Do a sanity check for a misconfigured nmbd */
301   if( lp_wins_support() && *lp_wins_server() )
302   {
303     DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
304 cannot be set in the smb.conf file. nmbd aborting.\n"));
305     exit(10);
306   }
307
308   return(ret);
309 } /* reload_nmbd_services */
310
311 /**************************************************************************** **
312  The main select loop.
313  **************************************************************************** */
314 static void process(void)
315 {
316   BOOL run_election;
317
318   while( True )
319   {
320     time_t t = time(NULL);
321
322     /* check for internal messages */
323     message_dispatch();
324
325     /*
326      * Check all broadcast subnets to see if
327      * we need to run an election on any of them.
328      * (nmbd_elections.c)
329      */
330     run_election = check_elections();
331
332     /*
333      * Read incoming UDP packets.
334      * (nmbd_packets.c)
335      */
336     if(listen_for_packets(run_election))
337       return;
338
339     /*
340      * Process all incoming packets
341      * read above. This calls the success and
342      * failure functions registered when response
343      * packets arrrive, and also deals with request
344      * packets from other sources.
345      * (nmbd_packets.c)
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     run_elections(t);
355
356     /*
357      * Send out any broadcast announcements
358      * of our server names. This also announces
359      * the workgroup name if we are a local
360      * master browser.
361      * (nmbd_sendannounce.c)
362      */
363     announce_my_server_names(t);
364
365     /*
366      * Send out any LanMan broadcast announcements
367      * of our server names.
368      * (nmbd_sendannounce.c)
369      */
370     announce_my_lm_server_names(t);
371
372     /*
373      * If we are a local master browser, periodically
374      * announce ourselves to the domain master browser.
375      * This also deals with syncronising the domain master
376      * browser server lists with ourselves as a local
377      * master browser.
378      * (nmbd_sendannounce.c)
379      */
380     announce_myself_to_domain_master_browser(t);
381
382     /*
383      * Fullfill any remote announce requests.
384      * (nmbd_sendannounce.c)
385      */
386     announce_remote(t);
387
388     /*
389      * Fullfill any remote browse sync announce requests.
390      * (nmbd_sendannounce.c)
391      */
392     browse_sync_remote(t);
393
394     /*
395      * Scan the broadcast subnets, and WINS client
396      * namelists and refresh any that need refreshing.
397      * (nmbd_mynames.c)
398      */
399     refresh_my_names(t);
400
401     /*
402      * Scan the subnet namelists and server lists and
403      * expire thos that have timed out.
404      * (nmbd.c)
405      */
406     expire_names_and_servers(t);
407
408     /*
409      * Write out a snapshot of our current browse list into
410      * the browse.dat file. This is used by smbd to service
411      * incoming NetServerEnum calls - used to synchronise
412      * browse lists over subnets.
413      * (nmbd_serverlistdb.c)
414      */
415     write_browse_list(t, False);
416
417     /*
418      * If we are a domain master browser, we have a list of
419      * local master browsers we should synchronise browse
420      * lists with (these are added by an incoming local
421      * master browser announcement packet). Expire any of
422      * these that are no longer current, and pull the server
423      * lists from each of these known local master browsers.
424      * (nmbd_browsesync.c)
425      */
426     dmb_expire_and_sync_browser_lists(t);
427
428     /*
429      * Check that there is a local master browser for our
430      * workgroup for all our broadcast subnets. If one
431      * is not found, start an election (which we ourselves
432      * may or may not participate in, depending on the
433      * setting of the 'local master' parameter.
434      * (nmbd_elections.c)
435      */
436     check_master_browser_exists(t);
437
438     /*
439      * If we are configured as a logon server, attempt to
440      * register the special NetBIOS names to become such
441      * (WORKGROUP<1c> name) on all broadcast subnets and
442      * with the WINS server (if used). If we are configured
443      * to become a domain master browser, attempt to register
444      * the special NetBIOS name (WORKGROUP<1b> name) to
445      * become such.
446      * (nmbd_become_dmb.c)
447      */
448     add_domain_names(t);
449
450     /*
451      * If we are a WINS server, do any timer dependent
452      * processing required.
453      * (nmbd_winsserver.c)
454      */
455     initiate_wins_processing(t);
456
457     /*
458      * If we are a domain master browser, attempt to contact the
459      * WINS server to get a list of all known WORKGROUPS/DOMAINS.
460      * This will only work to a Samba WINS server.
461      * (nmbd_browsesync.c)
462      */
463     if (lp_enhanced_browsing()) {
464             collect_all_workgroup_names_from_wins_server(t);
465     }
466
467     /*
468      * Go through the response record queue and time out or re-transmit
469      * and expired entries.
470      * (nmbd_packets.c)
471      */
472     retransmit_or_expire_response_records(t);
473
474     /*
475      * check to see if any remote browse sync child processes have completed
476      */
477     sync_check_completion();
478
479     /*
480      * regularly sync with any other DMBs we know about 
481      */
482     if (lp_enhanced_browsing()) {
483             sync_all_dmbs(t);
484     }
485
486     /*
487      * clear the unexpected packet queue 
488      */
489     clear_unexpected(t);
490
491     /*
492      * Reload the services file if we got a sighup.
493      */
494
495     if(reload_after_sighup) {
496             reload_nmbd_services( True );
497             reopen_logs();
498             if(reload_interfaces(0))
499                         return;
500             reload_after_sighup = False;
501     }
502
503     /* check for new network interfaces */
504     if(reload_interfaces(t))
505                 return;
506
507     /* free up temp memory */
508     lp_talloc_free();
509   }
510 } /* process */
511
512
513 /**************************************************************************** **
514  open the socket communication
515  **************************************************************************** */
516 static BOOL open_sockets(BOOL isdaemon, int port)
517 {
518   /* The sockets opened here will be used to receive broadcast
519      packets *only*. Interface specific sockets are opened in
520      make_subnet() in namedbsubnet.c. Thus we bind to the
521      address "0.0.0.0". The parameter 'socket address' is
522      now deprecated.
523    */
524
525   if ( isdaemon )
526     ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
527   else
528     ClientNMB = 0;
529   
530   ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
531
532   if ( ClientNMB == -1 )
533     return( False );
534
535   /* we are never interested in SIGPIPE */
536   BlockSignals(True,SIGPIPE);
537
538   set_socket_options( ClientNMB,   "SO_BROADCAST" );
539   set_socket_options( ClientDGRAM, "SO_BROADCAST" );
540
541   DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
542   return( True );
543 } /* open_sockets */
544
545
546 /**************************************************************************** **
547  initialise connect, service and file structs
548  **************************************************************************** */
549 static BOOL init_structs(void)
550 {
551   extern fstring local_machine;
552   char *p, **ptr;
553   int namecount;
554   int n;
555   int nodup;
556   char *nbname;
557
558   if (! *global_myname)
559   {
560     fstrcpy( global_myname, myhostname() );
561     p = strchr( global_myname, '.' );
562     if (p)
563       *p = 0;
564   }
565   strupper( global_myname );
566
567   /* Add any NETBIOS name aliases. Ensure that the first entry
568      is equal to global_myname.
569    */
570   /* Work out the max number of netbios aliases that we have */
571   ptr = lp_netbios_aliases();
572   namecount = 0;
573   if (ptr)
574     for( ; *ptr; namecount++,ptr++ )
575       ;
576   if ( *global_myname )
577     namecount++;
578
579   /* Allocate space for the netbios aliases */
580   my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
581   if( NULL == my_netbios_names )
582   {
583      DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
584      return( False );
585   }
586  
587   /* Use the global_myname string first */
588   namecount=0;
589   if ( *global_myname )
590     my_netbios_names[namecount++] = global_myname;
591   
592   ptr = lp_netbios_aliases();
593   if (ptr)
594   {
595     while ( *ptr )
596     {
597       nbname = strdup(*ptr);
598       if (nbname == NULL)
599       {
600         DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
601         return False;
602       }
603       strupper( nbname );
604       /* Look for duplicates */
605       nodup=1;
606       for( n=0; n<namecount; n++ )
607       {
608         if( 0 == strcmp( nbname, my_netbios_names[n] ) )
609           nodup=0;
610       }
611       if (nodup)
612         my_netbios_names[namecount++] = nbname;
613       else
614         free(nbname);
615
616       ptr++;
617     }
618   }
619   
620   /* Terminate name list */
621   my_netbios_names[namecount++] = NULL;
622   
623   fstrcpy( local_machine, global_myname );
624   trim_string( local_machine, " ", " " );
625   p = strchr( local_machine, ' ' );
626   if (p)
627     *p = 0;
628   strlower( local_machine );
629
630   DEBUG( 5, ("Netbios name list:-\n") );
631   for( n=0; my_netbios_names[n]; n++ )
632     DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
633
634   return( True );
635 } /* init_structs */
636
637 /**************************************************************************** **
638  usage on the program
639  **************************************************************************** */
640 static void usage(char *pname)
641 {
642
643   printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
644   printf( "       [-n name] [-p port] [-s configuration file]\n" );
645   printf( "\t-D                    Become a daemon\n" );
646   printf( "\t-a                    Append to log file (default)\n" );
647   printf( "\t-o                    Overwrite log file, don't append\n" );
648   printf( "\t-h                    Print usage\n" );
649   printf( "\t-V                    Print version\n" );
650   printf( "\t-H hosts file         Load a netbios hosts file\n" );
651   printf( "\t-d debuglevel         Set the debuglevel\n" );
652   printf( "\t-l log basename.      Basename for log/debug files\n" );
653   printf( "\t-n netbiosname.       Primary netbios name\n" );
654   printf( "\t-p port               Listen on the specified port\n" );
655   printf( "\t-s configuration file Configuration file name\n" );
656   printf( "\n");
657 } /* usage */
658
659
660 /**************************************************************************** **
661  main program
662  **************************************************************************** */
663  int main(int argc,char *argv[])
664 {
665   int opt;
666   extern FILE *dbf;
667   extern char *optarg;
668   extern BOOL  append_log;
669
670   append_log = True;  /* Default, override with '-o' option. */
671
672   global_nmb_port = NMB_PORT;
673   *host_file = 0;
674   global_in_nmbd = True;
675
676   StartupTime = time(NULL);
677
678   sys_srandom(time(NULL) ^ sys_getpid());
679
680   TimeInit();
681
682   slprintf(debugf, sizeof(debugf)-1, "%s/log.nmbd", LOGFILEBASE);
683   setup_logging( argv[0], False );
684
685 #ifdef LMHOSTSFILE
686   pstrcpy( host_file, LMHOSTSFILE );
687 #endif
688
689   /* this is for people who can't start the program correctly */
690   while (argc > 1 && (*argv[1] != '-'))
691   {
692     argv++;
693     argc--;
694   }
695
696   fault_setup((void (*)(void *))fault_continue );
697
698   /* POSIX demands that signals are inherited. If the invoking process has
699    * these signals masked, we will have problems, as we won't recieve them. */
700   BlockSignals(False, SIGHUP);
701   BlockSignals(False, SIGUSR1);
702   BlockSignals(False, SIGTERM);
703
704   CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
705   CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
706
707 #if defined(SIGFPE)
708   /* we are never interested in SIGFPE */
709   BlockSignals(True,SIGFPE);
710 #endif
711
712   /* We no longer use USR2... */
713 #if defined(SIGUSR2)
714   BlockSignals(True, SIGUSR2);
715 #endif
716
717   while( EOF != 
718          (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:" )) )
719     {
720       switch (opt)
721         {
722         case 's':
723           pstrcpy(servicesf,optarg);
724           break;          
725         case 'N':
726         case 'B':
727         case 'I':
728         case 'C':
729         case 'G':
730           DEBUG(0,("Obsolete option '%c' used\n",opt));
731           break;
732         case 'H':
733           pstrcpy(host_file,optarg);
734           break;
735         case 'n':
736           pstrcpy(global_myname,optarg);
737           strupper(global_myname);
738           break;
739         case 'l':
740           slprintf(debugf,sizeof(debugf)-1, "%s.nmb",optarg);
741           break;
742         case 'a':
743           append_log = True;
744           break;
745         case 'o':
746           append_log = False;
747           break;
748         case 'D':
749           is_daemon = True;
750           break;
751         case 'd':
752           DEBUGLEVEL = atoi(optarg);
753           break;
754         case 'p':
755           global_nmb_port = atoi(optarg);
756           break;
757         case 'h':
758           usage(argv[0]);
759           exit(0);
760           break;
761         case 'V':
762           printf( "Version %s\n", VERSION );
763           exit(0);
764           break;
765         default:
766           if( !is_a_socket(0) )
767           {
768             DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
769             usage(argv[0]);
770             exit(0);
771           }
772           break;
773         }
774     }
775
776   reopen_logs();
777
778   DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
779   DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
780
781   if ( !reload_nmbd_services(False) )
782     return(-1);
783
784   if(!init_structs())
785     return -1;
786
787   reload_nmbd_services( True );
788
789   fstrcpy( global_myworkgroup, lp_workgroup() );
790
791   if (strequal(global_myworkgroup,"*"))
792   {
793     DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
794     exit(1);
795   }
796
797   set_samba_nb_type();
798
799   if (!is_daemon && !is_a_socket(0))
800   {
801     DEBUG(0,("standard input is not a socket, assuming -D option\n"));
802     is_daemon = True;
803   }
804   
805   if (is_daemon)
806   {
807     DEBUG( 2, ( "Becoming a daemon.\n" ) );
808     become_daemon();
809   }
810
811 #ifndef SYNC_DNS
812   /* Setup the async dns. We do it here so it doesn't have all the other
813      stuff initialised and thus chewing memory and sockets */
814   if(lp_we_are_a_wins_server()) {
815           start_async_dns();
816   }
817 #endif
818
819   if (!directory_exist(lp_lockdir(), NULL)) {
820           mkdir(lp_lockdir(), 0755);
821   }
822
823   pidfile_create("nmbd");
824   message_init();
825   message_register(MSG_FORCE_ELECTION, nmbd_message_election);
826
827   DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
828
829   if ( !open_sockets( is_daemon, global_nmb_port ) )
830     return 1;
831
832   /* Determine all the IP addresses we have. */
833   load_interfaces();
834
835   /* Create an nmbd subnet record for each of the above. */
836   if( False == create_subnets() )
837   {
838     DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
839     exit(1);
840   }
841
842   /* Load in any static local names. */ 
843   if ( *host_file )
844   {
845     load_lmhosts_file(host_file);
846     DEBUG(3,("Loaded hosts file\n"));
847   }
848
849   /* If we are acting as a WINS server, initialise data structures. */
850   if( !initialise_wins() )
851   {
852     DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
853     exit(1);
854   }
855
856   /* 
857    * Register nmbd primary workgroup and nmbd names on all
858    * the broadcast subnets, and on the WINS server (if specified).
859    * Also initiate the startup of our primary workgroup (start
860    * elections if we are setup as being able to be a local
861    * master browser.
862    */
863
864   if( False == register_my_workgroup_and_names() )
865   {
866     DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
867     exit(1);
868   }
869
870   /* We can only take signals in the select. */
871   BlockSignals( True, SIGTERM );
872
873   process();
874
875   if (dbf)
876     fclose(dbf);
877   return(0);
878 } /* main */
879