home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / nmbd.c < prev    next >
C/C++ Source or Header  |  1997-07-31  |  16KB  |  648 lines

  1. /*
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios routines and daemon - version 2
  5.    Copyright (C) Andrew Tridgell 1994-1997
  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. extern pstring scope;
  36.  
  37. int ClientNMB   = -1;
  38. int ClientDGRAM = -1;
  39.  
  40. extern pstring myhostname;
  41. static pstring host_file;
  42. extern pstring myname;
  43. extern fstring myworkgroup;
  44. extern char **my_netbios_names;
  45.  
  46. /* are we running as a daemon ? */
  47. static BOOL is_daemon = False;
  48.  
  49. /* what server type are we currently */
  50.  
  51. time_t StartupTime =0;
  52.  
  53. extern struct in_addr ipzero;
  54.  
  55.  /****************************************************************************
  56.   catch a sigterm
  57.   ****************************************************************************/
  58. static int sig_term()
  59. {
  60.   BlockSignals(True,SIGTERM);
  61.   
  62.   DEBUG(0,("Got SIGTERM: going down...\n"));
  63.   
  64.   /* write out wins.dat file if samba is a WINS server */
  65.   dump_names();
  66.   
  67.   /* remove all samba names, with wins server if necessary. */
  68.   remove_my_names();
  69.   
  70.   /* announce all server entries as 0 time-to-live, 0 type */
  71.   /* XXXX don't care if we never receive a response back... yet */
  72.   announce_my_servers_removed();
  73.  
  74.   /* XXXX other things: if we are a master browser, force an election? */
  75.   
  76.   exit(0);
  77.   /* Keep compiler happy.. */
  78.   return 0;
  79. }
  80.  
  81.  
  82. /****************************************************************************
  83. catch a sighup
  84. ****************************************************************************/
  85. static int sig_hup(void)
  86. {
  87.   BlockSignals(True,SIGHUP);
  88.  
  89.   DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
  90.   dump_names();
  91.   reload_services(True);
  92.  
  93.   set_samba_nb_type();
  94.  
  95.   BlockSignals(False,SIGHUP);
  96. #ifndef DONT_REINSTALL_SIG
  97.   signal(SIGHUP,SIGNAL_CAST sig_hup);
  98. #endif
  99.   return(0);
  100. }
  101.  
  102. /****************************************************************************
  103. catch a sigpipe
  104. ****************************************************************************/
  105. static int sig_pipe(void)
  106. {
  107.   BlockSignals(True,SIGPIPE);
  108.  
  109.   DEBUG(0,("Got SIGPIPE\n"));
  110.   if (!is_daemon)
  111.     exit(1);
  112.   BlockSignals(False,SIGPIPE);
  113.   return(0);
  114. }
  115.  
  116. #if DUMP_CORE
  117. /*******************************************************************
  118. prepare to dump a core file - carefully!
  119. ********************************************************************/
  120. static BOOL dump_core(void)
  121. {
  122.   char *p;
  123.   pstring dname;
  124.   strcpy(dname,debugf);
  125.   if ((p=strrchr(dname,'/'))) *p=0;
  126.   strcat(dname,"/corefiles");
  127.   mkdir(dname,0700);
  128.   sys_chown(dname,getuid(),getgid());
  129.   chmod(dname,0700);
  130.   if (chdir(dname)) return(False);
  131.   umask(~(0700));
  132.  
  133. #ifndef NO_GETRLIMIT
  134. #ifdef RLIMIT_CORE
  135.   {
  136.     struct rlimit rlp;
  137.     getrlimit(RLIMIT_CORE, &rlp);
  138.     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
  139.     setrlimit(RLIMIT_CORE, &rlp);
  140.     getrlimit(RLIMIT_CORE, &rlp);
  141.     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
  142.   }
  143. #endif
  144. #endif
  145.  
  146.  
  147.   DEBUG(0,("Dumping core in %s\n",dname));
  148.   return(True);
  149. }
  150. #endif
  151.  
  152.  
  153. /****************************************************************************
  154. possibly continue after a fault
  155. ****************************************************************************/
  156. static void fault_continue(void)
  157. {
  158. #if DUMP_CORE
  159.   dump_core();
  160. #endif
  161. }
  162.  
  163. /*******************************************************************
  164.   expire old names from the namelist and server list
  165.   ******************************************************************/
  166. static void expire_names_and_servers(time_t t)
  167. {
  168.   static time_t lastrun = 0;
  169.   
  170.   if (!lastrun) lastrun = t;
  171.   if (t < lastrun + 5) return;
  172.   lastrun = t;
  173.   
  174.   expire_names(t);
  175.   expire_servers(t);
  176. }
  177.  
  178. /*****************************************************************************
  179.   reload the services file
  180.   **************************************************************************/
  181. BOOL reload_services(BOOL test)
  182. {
  183.   BOOL ret;
  184.   extern fstring remote_machine;
  185.  
  186.   strcpy(remote_machine,"nmbd");
  187.  
  188.   if (lp_loaded())
  189.     {
  190.       pstring fname;
  191.       strcpy(fname,lp_configfile());
  192.       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
  193.     {
  194.       strcpy(servicesf,fname);
  195.       test = False;
  196.     }
  197.     }
  198.  
  199.   if (test && !lp_file_list_changed())
  200.     return(True);
  201.  
  202.   ret = lp_load(servicesf,True);
  203.  
  204.   /* perhaps the config filename is now set */
  205.   if (!test) {
  206.     DEBUG(3,("services not loaded\n"));
  207.     reload_services(True);
  208.   }
  209.  
  210.   /* Do a sanity check for a misconfigured nmbd */
  211.   if(lp_wins_support() && *lp_wins_server()) {
  212.     DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
  213. cannot be set in the smb.conf file. nmbd aborting.\n"));
  214.     exit(10);
  215.   }
  216.  
  217.   return(ret);
  218. }
  219.  
  220.  
  221.  
  222. /****************************************************************************
  223. load a netbios hosts file
  224. ****************************************************************************/
  225. static void load_hosts_file(char *fname)
  226. {
  227.   FILE *f = fopen(fname,"r");
  228.   pstring line;
  229.   if (!f) {
  230.     DEBUG(2,("Can't open lmhosts file %s\n",fname));
  231.     return;
  232.   }
  233.  
  234.   while (!feof(f))
  235.     {
  236.       pstring ip,name,flags,extra;
  237.       struct subnet_record *d;
  238.       char *ptr;
  239.       int count = 0;
  240.       struct in_addr ipaddr;
  241.       enum name_source source = LMHOSTS;
  242.  
  243.       if (!fgets_slash(line,sizeof(pstring),f)) continue;
  244.  
  245.       if (*line == '#') continue;
  246.  
  247.       strcpy(ip,"");
  248.       strcpy(name,"");
  249.       strcpy(flags,"");
  250.       
  251.       ptr = line;
  252.       
  253.       if (next_token(&ptr,ip   ,NULL)) ++count;
  254.       if (next_token(&ptr,name ,NULL)) ++count;
  255.       if (next_token(&ptr,flags,NULL)) ++count;
  256.       if (next_token(&ptr,extra,NULL)) ++count;
  257.       
  258.       if (count <= 0) continue;
  259.       
  260.       if (count > 0 && count < 2) {
  261.     DEBUG(0,("Ill formed hosts line [%s]\n",line));        
  262.     continue;
  263.       }
  264.       
  265.       if (count >= 4) {
  266.     DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
  267.     continue;
  268.       }
  269.       
  270.       DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
  271.       
  272.       if (strchr(flags,'G') || strchr(flags,'S')) {
  273.     DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
  274.     continue;
  275.       }
  276.       
  277.       if (strchr(flags,'M')) {
  278.     source = SELF;
  279.     strcpy(myname,name);
  280.       }
  281.       
  282.       ipaddr = *interpret_addr2(ip);
  283.       d = find_subnet_all(ipaddr);
  284.       if (d) {
  285.     add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
  286.     add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
  287.       } 
  288.     }
  289.   
  290.   fclose(f);
  291. }
  292.  
  293.  
  294. /****************************************************************************
  295.   The main select loop.
  296.   ***************************************************************************/
  297. static void process(void)
  298. {
  299.   BOOL run_election;
  300.  
  301.   while (True)
  302.     {
  303.       time_t t = time(NULL);
  304.       run_election = check_elections();
  305.       listen_for_packets(run_election);
  306.  
  307.       run_packet_queue();
  308.       run_elections(t);
  309.  
  310.       announce_host(t);
  311.       announce_master(t);
  312.       announce_remote(t);
  313.  
  314.       query_refresh_names(t);
  315.  
  316.       expire_names_and_servers(t);
  317.       expire_netbios_response_entries(t);
  318.       refresh_my_names(t);
  319.  
  320.       write_browse_list(t);
  321.       do_browser_lists(t);
  322.       check_master_browser(t);
  323.       add_domain_names(t);
  324.     }
  325. }
  326.  
  327.  
  328. /****************************************************************************
  329.   open the socket communication
  330. ****************************************************************************/
  331. static BOOL open_sockets(BOOL isdaemon, int port)
  332. {
  333.   struct hostent *hp;
  334.  
  335.   /* get host info */
  336.   if ((hp = Get_Hostbyname(myhostname)) == 0) {
  337.     DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
  338.     return False;
  339.   }   
  340.  
  341.   if (isdaemon)
  342.     ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
  343.   else
  344.     ClientNMB = 0;
  345.   
  346.   ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
  347.  
  348.   if (ClientNMB == -1)
  349.     return(False);
  350.  
  351.   signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  352.  
  353.   set_socket_options(ClientNMB,"SO_BROADCAST");
  354.   set_socket_options(ClientDGRAM,"SO_BROADCAST");
  355.  
  356.   DEBUG(3,("Sockets opened.\n"));
  357.   return True;
  358. }
  359.  
  360.  
  361. /****************************************************************************
  362.   initialise connect, service and file structs
  363. ****************************************************************************/
  364. static BOOL init_structs()
  365. {
  366.   extern fstring local_machine;
  367.   char *p, *ptr;
  368.   int namecount;
  369.   int n;
  370.   int nodup;
  371.   pstring nbname;
  372.  
  373.   if (! *myname) {
  374.     strcpy(myname,myhostname);
  375.     p = strchr(myname,'.');
  376.     if (p) *p = 0;
  377.   }
  378.   strupper(myname);
  379.  
  380.   /* Add any NETBIOS name aliases. Ensure that the first entry
  381.      is equal to myname. */
  382.   /* Work out the max number of netbios aliases that we have */
  383.   ptr=lp_netbios_aliases();
  384.   for (namecount=0; next_token(&ptr,nbname,NULL); namecount++)
  385.     ;
  386.   if (*myname)
  387.       namecount++;
  388.  
  389.   /* Allocate space for the netbios aliases */
  390.   if((my_netbios_names=(char **)malloc(sizeof(char *)*(namecount+1))) == NULL)
  391.   {
  392.      DEBUG(0,("init_structs: malloc fail.\n"));
  393.      return False;
  394.   }
  395.  
  396.   /* Use the myname string first */
  397.   namecount=0;
  398.   if (*myname)
  399.     my_netbios_names[namecount++] = myname;
  400.   
  401.   ptr=lp_netbios_aliases();
  402.   while (next_token(&ptr,nbname,NULL)) {
  403.     strupper(nbname);
  404.     /* Look for duplicates */
  405.     nodup=1;
  406.     for(n=0; n<namecount; n++) {
  407.       if (strcmp(nbname, my_netbios_names[n])==0)
  408.         nodup=0;
  409.     }
  410.     if (nodup)
  411.       my_netbios_names[namecount++]=strdup(nbname);
  412.   }
  413.   
  414.   /* Check the strdups succeeded. */
  415.   for(n = 0; n < namecount; n++)
  416.     if(my_netbios_names[n]==NULL)
  417.     {
  418.       DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
  419.       return False;
  420.     }
  421.   
  422.   /* Terminate name list */
  423.   my_netbios_names[namecount++]=NULL;
  424.   
  425.   strcpy(local_machine,myname);
  426.   trim_string(local_machine," "," ");
  427.   p = strchr(local_machine,' ');
  428.   if (p) 
  429.     *p = 0;
  430.   strlower(local_machine);
  431.  
  432.   DEBUG(5, ("Netbios name list:-\n"));
  433.   for (n=0; my_netbios_names[n]; n++)
  434.     DEBUG(5, ("my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n]));
  435.  
  436.   return True;
  437. }
  438.  
  439. /****************************************************************************
  440. usage on the program
  441. ****************************************************************************/
  442. static void usage(char *pname)
  443. {
  444.   DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
  445.  
  446.   printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
  447.   printf("Version %s\n",VERSION);
  448.   printf("\t-D                    become a daemon\n");
  449.   printf("\t-p port               listen on the specified port\n");
  450.   printf("\t-d debuglevel         set the debuglevel\n");
  451.   printf("\t-l log basename.      Basename for log/debug files\n");
  452.   printf("\t-n netbiosname.       the netbios name to advertise for this host\n");
  453.   printf("\t-H hosts file        load a netbios hosts file\n");
  454.   printf("\n");
  455. }
  456.  
  457.  
  458. /****************************************************************************
  459.   main program
  460.   **************************************************************************/
  461.  int main(int argc,char *argv[])
  462. {
  463.   int port = NMB_PORT;
  464.   int opt;
  465.   extern FILE *dbf;
  466.   extern char *optarg;
  467.   char pidFile[100] = { 0 };
  468.  
  469.   *host_file = 0;
  470.  
  471.   StartupTime = time(NULL);
  472.  
  473.   TimeInit();
  474.  
  475.   strcpy(debugf,NMBLOGFILE);
  476.  
  477.   setup_logging(argv[0],False);
  478.  
  479.   charset_initialise();
  480.  
  481. #ifdef LMHOSTSFILE
  482.   strcpy(host_file,LMHOSTSFILE);
  483. #endif
  484.  
  485.   /* this is for people who can't start the program correctly */
  486.   while (argc > 1 && (*argv[1] != '-')) {
  487.     argv++;
  488.     argc--;
  489.   }
  490.  
  491.   fault_setup(fault_continue);
  492.  
  493.   signal(SIGHUP ,SIGNAL_CAST sig_hup);
  494.   signal(SIGTERM,SIGNAL_CAST sig_term);
  495.  
  496.   while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
  497.     {
  498.       switch (opt)
  499.     {
  500.         case 'f':
  501.           strncpy(pidFile, optarg, sizeof(pidFile));
  502.           break;
  503.     case 's':
  504.       strcpy(servicesf,optarg);
  505.       break;      
  506.     case 'N':
  507.     case 'B':
  508.     case 'I':
  509.     case 'C':
  510.     case 'G':
  511.       DEBUG(0,("Obsolete option '%c' used\n",opt));
  512.       break;
  513.     case 'H':
  514.       strcpy(host_file,optarg);
  515.       break;
  516.     case 'n':
  517.       strcpy(myname,optarg);
  518.       strupper(myname);
  519.       break;
  520.     case 'l':
  521.       sprintf(debugf,"%s.nmb",optarg);
  522.       break;
  523.     case 'i':
  524.       strcpy(scope,optarg);
  525.       strupper(scope);
  526.       break;
  527.     case 'D':
  528.       is_daemon = True;
  529.       break;
  530.     case 'd':
  531.       DEBUGLEVEL = atoi(optarg);
  532.       break;
  533.     case 'p':
  534.       port = atoi(optarg);
  535.       break;
  536.     case 'h':
  537.       usage(argv[0]);
  538.       exit(0);
  539.       break;
  540.     default:
  541.       if (!is_a_socket(0)) {
  542.         usage(argv[0]);
  543.       }
  544.       break;
  545.     }
  546.     }
  547.  
  548.   DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
  549.   DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
  550.  
  551.   if(!get_myname(myhostname,NULL))
  552.   {
  553.     DEBUG(0,("Unable to get my hostname - exiting.\n"));
  554.     return -1;
  555.   }
  556.  
  557.   if (!reload_services(False))
  558.     return(-1);    
  559.  
  560.   codepage_initialise(lp_client_code_page());
  561.  
  562.   if(!init_structs())
  563.     return -1;
  564.  
  565.   reload_services(True);
  566.  
  567.   strcpy(myworkgroup, lp_workgroup());
  568.  
  569.   if (strequal(myworkgroup,"*")) {
  570.     DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
  571.     exit(1);
  572.   }
  573.  
  574.   set_samba_nb_type();
  575.  
  576.   if (!is_daemon && !is_a_socket(0)) {
  577.     DEBUG(0,("standard input is not a socket, assuming -D option\n"));
  578.     is_daemon = True;
  579.   }
  580.   
  581.   if (is_daemon) {
  582.     DEBUG(2,("%s becoming a daemon\n",timestring()));
  583.     become_daemon();
  584.   }
  585.  
  586.   if (*pidFile)
  587.     {
  588.       int     fd;
  589.       char    buf[20];
  590.  
  591.       if ((fd = open(pidFile,
  592. #ifdef O_NONBLOCK
  593.         O_NONBLOCK | 
  594. #endif
  595.         O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
  596.         {
  597.           DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
  598.           exit(1);
  599.         }
  600.       if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
  601.         {
  602.           DEBUG(0,("ERROR: nmbd is already running\n"));
  603.           exit(1);
  604.         }
  605.       sprintf(buf, "%u\n", (unsigned int) getpid());
  606.       if (write(fd, buf, strlen(buf)) < 0)
  607.         {
  608.           DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
  609.           exit(1);
  610.         }
  611.       /* Leave pid file open & locked for the duration... */
  612.     }
  613.  
  614.  
  615.   DEBUG(3,("Opening sockets %d\n", port));
  616.  
  617.   if (!open_sockets(is_daemon,port)) return 1;
  618.  
  619.   load_interfaces();
  620.   add_my_subnets(myworkgroup);
  621.  
  622.   add_my_names();
  623.  
  624.   DEBUG(3,("Checked names\n"));
  625.   
  626.   load_netbios_names();
  627.  
  628.   DEBUG(3,("Loaded names\n"));
  629.  
  630.   if (*host_file) {
  631.     load_hosts_file(host_file);
  632.     DEBUG(3,("Loaded hosts file\n"));
  633.   }
  634.  
  635.   write_browse_list(time(NULL));
  636.  
  637.   DEBUG(3,("Dumped names\n"));
  638.  
  639.   /* We can only take sigterm signals in the select. */
  640.   BlockSignals(True,SIGTERM);
  641.   process();
  642.   close_sockets();
  643.  
  644.   if (dbf)
  645.     fclose(dbf);
  646.   return(0);
  647. }
  648.