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