2 Unix SMB/Netbios implementation.
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.
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
30 extern int DEBUGLEVEL;
32 extern pstring debugf;
33 pstring servicesf = CONFIGFILE;
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 /****************************************************************************
56 ****************************************************************************/
59 BlockSignals(True,SIGTERM);
61 DEBUG(0,("Got SIGTERM: going down...\n"));
63 /* write out wins.dat file if samba is a WINS server */
66 /* remove all samba names, with wins server if necessary. */
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? */
79 /****************************************************************************
81 ****************************************************************************/
82 static int sig_hup(void)
84 BlockSignals(True,SIGHUP);
86 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
88 reload_services(True);
92 BlockSignals(False,SIGHUP);
93 #ifndef DONT_REINSTALL_SIG
94 signal(SIGHUP,SIGNAL_CAST sig_hup);
99 /****************************************************************************
101 ****************************************************************************/
102 static int sig_pipe(void)
104 BlockSignals(True,SIGPIPE);
106 DEBUG(0,("Got SIGPIPE\n"));
109 BlockSignals(False,SIGPIPE);
114 /*******************************************************************
115 prepare to dump a core file - carefully!
116 ********************************************************************/
117 static BOOL dump_core(void)
121 strcpy(dname,debugf);
122 if ((p=strrchr(dname,'/'))) *p=0;
123 strcat(dname,"/corefiles");
125 sys_chown(dname,getuid(),getgid());
127 if (chdir(dname)) return(False);
134 getrlimit(RLIMIT_CORE, &rlp);
135 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
136 setrlimit(RLIMIT_CORE, &rlp);
137 getrlimit(RLIMIT_CORE, &rlp);
138 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
144 DEBUG(0,("Dumping core in %s\n",dname));
150 /****************************************************************************
151 possibly continue after a fault
152 ****************************************************************************/
153 static void fault_continue(void)
160 /*******************************************************************
161 expire old names from the namelist and server list
162 ******************************************************************/
163 static void expire_names_and_servers(time_t t)
165 static time_t lastrun = 0;
167 if (!lastrun) lastrun = t;
168 if (t < lastrun + 5) return;
175 /*****************************************************************************
176 reload the services file
177 **************************************************************************/
178 BOOL reload_services(BOOL test)
181 extern fstring remote_machine;
183 strcpy(remote_machine,"nmbd");
188 strcpy(fname,lp_configfile());
189 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
191 strcpy(servicesf,fname);
196 if (test && !lp_file_list_changed())
199 ret = lp_load(servicesf,True);
201 /* perhaps the config filename is now set */
203 DEBUG(3,("services not loaded\n"));
204 reload_services(True);
207 /* Do a sanity check for a misconfigured nmbd */
208 if(lp_wins_support() && *lp_wins_server()) {
209 DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
210 cannot be set in the smb.conf file. nmbd aborting.\n"));
219 /****************************************************************************
220 load a netbios hosts file
221 ****************************************************************************/
222 static void load_hosts_file(char *fname)
224 FILE *f = fopen(fname,"r");
227 DEBUG(2,("Can't open lmhosts file %s\n",fname));
233 pstring ip,name,flags,extra;
234 struct subnet_record *d;
237 struct in_addr ipaddr;
238 enum name_source source = LMHOSTS;
240 if (!fgets_slash(line,sizeof(pstring),f)) continue;
242 if (*line == '#') continue;
250 if (next_token(&ptr,ip ,NULL)) ++count;
251 if (next_token(&ptr,name ,NULL)) ++count;
252 if (next_token(&ptr,flags,NULL)) ++count;
253 if (next_token(&ptr,extra,NULL)) ++count;
255 if (count <= 0) continue;
257 if (count > 0 && count < 2) {
258 DEBUG(0,("Ill formed hosts line [%s]\n",line));
263 DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
267 DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
269 if (strchr(flags,'G') || strchr(flags,'S')) {
270 DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
274 if (strchr(flags,'M')) {
279 ipaddr = *interpret_addr2(ip);
280 d = find_subnet_all(ipaddr);
282 add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
283 add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
291 /****************************************************************************
292 The main select loop.
293 ***************************************************************************/
294 static void process(void)
300 time_t t = time(NULL);
301 run_election = check_elections();
302 listen_for_packets(run_election);
311 query_refresh_names(t);
313 expire_names_and_servers(t);
314 expire_netbios_response_entries(t);
317 write_browse_list(t);
319 check_master_browser(t);
325 /****************************************************************************
326 open the socket communication
327 ****************************************************************************/
328 static BOOL open_sockets(BOOL isdaemon, int port)
333 if ((hp = Get_Hostbyname(myhostname)) == 0) {
334 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
339 ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
343 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
348 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
350 set_socket_options(ClientNMB,"SO_BROADCAST");
351 set_socket_options(ClientDGRAM,"SO_BROADCAST");
353 DEBUG(3,("Sockets opened.\n"));
358 /****************************************************************************
359 initialise connect, service and file structs
360 ****************************************************************************/
361 static BOOL init_structs()
363 extern fstring local_machine;
367 strcpy(myname,myhostname);
368 p = strchr(myname,'.');
373 strcpy(local_machine,myname);
374 trim_string(local_machine," "," ");
375 p = strchr(local_machine,' ');
377 strlower(local_machine);
382 /****************************************************************************
384 ****************************************************************************/
385 static void usage(char *pname)
387 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
389 printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
390 printf("Version %s\n",VERSION);
391 printf("\t-D become a daemon\n");
392 printf("\t-p port listen on the specified port\n");
393 printf("\t-d debuglevel set the debuglevel\n");
394 printf("\t-l log basename. Basename for log/debug files\n");
395 printf("\t-n netbiosname. the netbios name to advertise for this host\n");
396 printf("\t-H hosts file load a netbios hosts file\n");
401 /****************************************************************************
403 **************************************************************************/
404 int main(int argc,char *argv[])
410 char pidFile[100] = { 0 };
414 StartupTime = time(NULL);
418 strcpy(debugf,NMBLOGFILE);
420 setup_logging(argv[0],False);
422 charset_initialise();
425 strcpy(host_file,LMHOSTSFILE);
428 /* this is for people who can't start the program correctly */
429 while (argc > 1 && (*argv[1] != '-')) {
434 fault_setup(fault_continue);
436 signal(SIGHUP ,SIGNAL_CAST sig_hup);
437 signal(SIGTERM,SIGNAL_CAST sig_term);
439 while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
444 strncpy(pidFile, optarg, sizeof(pidFile));
447 strcpy(servicesf,optarg);
454 DEBUG(0,("Obsolete option '%c' used\n",opt));
457 strcpy(host_file,optarg);
460 strcpy(myname,optarg);
464 sprintf(debugf,"%s.nmb",optarg);
467 strcpy(scope,optarg);
474 DEBUGLEVEL = atoi(optarg);
484 if (!is_a_socket(0)) {
491 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
492 DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
494 get_myname(myhostname,NULL);
496 if (!reload_services(False))
501 reload_services(True);
503 strcpy(myworkgroup, lp_workgroup());
507 if (!is_daemon && !is_a_socket(0)) {
508 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
513 DEBUG(2,("%s becoming a daemon\n",timestring()));
522 if ((fd = open(pidFile,
523 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
525 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
528 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
530 DEBUG(0,("ERROR: nmbd is already running\n"));
533 sprintf(buf, "%u\n", (unsigned int) getpid());
534 if (write(fd, buf, strlen(buf)) < 0)
536 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
539 /* Leave pid file open & locked for the duration... */
543 DEBUG(3,("Opening sockets %d\n", port));
545 if (!open_sockets(is_daemon,port)) return 1;
548 load_hosts_file(host_file);
549 DEBUG(3,("Loaded hosts file\n"));
553 add_my_subnets(myworkgroup);
557 if (strequal(myworkgroup,"*")) {
558 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
562 DEBUG(3,("Checked names\n"));
564 load_netbios_names();
566 DEBUG(3,("Loaded names\n"));
568 write_browse_list(time(NULL));
570 DEBUG(3,("Dumped names\n"));