updated to include NT 4.0 Workstation profile setup.
[Samba.git] / source / nmbd / nmbd.c
blob925f975ffef48b5b2a45eb9b9bd3dd76af90799f
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;
40 extern pstring myhostname;
41 static pstring host_file;
42 extern pstring myname;
43 extern fstring myworkgroup;
44 extern char **my_netbios_names;
46 /* are we running as a daemon ? */
47 static BOOL is_daemon = False;
49 /* what server type are we currently */
51 time_t StartupTime =0;
53 extern struct in_addr ipzero;
55 /****************************************************************************
56 catch a sigterm
57 ****************************************************************************/
58 static int sig_term()
60 BlockSignals(True,SIGTERM);
62 DEBUG(0,("Got SIGTERM: going down...\n"));
64 /* write out wins.dat file if samba is a WINS server */
65 dump_names();
67 /* remove all samba names, with wins server if necessary. */
68 remove_my_names();
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();
74 /* XXXX other things: if we are a master browser, force an election? */
76 exit(0);
77 /* Keep compiler happy.. */
78 return 0;
82 /****************************************************************************
83 catch a sighup
84 ****************************************************************************/
85 static int sig_hup(void)
87 BlockSignals(True,SIGHUP);
89 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
90 dump_names();
91 reload_services(True);
93 set_samba_nb_type();
95 BlockSignals(False,SIGHUP);
96 #ifndef DONT_REINSTALL_SIG
97 signal(SIGHUP,SIGNAL_CAST sig_hup);
98 #endif
99 return(0);
102 /****************************************************************************
103 catch a sigpipe
104 ****************************************************************************/
105 static int sig_pipe(void)
107 BlockSignals(True,SIGPIPE);
109 DEBUG(0,("Got SIGPIPE\n"));
110 if (!is_daemon)
111 exit(1);
112 BlockSignals(False,SIGPIPE);
113 return(0);
116 #if DUMP_CORE
117 /*******************************************************************
118 prepare to dump a core file - carefully!
119 ********************************************************************/
120 static BOOL dump_core(void)
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));
133 #ifndef NO_GETRLIMIT
134 #ifdef RLIMIT_CORE
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));
143 #endif
144 #endif
147 DEBUG(0,("Dumping core in %s\n",dname));
148 return(True);
150 #endif
153 /****************************************************************************
154 possibly continue after a fault
155 ****************************************************************************/
156 static void fault_continue(void)
158 #if DUMP_CORE
159 dump_core();
160 #endif
163 /*******************************************************************
164 expire old names from the namelist and server list
165 ******************************************************************/
166 static void expire_names_and_servers(time_t t)
168 static time_t lastrun = 0;
170 if (!lastrun) lastrun = t;
171 if (t < lastrun + 5) return;
172 lastrun = t;
174 expire_names(t);
175 expire_servers(t);
178 /*****************************************************************************
179 reload the services file
180 **************************************************************************/
181 BOOL reload_services(BOOL test)
183 BOOL ret;
184 extern fstring remote_machine;
186 strcpy(remote_machine,"nmbd");
188 if (lp_loaded())
190 pstring fname;
191 strcpy(fname,lp_configfile());
192 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
194 strcpy(servicesf,fname);
195 test = False;
199 if (test && !lp_file_list_changed())
200 return(True);
202 ret = lp_load(servicesf,True);
204 /* perhaps the config filename is now set */
205 if (!test) {
206 DEBUG(3,("services not loaded\n"));
207 reload_services(True);
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);
217 return(ret);
222 /****************************************************************************
223 load a netbios hosts file
224 ****************************************************************************/
225 static void load_hosts_file(char *fname)
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;
234 while (!feof(f))
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;
243 if (!fgets_slash(line,sizeof(pstring),f)) continue;
245 if (*line == '#') continue;
247 strcpy(ip,"");
248 strcpy(name,"");
249 strcpy(flags,"");
251 ptr = line;
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;
258 if (count <= 0) continue;
260 if (count > 0 && count < 2) {
261 DEBUG(0,("Ill formed hosts line [%s]\n",line));
262 continue;
265 if (count >= 4) {
266 DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
267 continue;
270 DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
272 if (strchr(flags,'G') || strchr(flags,'S')) {
273 DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
274 continue;
277 if (strchr(flags,'M')) {
278 source = SELF;
279 strcpy(myname,name);
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);
290 fclose(f);
294 /****************************************************************************
295 The main select loop.
296 ***************************************************************************/
297 static void process(void)
299 BOOL run_election;
301 while (True)
303 time_t t = time(NULL);
304 run_election = check_elections();
305 listen_for_packets(run_election);
307 run_packet_queue();
308 run_elections(t);
310 announce_host(t);
311 announce_master(t);
312 announce_remote(t);
314 query_refresh_names(t);
316 expire_names_and_servers(t);
317 expire_netbios_response_entries(t);
318 refresh_my_names(t);
320 write_browse_list(t);
321 do_browser_lists(t);
322 check_master_browser(t);
323 add_domain_names(t);
328 /****************************************************************************
329 open the socket communication
330 ****************************************************************************/
331 static BOOL open_sockets(BOOL isdaemon, int port)
333 struct hostent *hp;
335 /* get host info */
336 if ((hp = Get_Hostbyname(myhostname)) == 0) {
337 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
338 return False;
341 if (isdaemon)
342 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
343 else
344 ClientNMB = 0;
346 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
348 if (ClientNMB == -1)
349 return(False);
351 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
353 set_socket_options(ClientNMB,"SO_BROADCAST");
354 set_socket_options(ClientDGRAM,"SO_BROADCAST");
356 DEBUG(3,("Sockets opened.\n"));
357 return True;
361 /****************************************************************************
362 initialise connect, service and file structs
363 ****************************************************************************/
364 static BOOL init_structs()
366 extern fstring local_machine;
367 char *p, *ptr;
368 int namecount;
369 int n;
370 int nodup;
371 pstring nbname;
373 if (! *myname) {
374 strcpy(myname,myhostname);
375 p = strchr(myname,'.');
376 if (p) *p = 0;
378 strupper(myname);
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++)
386 if (*myname)
387 namecount++;
389 /* Allocate space for the netbios aliases */
390 if((my_netbios_names=(char **)malloc(sizeof(char *)*(namecount+1))) == NULL)
392 DEBUG(0,("init_structs: malloc fail.\n"));
393 return False;
396 /* Use the myname string first */
397 namecount=0;
398 if (*myname)
399 my_netbios_names[namecount++] = myname;
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;
410 if (nodup)
411 my_netbios_names[namecount++]=strdup(nbname);
414 /* Check the strdups succeeded. */
415 for(n = 0; n < namecount; n++)
416 if(my_netbios_names[n]==NULL)
418 DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
419 return False;
422 /* Terminate name list */
423 my_netbios_names[namecount++]=NULL;
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);
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]));
436 return True;
439 /****************************************************************************
440 usage on the program
441 ****************************************************************************/
442 static void usage(char *pname)
444 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
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");
458 /****************************************************************************
459 main program
460 **************************************************************************/
461 int main(int argc,char *argv[])
463 int port = NMB_PORT;
464 int opt;
465 extern FILE *dbf;
466 extern char *optarg;
467 char pidFile[100] = { 0 };
469 *host_file = 0;
471 StartupTime = time(NULL);
473 TimeInit();
475 strcpy(debugf,NMBLOGFILE);
477 setup_logging(argv[0],False);
479 charset_initialise();
481 #ifdef LMHOSTSFILE
482 strcpy(host_file,LMHOSTSFILE);
483 #endif
485 /* this is for people who can't start the program correctly */
486 while (argc > 1 && (*argv[1] != '-')) {
487 argv++;
488 argc--;
491 fault_setup(fault_continue);
493 signal(SIGHUP ,SIGNAL_CAST sig_hup);
494 signal(SIGTERM,SIGNAL_CAST sig_term);
496 while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
498 switch (opt)
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]);
544 break;
548 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
549 DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
551 if(!get_myname(myhostname,NULL))
553 DEBUG(0,("Unable to get my hostname - exiting.\n"));
554 return -1;
557 if (!reload_services(False))
558 return(-1);
560 codepage_initialise(lp_client_code_page());
562 if(!init_structs())
563 return -1;
565 reload_services(True);
567 strcpy(myworkgroup, lp_workgroup());
569 if (strequal(myworkgroup,"*")) {
570 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
571 exit(1);
574 set_samba_nb_type();
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;
581 if (is_daemon) {
582 DEBUG(2,("%s becoming a daemon\n",timestring()));
583 become_daemon();
586 if (*pidFile)
588 int fd;
589 char buf[20];
591 if ((fd = open(pidFile,
592 #ifdef O_NONBLOCK
593 O_NONBLOCK |
594 #endif
595 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
597 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
598 exit(1);
600 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
602 DEBUG(0,("ERROR: nmbd is already running\n"));
603 exit(1);
605 sprintf(buf, "%u\n", (unsigned int) getpid());
606 if (write(fd, buf, strlen(buf)) < 0)
608 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
609 exit(1);
611 /* Leave pid file open & locked for the duration... */
615 DEBUG(3,("Opening sockets %d\n", port));
617 if (!open_sockets(is_daemon,port)) return 1;
619 load_interfaces();
620 add_my_subnets(myworkgroup);
622 add_my_names();
624 DEBUG(3,("Checked names\n"));
626 load_netbios_names();
628 DEBUG(3,("Loaded names\n"));
630 if (*host_file) {
631 load_hosts_file(host_file);
632 DEBUG(3,("Loaded hosts file\n"));
635 write_browse_list(time(NULL));
637 DEBUG(3,("Dumped names\n"));
639 /* We can only take sigterm signals in the select. */
640 BlockSignals(True,SIGTERM);
641 process();
642 close_sockets();
644 if (dbf)
645 fclose(dbf);
646 return(0);