made "hide files" and "veto files" into per-service parameter sections,
[Samba.git] / source / nmbd / nmbd.c
blob75544535af2f3cb0f269bf1e51a53b8480ed6676
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;
45 /* are we running as a daemon ? */
46 static BOOL is_daemon = False;
48 /* what server type are we currently */
50 time_t StartupTime =0;
52 extern struct in_addr ipzero;
54 /****************************************************************************
55 catch a sigterm
56 ****************************************************************************/
57 static int sig_term()
59 BlockSignals(True,SIGTERM);
61 DEBUG(0,("Got SIGTERM: going down...\n"));
63 /* write out wins.dat file if samba is a WINS server */
64 dump_names();
66 /* remove all samba names, with wins server if necessary. */
67 remove_my_names();
69 /* announce all server entries as 0 time-to-live, 0 type */
70 /* XXXX don't care if we never receive a response back... yet */
71 announce_my_servers_removed();
73 /* XXXX other things: if we are a master browser, force an election? */
75 exit(0);
76 /* Keep compiler happy.. */
77 return 0;
81 /****************************************************************************
82 catch a sighup
83 ****************************************************************************/
84 static int sig_hup(void)
86 BlockSignals(True,SIGHUP);
88 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
89 dump_names();
90 reload_services(True);
92 set_samba_nb_type();
94 BlockSignals(False,SIGHUP);
95 #ifndef DONT_REINSTALL_SIG
96 signal(SIGHUP,SIGNAL_CAST sig_hup);
97 #endif
98 return(0);
101 /****************************************************************************
102 catch a sigpipe
103 ****************************************************************************/
104 static int sig_pipe(void)
106 BlockSignals(True,SIGPIPE);
108 DEBUG(0,("Got SIGPIPE\n"));
109 if (!is_daemon)
110 exit(1);
111 BlockSignals(False,SIGPIPE);
112 return(0);
115 #if DUMP_CORE
116 /*******************************************************************
117 prepare to dump a core file - carefully!
118 ********************************************************************/
119 static BOOL dump_core(void)
121 char *p;
122 pstring dname;
123 strcpy(dname,debugf);
124 if ((p=strrchr(dname,'/'))) *p=0;
125 strcat(dname,"/corefiles");
126 mkdir(dname,0700);
127 sys_chown(dname,getuid(),getgid());
128 chmod(dname,0700);
129 if (chdir(dname)) return(False);
130 umask(~(0700));
132 #ifndef NO_GETRLIMIT
133 #ifdef RLIMIT_CORE
135 struct rlimit rlp;
136 getrlimit(RLIMIT_CORE, &rlp);
137 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
138 setrlimit(RLIMIT_CORE, &rlp);
139 getrlimit(RLIMIT_CORE, &rlp);
140 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
142 #endif
143 #endif
146 DEBUG(0,("Dumping core in %s\n",dname));
147 return(True);
149 #endif
152 /****************************************************************************
153 possibly continue after a fault
154 ****************************************************************************/
155 static void fault_continue(void)
157 #if DUMP_CORE
158 dump_core();
159 #endif
162 /*******************************************************************
163 expire old names from the namelist and server list
164 ******************************************************************/
165 static void expire_names_and_servers(time_t t)
167 static time_t lastrun = 0;
169 if (!lastrun) lastrun = t;
170 if (t < lastrun + 5) return;
171 lastrun = t;
173 expire_names(t);
174 expire_servers(t);
177 /*****************************************************************************
178 reload the services file
179 **************************************************************************/
180 BOOL reload_services(BOOL test)
182 BOOL ret;
183 extern fstring remote_machine;
185 strcpy(remote_machine,"nmbd");
187 if (lp_loaded())
189 pstring fname;
190 strcpy(fname,lp_configfile());
191 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
193 strcpy(servicesf,fname);
194 test = False;
198 if (test && !lp_file_list_changed())
199 return(True);
201 ret = lp_load(servicesf,True);
203 /* perhaps the config filename is now set */
204 if (!test) {
205 DEBUG(3,("services not loaded\n"));
206 reload_services(True);
209 /* Do a sanity check for a misconfigured nmbd */
210 if(lp_wins_support() && *lp_wins_server()) {
211 DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
212 cannot be set in the smb.conf file. nmbd aborting.\n"));
213 exit(10);
216 return(ret);
221 /****************************************************************************
222 load a netbios hosts file
223 ****************************************************************************/
224 static void load_hosts_file(char *fname)
226 FILE *f = fopen(fname,"r");
227 pstring line;
228 if (!f) {
229 DEBUG(2,("Can't open lmhosts file %s\n",fname));
230 return;
233 while (!feof(f))
235 pstring ip,name,flags,extra;
236 struct subnet_record *d;
237 char *ptr;
238 int count = 0;
239 struct in_addr ipaddr;
240 enum name_source source = LMHOSTS;
242 if (!fgets_slash(line,sizeof(pstring),f)) continue;
244 if (*line == '#') continue;
246 strcpy(ip,"");
247 strcpy(name,"");
248 strcpy(flags,"");
250 ptr = line;
252 if (next_token(&ptr,ip ,NULL)) ++count;
253 if (next_token(&ptr,name ,NULL)) ++count;
254 if (next_token(&ptr,flags,NULL)) ++count;
255 if (next_token(&ptr,extra,NULL)) ++count;
257 if (count <= 0) continue;
259 if (count > 0 && count < 2) {
260 DEBUG(0,("Ill formed hosts line [%s]\n",line));
261 continue;
264 if (count >= 4) {
265 DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
266 continue;
269 DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
271 if (strchr(flags,'G') || strchr(flags,'S')) {
272 DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
273 continue;
276 if (strchr(flags,'M')) {
277 source = SELF;
278 strcpy(myname,name);
281 ipaddr = *interpret_addr2(ip);
282 d = find_subnet_all(ipaddr);
283 if (d) {
284 add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
285 add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
289 fclose(f);
293 /****************************************************************************
294 The main select loop.
295 ***************************************************************************/
296 static void process(void)
298 BOOL run_election;
300 while (True)
302 time_t t = time(NULL);
303 run_election = check_elections();
304 listen_for_packets(run_election);
306 run_packet_queue();
307 run_elections(t);
309 announce_host(t);
310 announce_master(t);
311 announce_remote(t);
313 query_refresh_names(t);
315 expire_names_and_servers(t);
316 expire_netbios_response_entries(t);
317 refresh_my_names(t);
319 write_browse_list(t);
320 do_browser_lists(t);
321 check_master_browser(t);
322 add_domain_names(t);
327 /****************************************************************************
328 open the socket communication
329 ****************************************************************************/
330 static BOOL open_sockets(BOOL isdaemon, int port)
332 struct hostent *hp;
334 /* get host info */
335 if ((hp = Get_Hostbyname(myhostname)) == 0) {
336 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
337 return False;
340 if (isdaemon)
341 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
342 else
343 ClientNMB = 0;
345 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
347 if (ClientNMB == -1)
348 return(False);
350 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
352 set_socket_options(ClientNMB,"SO_BROADCAST");
353 set_socket_options(ClientDGRAM,"SO_BROADCAST");
355 DEBUG(3,("Sockets opened.\n"));
356 return True;
360 /****************************************************************************
361 initialise connect, service and file structs
362 ****************************************************************************/
363 static BOOL init_structs()
365 extern fstring local_machine;
366 char *p;
368 if (! *myname) {
369 strcpy(myname,myhostname);
370 p = strchr(myname,'.');
371 if (p) *p = 0;
373 strupper(myname);
375 strcpy(local_machine,myname);
376 trim_string(local_machine," "," ");
377 p = strchr(local_machine,' ');
378 if (p) *p = 0;
379 strlower(local_machine);
381 return True;
384 /****************************************************************************
385 usage on the program
386 ****************************************************************************/
387 static void usage(char *pname)
389 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
391 printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
392 printf("Version %s\n",VERSION);
393 printf("\t-D become a daemon\n");
394 printf("\t-p port listen on the specified port\n");
395 printf("\t-d debuglevel set the debuglevel\n");
396 printf("\t-l log basename. Basename for log/debug files\n");
397 printf("\t-n netbiosname. the netbios name to advertise for this host\n");
398 printf("\t-H hosts file load a netbios hosts file\n");
399 printf("\n");
403 /****************************************************************************
404 main program
405 **************************************************************************/
406 int main(int argc,char *argv[])
408 int port = NMB_PORT;
409 int opt;
410 extern FILE *dbf;
411 extern char *optarg;
412 char pidFile[100] = { 0 };
414 *host_file = 0;
416 StartupTime = time(NULL);
418 TimeInit();
420 strcpy(debugf,NMBLOGFILE);
422 setup_logging(argv[0],False);
424 charset_initialise(-1);
426 #ifdef LMHOSTSFILE
427 strcpy(host_file,LMHOSTSFILE);
428 #endif
430 /* this is for people who can't start the program correctly */
431 while (argc > 1 && (*argv[1] != '-')) {
432 argv++;
433 argc--;
436 fault_setup(fault_continue);
438 signal(SIGHUP ,SIGNAL_CAST sig_hup);
439 signal(SIGTERM,SIGNAL_CAST sig_term);
441 while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
443 switch (opt)
445 case 'f':
446 strncpy(pidFile, optarg, sizeof(pidFile));
447 break;
448 case 's':
449 strcpy(servicesf,optarg);
450 break;
451 case 'N':
452 case 'B':
453 case 'I':
454 case 'C':
455 case 'G':
456 DEBUG(0,("Obsolete option '%c' used\n",opt));
457 break;
458 case 'H':
459 strcpy(host_file,optarg);
460 break;
461 case 'n':
462 strcpy(myname,optarg);
463 strupper(myname);
464 break;
465 case 'l':
466 sprintf(debugf,"%s.nmb",optarg);
467 break;
468 case 'i':
469 strcpy(scope,optarg);
470 strupper(scope);
471 break;
472 case 'D':
473 is_daemon = True;
474 break;
475 case 'd':
476 DEBUGLEVEL = atoi(optarg);
477 break;
478 case 'p':
479 port = atoi(optarg);
480 break;
481 case 'h':
482 usage(argv[0]);
483 exit(0);
484 break;
485 default:
486 if (!is_a_socket(0)) {
487 usage(argv[0]);
489 break;
493 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
494 DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
496 get_myname(myhostname,NULL);
498 if (!reload_services(False))
499 return(-1);
501 charset_initialise(lp_client_code_page());
503 init_structs();
505 reload_services(True);
507 strcpy(myworkgroup, lp_workgroup());
509 if (strequal(myworkgroup,"*")) {
510 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
511 exit(1);
514 set_samba_nb_type();
516 if (!is_daemon && !is_a_socket(0)) {
517 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
518 is_daemon = True;
521 if (is_daemon) {
522 DEBUG(2,("%s becoming a daemon\n",timestring()));
523 become_daemon();
526 if (*pidFile)
528 int fd;
529 char buf[20];
531 if ((fd = open(pidFile,
532 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
534 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
535 exit(1);
537 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
539 DEBUG(0,("ERROR: nmbd is already running\n"));
540 exit(1);
542 sprintf(buf, "%u\n", (unsigned int) getpid());
543 if (write(fd, buf, strlen(buf)) < 0)
545 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
546 exit(1);
548 /* Leave pid file open & locked for the duration... */
552 DEBUG(3,("Opening sockets %d\n", port));
554 if (!open_sockets(is_daemon,port)) return 1;
556 load_interfaces();
557 add_my_subnets(myworkgroup);
559 add_my_names();
561 DEBUG(3,("Checked names\n"));
563 load_netbios_names();
565 DEBUG(3,("Loaded names\n"));
567 if (*host_file) {
568 load_hosts_file(host_file);
569 DEBUG(3,("Loaded hosts file\n"));
572 write_browse_list(time(NULL));
574 DEBUG(3,("Dumped names\n"));
576 /* We can only take sigterm signals in the select. */
577 BlockSignals(True,SIGTERM);
578 process();
579 close_sockets();
581 if (dbf)
582 fclose(dbf);
583 return(0);