minor async DNS cleanups
[Samba.git] / source / nmbd / nmbd.c
blob696889c4844a4932e8bcb81ec66ad5251007a956
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
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.
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.
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.
21 Revision History:
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
28 #include "includes.h"
30 extern int DEBUGLEVEL;
32 extern pstring debugf;
33 pstring servicesf = CONFIGFILE;
35 extern pstring scope;
37 int ClientNMB = -1;
38 int ClientDGRAM = -1;
39 int global_nmb_port = -1;
41 extern pstring myhostname;
42 static pstring host_file;
43 extern pstring myname;
44 extern fstring myworkgroup;
45 extern char **my_netbios_names;
47 /* are we running as a daemon ? */
48 static BOOL is_daemon = False;
50 /* what server type are we currently */
52 time_t StartupTime =0;
54 extern struct in_addr ipzero;
56 /****************************************************************************
57 catch a sigterm
58 ****************************************************************************/
59 static int sig_term()
61 BlockSignals(True,SIGTERM);
63 DEBUG(0,("Got SIGTERM: going down...\n"));
65 /* write out wins.dat file if samba is a WINS server */
66 dump_names();
68 /* remove all samba names, with wins server if necessary. */
69 remove_my_names();
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();
75 /* XXXX other things: if we are a master browser, force an election? */
77 exit(0);
78 /* Keep compiler happy.. */
79 return 0;
83 /****************************************************************************
84 catch a sighup
85 ****************************************************************************/
86 static int sig_hup(void)
88 BlockSignals(True,SIGHUP);
90 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
91 dump_names();
92 reload_services(True);
94 set_samba_nb_type();
96 BlockSignals(False,SIGHUP);
97 #ifndef DONT_REINSTALL_SIG
98 signal(SIGHUP,SIGNAL_CAST sig_hup);
99 #endif
100 return(0);
103 /****************************************************************************
104 catch a sigpipe
105 ****************************************************************************/
106 static int sig_pipe(void)
108 BlockSignals(True,SIGPIPE);
110 DEBUG(0,("Got SIGPIPE\n"));
111 if (!is_daemon)
112 exit(1);
113 BlockSignals(False,SIGPIPE);
114 return(0);
117 #if DUMP_CORE
118 /*******************************************************************
119 prepare to dump a core file - carefully!
120 ********************************************************************/
121 static BOOL dump_core(void)
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));
134 #ifndef NO_GETRLIMIT
135 #ifdef RLIMIT_CORE
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));
144 #endif
145 #endif
148 DEBUG(0,("Dumping core in %s\n",dname));
149 return(True);
151 #endif
154 /****************************************************************************
155 possibly continue after a fault
156 ****************************************************************************/
157 static void fault_continue(void)
159 #if DUMP_CORE
160 dump_core();
161 #endif
164 /*******************************************************************
165 expire old names from the namelist and server list
166 ******************************************************************/
167 static void expire_names_and_servers(time_t t)
169 static time_t lastrun = 0;
171 if (!lastrun) lastrun = t;
172 if (t < lastrun + 5) return;
173 lastrun = t;
175 expire_names(t);
176 expire_servers(t);
179 /*****************************************************************************
180 reload the services file
181 **************************************************************************/
182 BOOL reload_services(BOOL test)
184 BOOL ret;
185 extern fstring remote_machine;
187 strcpy(remote_machine,"nmbd");
189 if (lp_loaded())
191 pstring fname;
192 pstrcpy(fname,lp_configfile());
193 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
195 pstrcpy(servicesf,fname);
196 test = False;
200 if (test && !lp_file_list_changed())
201 return(True);
203 ret = lp_load(servicesf,True);
205 /* perhaps the config filename is now set */
206 if (!test) {
207 DEBUG(3,("services not loaded\n"));
208 reload_services(True);
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);
218 return(ret);
223 /****************************************************************************
224 load a netbios hosts file
225 ****************************************************************************/
226 static void load_hosts_file(char *fname)
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;
235 while (!feof(f))
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;
244 if (!fgets_slash(line,sizeof(pstring),f)) continue;
246 if (*line == '#') continue;
248 strcpy(ip,"");
249 strcpy(name,"");
250 strcpy(flags,"");
252 ptr = line;
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;
259 if (count <= 0) continue;
261 if (count > 0 && count < 2) {
262 DEBUG(0,("Ill formed hosts line [%s]\n",line));
263 continue;
266 if (count >= 4) {
267 DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
268 continue;
271 DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
273 if (strchr(flags,'G') || strchr(flags,'S')) {
274 DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
275 continue;
278 if (strchr(flags,'M')) {
279 source = SELF;
280 pstrcpy(myname,name);
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);
287 add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True);
291 fclose(f);
295 /****************************************************************************
296 The main select loop.
297 ***************************************************************************/
298 static void process(void)
300 BOOL run_election;
302 while (True)
304 time_t t = time(NULL);
305 run_election = check_elections();
306 if(listen_for_packets(run_election))
307 return;
309 run_packet_queue();
310 run_elections(t);
312 announce_host(t);
313 announce_master(t);
314 announce_remote(t);
316 query_refresh_names(t);
318 expire_names_and_servers(t);
319 expire_netbios_response_entries(t);
320 refresh_my_names(t);
322 write_browse_list(t);
323 do_browser_lists(t);
324 check_master_browser(t);
325 add_domain_names(t);
330 /****************************************************************************
331 open the socket communication
332 ****************************************************************************/
333 static BOOL open_sockets(BOOL isdaemon, int port)
335 /* The sockets opened here will be used to receive broadcast
336 packets *only*. Interface specific sockets are opened in
337 make_subnet() in namedbsubnet.c. Thus we bind to the
338 address "0.0.0.0". The parameter 'socket address' is
339 now deprecated.
342 if (isdaemon)
343 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
344 else
345 ClientNMB = 0;
347 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0);
349 if (ClientNMB == -1)
350 return(False);
352 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
354 set_socket_options(ClientNMB,"SO_BROADCAST");
355 set_socket_options(ClientDGRAM,"SO_BROADCAST");
357 DEBUG(3,("open_sockets: Broadcast sockets opened.\n"));
358 return True;
362 /****************************************************************************
363 initialise connect, service and file structs
364 ****************************************************************************/
365 static BOOL init_structs()
367 extern fstring local_machine;
368 char *p, *ptr;
369 int namecount;
370 int n;
371 int nodup;
372 pstring nbname;
374 if (! *myname) {
375 fstrcpy(myname,myhostname);
376 p = strchr(myname,'.');
377 if (p) *p = 0;
379 strupper(myname);
381 /* Add any NETBIOS name aliases. Ensure that the first entry
382 is equal to myname. */
383 /* Work out the max number of netbios aliases that we have */
384 ptr=lp_netbios_aliases();
385 for (namecount=0; next_token(&ptr,nbname,NULL); namecount++)
387 if (*myname)
388 namecount++;
390 /* Allocate space for the netbios aliases */
391 if((my_netbios_names=(char **)malloc(sizeof(char *)*(namecount+1))) == NULL)
393 DEBUG(0,("init_structs: malloc fail.\n"));
394 return False;
397 /* Use the myname string first */
398 namecount=0;
399 if (*myname)
400 my_netbios_names[namecount++] = myname;
402 ptr=lp_netbios_aliases();
403 while (next_token(&ptr,nbname,NULL)) {
404 strupper(nbname);
405 /* Look for duplicates */
406 nodup=1;
407 for(n=0; n<namecount; n++) {
408 if (strcmp(nbname, my_netbios_names[n])==0)
409 nodup=0;
411 if (nodup)
412 my_netbios_names[namecount++]=strdup(nbname);
415 /* Check the strdups succeeded. */
416 for(n = 0; n < namecount; n++)
417 if(my_netbios_names[n]==NULL)
419 DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
420 return False;
423 /* Terminate name list */
424 my_netbios_names[namecount++]=NULL;
426 fstrcpy(local_machine,myname);
427 trim_string(local_machine," "," ");
428 p = strchr(local_machine,' ');
429 if (p)
430 *p = 0;
431 strlower(local_machine);
433 DEBUG(5, ("Netbios name list:-\n"));
434 for (n=0; my_netbios_names[n]; n++)
435 DEBUG(5, ("my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n]));
437 return True;
440 /****************************************************************************
441 usage on the program
442 ****************************************************************************/
443 static void usage(char *pname)
445 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
447 printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
448 printf("Version %s\n",VERSION);
449 printf("\t-D become a daemon\n");
450 printf("\t-p port listen on the specified port\n");
451 printf("\t-d debuglevel set the debuglevel\n");
452 printf("\t-l log basename. Basename for log/debug files\n");
453 printf("\t-n netbiosname. the netbios name to advertise for this host\n");
454 printf("\t-H hosts file load a netbios hosts file\n");
455 printf("\n");
459 /****************************************************************************
460 main program
461 **************************************************************************/
462 int main(int argc,char *argv[])
464 int opt;
465 extern FILE *dbf;
466 extern char *optarg;
467 char pidFile[100] = { 0 };
469 global_nmb_port = NMB_PORT;
470 *host_file = 0;
472 StartupTime = time(NULL);
474 TimeInit();
476 strcpy(debugf,NMBLOGFILE);
478 setup_logging(argv[0],False);
480 charset_initialise();
482 #ifdef LMHOSTSFILE
483 strcpy(host_file,LMHOSTSFILE);
484 #endif
486 /* this is for people who can't start the program correctly */
487 while (argc > 1 && (*argv[1] != '-')) {
488 argv++;
489 argc--;
492 fault_setup(fault_continue);
494 signal(SIGHUP ,SIGNAL_CAST sig_hup);
495 signal(SIGTERM,SIGNAL_CAST sig_term);
497 while ((opt = getopt(argc, argv, "as:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
499 switch (opt)
501 case 'f':
502 strncpy(pidFile, optarg, sizeof(pidFile));
503 break;
504 case 's':
505 pstrcpy(servicesf,optarg);
506 break;
507 case 'N':
508 case 'B':
509 case 'I':
510 case 'C':
511 case 'G':
512 DEBUG(0,("Obsolete option '%c' used\n",opt));
513 break;
514 case 'H':
515 pstrcpy(host_file,optarg);
516 break;
517 case 'n':
518 pstrcpy(myname,optarg);
519 strupper(myname);
520 break;
521 case 'l':
522 sprintf(debugf,"%s.nmb",optarg);
523 break;
524 case 'i':
525 pstrcpy(scope,optarg);
526 strupper(scope);
527 break;
528 case 'a':
530 extern BOOL append_log;
531 append_log = !append_log;
533 break;
534 case 'D':
535 is_daemon = True;
536 break;
537 case 'd':
538 DEBUGLEVEL = atoi(optarg);
539 break;
540 case 'p':
541 global_nmb_port = atoi(optarg);
542 break;
543 case 'h':
544 usage(argv[0]);
545 exit(0);
546 break;
547 default:
548 if (!is_a_socket(0)) {
549 usage(argv[0]);
551 break;
555 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
556 DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
558 if(!get_myname(myhostname,NULL))
560 DEBUG(0,("Unable to get my hostname - exiting.\n"));
561 return -1;
564 #ifndef SYNC_DNS
565 start_async_dns();
566 #endif
568 if (!reload_services(False))
569 return(-1);
571 codepage_initialise(lp_client_code_page());
573 if(!init_structs())
574 return -1;
576 reload_services(True);
578 pstrcpy(myworkgroup, lp_workgroup());
580 if (strequal(myworkgroup,"*")) {
581 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
582 exit(1);
585 set_samba_nb_type();
587 if (!is_daemon && !is_a_socket(0)) {
588 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
589 is_daemon = True;
592 if (is_daemon) {
593 DEBUG(2,("%s becoming a daemon\n",timestring()));
594 become_daemon();
597 if (*pidFile)
599 int fd;
600 char buf[20];
602 if ((fd = open(pidFile,
603 #ifdef O_NONBLOCK
604 O_NONBLOCK |
605 #endif
606 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
608 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
609 exit(1);
611 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
613 DEBUG(0,("ERROR: nmbd is already running\n"));
614 exit(1);
616 sprintf(buf, "%u\n", (unsigned int) getpid());
617 if (write(fd, buf, strlen(buf)) < 0)
619 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
620 exit(1);
622 /* Leave pid file open & locked for the duration... */
626 DEBUG(3,("Opening sockets %d\n", global_nmb_port));
628 if (!open_sockets(is_daemon,global_nmb_port)) return 1;
630 load_interfaces();
631 add_my_subnets(myworkgroup);
633 add_my_names();
635 DEBUG(3,("Checked names\n"));
637 load_netbios_names();
639 DEBUG(3,("Loaded names\n"));
641 if (*host_file) {
642 load_hosts_file(host_file);
643 DEBUG(3,("Loaded hosts file\n"));
646 write_browse_list(time(NULL));
648 DEBUG(3,("Dumped names\n"));
650 /* We can only take sigterm signals in the select. */
651 BlockSignals(True,SIGTERM);
653 process();
654 close_sockets();
656 if (dbf)
657 fclose(dbf);
658 return(0);