charset.c: Split charset_initialise() into 2 - a charset_initialise() and
[jra/samba/.git] / source3 / nmbd / nmbd.c
index 87a545aa1cc4c24e52b9d25a7521c04ac93b7e39..14611dc2c51db50ad01d05be9f22a3b1248d1fea 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    NBT netbios routines and daemon - version 2
-   Copyright (C) Andrew Tridgell 1994-1995
+   Copyright (C) Andrew Tridgell 1994-1997
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,7 +26,6 @@
 */
 
 #include "includes.h"
-#include "loadparm.h"
 
 extern int DEBUGLEVEL;
 
@@ -41,39 +40,41 @@ int ClientDGRAM = -1;
 extern pstring myhostname;
 static pstring host_file;
 extern pstring myname;
+extern fstring myworkgroup;
 
 /* are we running as a daemon ? */
 static BOOL is_daemon = False;
 
-/* machine comment for host announcements */
-pstring ServerComment="";
-
 /* what server type are we currently */
 
 time_t StartupTime =0;
 
 extern struct in_addr ipzero;
 
-
  /****************************************************************************
-catch a sigterm
-****************************************************************************/
+  catch a sigterm
+  ****************************************************************************/
 static int sig_term()
 {
-  BlockSignals(True);
+  BlockSignals(True,SIGTERM);
   
   DEBUG(0,("Got SIGTERM: going down...\n"));
   
+  /* write out wins.dat file if samba is a WINS server */
   dump_names();
-  reload_services(True);
   
   /* remove all samba names, with wins server if necessary. */
   remove_my_names();
   
+  /* announce all server entries as 0 time-to-live, 0 type */
   /* XXXX don't care if we never receive a response back... yet */
+  announce_my_servers_removed();
+
   /* XXXX other things: if we are a master browser, force an election? */
   
   exit(0);
+  /* Keep compiler happy.. */
+  return 0;
 }
 
 
@@ -82,13 +83,15 @@ catch a sighup
 ****************************************************************************/
 static int sig_hup(void)
 {
-  BlockSignals(True);
+  BlockSignals(True,SIGHUP);
 
   DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
   dump_names();
   reload_services(True);
 
-  BlockSignals(False);
+  set_samba_nb_type();
+
+  BlockSignals(False,SIGHUP);
 #ifndef DONT_REINSTALL_SIG
   signal(SIGHUP,SIGNAL_CAST sig_hup);
 #endif
@@ -100,12 +103,12 @@ catch a sigpipe
 ****************************************************************************/
 static int sig_pipe(void)
 {
-  BlockSignals(True);
+  BlockSignals(True,SIGPIPE);
 
   DEBUG(0,("Got SIGPIPE\n"));
   if (!is_daemon)
     exit(1);
-  BlockSignals(False);
+  BlockSignals(False,SIGPIPE);
   return(0);
 }
 
@@ -159,10 +162,9 @@ static void fault_continue(void)
 /*******************************************************************
   expire old names from the namelist and server list
   ******************************************************************/
-static void expire_names_and_servers(void)
+static void expire_names_and_servers(time_t t)
 {
   static time_t lastrun = 0;
-  time_t t = time(NULL);
   
   if (!lastrun) lastrun = t;
   if (t < lastrun + 5) return;
@@ -204,7 +206,12 @@ BOOL reload_services(BOOL test)
     reload_services(True);
   }
 
-  load_interfaces();
+  /* Do a sanity check for a misconfigured nmbd */
+  if(lp_wins_support() && *lp_wins_server()) {
+    DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
+cannot be set in the smb.conf file. nmbd aborting.\n"));
+    exit(10);
+  }
 
   return(ret);
 }
@@ -225,75 +232,60 @@ static void load_hosts_file(char *fname)
 
   while (!feof(f))
     {
+      pstring ip,name,flags,extra;
+      struct subnet_record *d;
+      char *ptr;
+      int count = 0;
+      struct in_addr ipaddr;
+      enum name_source source = LMHOSTS;
+
       if (!fgets_slash(line,sizeof(pstring),f)) continue;
 
       if (*line == '#') continue;
 
-      {
-       BOOL group=False;
-
-       pstring ip,name,mask,flags,extra;
-
-       char *ptr;
-       int count = 0;
-       struct in_addr ipaddr;
-       struct in_addr ipmask;
-       enum name_source source = LMHOSTS;
-
-       strcpy(ip,"");
-       strcpy(name,"");
-       strcpy(mask,"");
-       strcpy(flags,"");
-       strcpy(extra,"");
-       
-       ptr = line;
-
-       if (next_token(&ptr,ip   ,NULL)) ++count;
-       if (next_token(&ptr,name ,NULL)) ++count;
-       if (next_token(&ptr,mask ,NULL)) ++count;
-       if (next_token(&ptr,flags,NULL)) ++count;
-       if (next_token(&ptr,extra,NULL)) ++count;
-
-       if (count <= 0) continue;
-
-       if (count > 0 && count < 2) {
-         DEBUG(0,("Ill formed hosts line [%s]\n",line));           
-         continue;
-       }
-
-       /* work out if we need to shuffle the tokens along due to the
-          optional subnet mask argument */
-
-       if (strchr(mask, 'G') || strchr(mask, 'S') || strchr(mask, 'M')) {
-         strcpy(flags, mask );
-         /* default action for no subnet mask */
-         strcpy(mask, "");
-       }
-
-       DEBUG(4, ("lmhost entry: %s %s %s %s\n", ip, name, mask, flags));
-
-       if (strchr(flags,'G') || strchr(flags,'S'))
-         group = True;
-
-       if (strchr(flags,'M') && !group) {
-         source = SELF;
-         strcpy(myname,name);
-       }
-
-       ipaddr = *interpret_addr2(ip);
-       if (*mask)
-         ipmask = *interpret_addr2(mask);
-       else 
-         ipmask = *iface_nmask(ipaddr);
-
-       if (group) {
-         add_subnet_entry(ipaddr, ipmask, name, True);
-       } else {
-         add_netbios_entry(name,0x20,NB_ACTIVE,0,source,ipaddr,True);
-       }
+      strcpy(ip,"");
+      strcpy(name,"");
+      strcpy(flags,"");
+      
+      ptr = line;
+      
+      if (next_token(&ptr,ip   ,NULL)) ++count;
+      if (next_token(&ptr,name ,NULL)) ++count;
+      if (next_token(&ptr,flags,NULL)) ++count;
+      if (next_token(&ptr,extra,NULL)) ++count;
+      
+      if (count <= 0) continue;
+      
+      if (count > 0 && count < 2) {
+       DEBUG(0,("Ill formed hosts line [%s]\n",line));     
+       continue;
+      }
+      
+      if (count >= 4) {
+       DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
+       continue;
+      }
+      
+      DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
+      
+      if (strchr(flags,'G') || strchr(flags,'S')) {
+       DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
+       continue;
+      }
+      
+      if (strchr(flags,'M')) {
+       source = SELF;
+       strcpy(myname,name);
       }
+      
+      ipaddr = *interpret_addr2(ip);
+      d = find_subnet_all(ipaddr);
+      if (d) {
+       add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
+       add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
+      } 
     }
-
+  
   fclose(f);
 }
 
@@ -312,26 +304,22 @@ static void process(void)
       listen_for_packets(run_election);
 
       run_packet_queue();
-      run_elections();
+      run_elections(t);
 
-      announce_host();
+      announce_host(t);
+      announce_master(t);
+      announce_remote(t);
 
-#if 0
-      /* what was this stuff supposed to do? It sent
-        ANN_GetBackupListReq packets which I think should only be
-        sent when trying to find out who to browse with */      
-      announce_backup();
-#endif
+      query_refresh_names(t);
 
-      announce_master();
-
-      expire_names_and_servers();
-      expire_netbios_response_entries(t-10);
+      expire_names_and_servers(t);
+      expire_netbios_response_entries(t);
       refresh_my_names(t);
 
-      write_browse_list();
-      do_browser_lists();
-      check_master_browser();
+      write_browse_list(t);
+      do_browser_lists(t);
+      check_master_browser(t);
+      add_domain_names(t);
     }
 }
 
@@ -350,11 +338,11 @@ static BOOL open_sockets(BOOL isdaemon, int port)
   }   
 
   if (isdaemon)
-    ClientNMB = open_socket_in(SOCK_DGRAM, port,0);
+    ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
   else
     ClientNMB = 0;
   
-  ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
+  ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
 
   if (ClientNMB == -1)
     return(False);
@@ -374,15 +362,21 @@ static BOOL open_sockets(BOOL isdaemon, int port)
 ****************************************************************************/
 static BOOL init_structs()
 {
-  if (!get_myname(myhostname,NULL))
-    return(False);
+  extern fstring local_machine;
+  char *p;
 
   if (! *myname) {
-    char *p;
     strcpy(myname,myhostname);
     p = strchr(myname,'.');
     if (p) *p = 0;
   }
+  strupper(myname);
+
+  strcpy(local_machine,myname);
+  trim_string(local_machine," "," ");
+  p = strchr(local_machine,' ');
+  if (p) *p = 0;
+  strlower(local_machine);
 
   return True;
 }
@@ -394,19 +388,14 @@ static void usage(char *pname)
 {
   DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
 
-  printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
+  printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
   printf("Version %s\n",VERSION);
   printf("\t-D                    become a daemon\n");
   printf("\t-p port               listen on the specified port\n");
   printf("\t-d debuglevel         set the debuglevel\n");
   printf("\t-l log basename.      Basename for log/debug files\n");
   printf("\t-n netbiosname.       the netbios name to advertise for this host\n");
-  printf("\t-B broadcast address  the address to use for broadcasts\n");
-  printf("\t-N netmask           the netmask to use for subnet determination\n");
   printf("\t-H hosts file        load a netbios hosts file\n");
-  printf("\t-G group name        add a group name to be part of\n");
-  printf("\t-I ip-address        override the IP address\n");
-  printf("\t-C comment           sets the machine comment that appears in browse lists\n");
   printf("\n");
 }
 
@@ -420,9 +409,8 @@ static void usage(char *pname)
   int opt;
   extern FILE *dbf;
   extern char *optarg;
-  fstring group;
+  char pidFile[100] = { 0 };
 
-  *group = 0;
   *host_file = 0;
 
   StartupTime = time(NULL);
@@ -447,36 +435,32 @@ static void usage(char *pname)
 
   fault_setup(fault_continue);
 
-  signal(SIGHUP,SIGNAL_CAST sig_hup);
+  signal(SIGHUP ,SIGNAL_CAST sig_hup);
   signal(SIGTERM,SIGNAL_CAST sig_term);
 
-  while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
+  while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
     {
       switch (opt)
        {
+        case 'f':
+          strncpy(pidFile, optarg, sizeof(pidFile));
+          break;
        case 's':
          strcpy(servicesf,optarg);
-         break;
+         break;          
+       case 'N':
+       case 'B':
+       case 'I':
        case 'C':
-         strcpy(ServerComment,optarg);
-         break;
        case 'G':
-         strcpy(group,optarg);
+         DEBUG(0,("Obsolete option '%c' used\n",opt));
          break;
        case 'H':
          strcpy(host_file,optarg);
          break;
-       case 'I':
-         iface_set_default(optarg,NULL,NULL);
-         break;
-       case 'B':
-         iface_set_default(NULL,optarg,NULL);
-         break;
-       case 'N':
-         iface_set_default(NULL,NULL,optarg);
-         break;
        case 'n':
          strcpy(myname,optarg);
+         strupper(myname);
          break;
        case 'l':
          sprintf(debugf,"%s.nmb",optarg);
@@ -507,15 +491,27 @@ static void usage(char *pname)
     }
 
   DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
-  DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
+  DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
 
-  init_structs();
+  get_myname(myhostname,NULL);
 
   if (!reload_services(False))
     return(-1);        
 
-  if (*group)
-    add_my_domains(group);
+  codepage_initialise(lp_client_code_page());
+
+  init_structs();
+
+  reload_services(True);
+
+  strcpy(myworkgroup, lp_workgroup());
+
+  if (strequal(myworkgroup,"*")) {
+    DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
+    exit(1);
+  }
+
+  set_samba_nb_type();
 
   if (!is_daemon && !is_a_socket(0)) {
     DEBUG(0,("standard input is not a socket, assuming -D option\n"));
@@ -527,29 +523,58 @@ static void usage(char *pname)
     become_daemon();
   }
 
+  if (*pidFile)
+    {
+      int     fd;
+      char    buf[20];
+
+      if ((fd = open(pidFile,
+        O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
+        {
+          DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
+          exit(1);
+        }
+      if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
+        {
+          DEBUG(0,("ERROR: nmbd is already running\n"));
+          exit(1);
+        }
+      sprintf(buf, "%u\n", (unsigned int) getpid());
+      if (write(fd, buf, strlen(buf)) < 0)
+        {
+          DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
+          exit(1);
+        }
+      /* Leave pid file open & locked for the duration... */
+    }
+
+
   DEBUG(3,("Opening sockets %d\n", port));
 
   if (!open_sockets(is_daemon,port)) return 1;
 
-  if (*host_file) {
-    load_hosts_file(host_file);
-    DEBUG(3,("Loaded hosts file\n"));
-  }
-
-  if (!*ServerComment)
-    strcpy(ServerComment,"Samba %v");
-  string_sub(ServerComment,"%v",VERSION);
-  string_sub(ServerComment,"%h",myhostname);
+  load_interfaces();
+  add_my_subnets(myworkgroup);
 
   add_my_names();
-  add_my_domains(lp_workgroup());
 
   DEBUG(3,("Checked names\n"));
   
-  write_browse_list();
+  load_netbios_names();
+
+  DEBUG(3,("Loaded names\n"));
+
+  if (*host_file) {
+    load_hosts_file(host_file);
+    DEBUG(3,("Loaded hosts file\n"));
+  }
+
+  write_browse_list(time(NULL));
 
   DEBUG(3,("Dumped names\n"));
 
+  /* We can only take sigterm signals in the select. */
+  BlockSignals(True,SIGTERM);
   process();
   close_sockets();