2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1995
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
;
44 /* are we running as a daemon ? */
45 static BOOL is_daemon
= False
;
47 /* what server type are we currently */
49 time_t StartupTime
=0;
51 extern struct in_addr ipzero
;
53 /****************************************************************************
55 ****************************************************************************/
58 BlockSignals(True
,SIGTERM
);
60 DEBUG(0,("Got SIGTERM: going down...\n"));
62 /* write out wins.dat file if samba is a WINS server */
65 /* remove all samba names, with wins server if necessary. */
68 /* announce all server entries as 0 time-to-live, 0 type */
69 /* XXXX don't care if we never receive a response back... yet */
72 /* XXXX other things: if we are a master browser, force an election? */
78 /****************************************************************************
80 ****************************************************************************/
81 static int sig_hup(void)
83 BlockSignals(True
,SIGHUP
);
85 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
87 reload_services(True
);
91 BlockSignals(False
,SIGHUP
);
92 #ifndef DONT_REINSTALL_SIG
93 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
98 /****************************************************************************
100 ****************************************************************************/
101 static int sig_pipe(void)
103 BlockSignals(True
,SIGPIPE
);
105 DEBUG(0,("Got SIGPIPE\n"));
108 BlockSignals(False
,SIGPIPE
);
113 /*******************************************************************
114 prepare to dump a core file - carefully!
115 ********************************************************************/
116 static BOOL
dump_core(void)
120 strcpy(dname
,debugf
);
121 if ((p
=strrchr(dname
,'/'))) *p
=0;
122 strcat(dname
,"/corefiles");
124 sys_chown(dname
,getuid(),getgid());
126 if (chdir(dname
)) return(False
);
133 getrlimit(RLIMIT_CORE
, &rlp
);
134 rlp
.rlim_cur
= MAX(4*1024*1024,rlp
.rlim_cur
);
135 setrlimit(RLIMIT_CORE
, &rlp
);
136 getrlimit(RLIMIT_CORE
, &rlp
);
137 DEBUG(3,("Core limits now %d %d\n",rlp
.rlim_cur
,rlp
.rlim_max
));
143 DEBUG(0,("Dumping core in %s\n",dname
));
149 /****************************************************************************
150 possibly continue after a fault
151 ****************************************************************************/
152 static void fault_continue(void)
159 /*******************************************************************
160 expire old names from the namelist and server list
161 ******************************************************************/
162 static void expire_names_and_servers(time_t t
)
164 static time_t lastrun
= 0;
166 if (!lastrun
) lastrun
= t
;
167 if (t
< lastrun
+ 5) return;
174 /*****************************************************************************
175 reload the services file
176 **************************************************************************/
177 BOOL
reload_services(BOOL test
)
180 extern fstring remote_machine
;
182 strcpy(remote_machine
,"nmbd");
187 strcpy(fname
,lp_configfile());
188 if (file_exist(fname
,NULL
) && !strcsequal(fname
,servicesf
))
190 strcpy(servicesf
,fname
);
195 if (test
&& !lp_file_list_changed())
198 ret
= lp_load(servicesf
,True
);
200 /* perhaps the config filename is now set */
202 DEBUG(3,("services not loaded\n"));
203 reload_services(True
);
207 add_subnet_interfaces();
214 /****************************************************************************
215 load a netbios hosts file
216 ****************************************************************************/
217 static void load_hosts_file(char *fname
)
219 FILE *f
= fopen(fname
,"r");
222 DEBUG(2,("Can't open lmhosts file %s\n",fname
));
228 pstring ip
,name
,flags
,extra
;
229 struct subnet_record
*d
;
232 struct in_addr ipaddr
;
233 enum name_source source
= LMHOSTS
;
235 if (!fgets_slash(line
,sizeof(pstring
),f
)) continue;
237 if (*line
== '#') continue;
245 if (next_token(&ptr
,ip
,NULL
)) ++count
;
246 if (next_token(&ptr
,name
,NULL
)) ++count
;
247 if (next_token(&ptr
,flags
,NULL
)) ++count
;
248 if (next_token(&ptr
,extra
,NULL
)) ++count
;
250 if (count
<= 0) continue;
252 if (count
> 0 && count
< 2) {
253 DEBUG(0,("Ill formed hosts line [%s]\n",line
));
258 DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname
));
262 DEBUG(4, ("lmhost entry: %s %s %s\n", ip
, name
, flags
));
264 if (strchr(flags
,'G') || strchr(flags
,'S')) {
265 DEBUG(0,("group flag in %s ignored (obsolete)\n",fname
));
269 if (strchr(flags
,'M')) {
274 ipaddr
= *interpret_addr2(ip
);
275 d
= find_subnet_all(ipaddr
);
277 add_netbios_entry(d
,name
,0x00,NB_ACTIVE
,0,source
,ipaddr
,True
,True
);
278 add_netbios_entry(d
,name
,0x20,NB_ACTIVE
,0,source
,ipaddr
,True
,True
);
286 /****************************************************************************
287 The main select loop.
288 ***************************************************************************/
289 static void process(void)
295 time_t t
= time(NULL
);
296 run_election
= check_elections();
297 listen_for_packets(run_election
);
306 query_refresh_names(t
);
308 expire_names_and_servers(t
);
309 expire_netbios_response_entries(t
);
312 write_browse_list(t
);
314 check_master_browser(t
);
320 /****************************************************************************
321 open the socket communication
322 ****************************************************************************/
323 static BOOL
open_sockets(BOOL isdaemon
, int port
)
328 if ((hp
= Get_Hostbyname(myhostname
)) == 0) {
329 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname
));
334 ClientNMB
= open_socket_in(SOCK_DGRAM
, port
,0,interpret_addr(lp_socket_address()));
338 ClientDGRAM
= open_socket_in(SOCK_DGRAM
,DGRAM_PORT
,3,interpret_addr(lp_socket_address()));
343 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
345 set_socket_options(ClientNMB
,"SO_BROADCAST");
346 set_socket_options(ClientDGRAM
,"SO_BROADCAST");
348 DEBUG(3,("Sockets opened.\n"));
353 /****************************************************************************
354 initialise connect, service and file structs
355 ****************************************************************************/
356 static BOOL
init_structs()
358 extern fstring local_machine
;
362 strcpy(myname
,myhostname
);
363 p
= strchr(myname
,'.');
368 strcpy(local_machine
,myname
);
369 trim_string(local_machine
," "," ");
370 p
= strchr(local_machine
,' ');
372 strlower(local_machine
);
377 /****************************************************************************
379 ****************************************************************************/
380 static void usage(char *pname
)
382 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
384 printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname
);
385 printf("Version %s\n",VERSION
);
386 printf("\t-D become a daemon\n");
387 printf("\t-p port listen on the specified port\n");
388 printf("\t-d debuglevel set the debuglevel\n");
389 printf("\t-l log basename. Basename for log/debug files\n");
390 printf("\t-n netbiosname. the netbios name to advertise for this host\n");
391 printf("\t-H hosts file load a netbios hosts file\n");
396 /****************************************************************************
398 **************************************************************************/
399 int main(int argc
,char *argv
[])
405 char pidFile
[100] = { 0 };
409 StartupTime
= time(NULL
);
413 strcpy(debugf
,NMBLOGFILE
);
415 setup_logging(argv
[0],False
);
417 charset_initialise();
420 strcpy(host_file
,LMHOSTSFILE
);
423 /* this is for people who can't start the program correctly */
424 while (argc
> 1 && (*argv
[1] != '-')) {
429 fault_setup(fault_continue
);
431 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
432 signal(SIGTERM
,SIGNAL_CAST sig_term
);
434 while ((opt
= getopt(argc
, argv
, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF
)
439 strncpy(pidFile
, optarg
, sizeof(pidFile
));
442 strcpy(servicesf
,optarg
);
449 DEBUG(0,("Obsolete option '%c' used\n",opt
));
452 strcpy(host_file
,optarg
);
455 strcpy(myname
,optarg
);
459 sprintf(debugf
,"%s.nmb",optarg
);
462 strcpy(scope
,optarg
);
469 DEBUGLEVEL
= atoi(optarg
);
479 if (!is_a_socket(0)) {
486 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION
));
487 DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
489 get_myname(myhostname
,NULL
);
491 if (!reload_services(False
))
496 reload_services(True
);
500 if (!is_daemon
&& !is_a_socket(0)) {
501 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
506 DEBUG(2,("%s becoming a daemon\n",timestring()));
515 if ((fd
= open(pidFile
,
516 O_NONBLOCK
| O_CREAT
| O_WRONLY
| O_TRUNC
, 0644)) < 0)
518 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile
, strerror(errno
)));
521 if (fcntl_lock(fd
,F_SETLK
,0,1,F_WRLCK
)==False
)
523 DEBUG(0,("ERROR: nmbd is already running\n"));
526 sprintf(buf
, "%u\n", (unsigned int) getpid());
527 if (write(fd
, buf
, strlen(buf
)) < 0)
529 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile
, strerror(errno
)));
532 /* Leave pid file open & locked for the duration... */
536 DEBUG(3,("Opening sockets %d\n", port
));
538 if (!open_sockets(is_daemon
,port
)) return 1;
541 load_hosts_file(host_file
);
542 DEBUG(3,("Loaded hosts file\n"));
547 if (strequal(lp_workgroup(),"*")) {
548 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
551 add_my_subnets(lp_workgroup());
553 DEBUG(3,("Checked names\n"));
555 load_netbios_names();
557 DEBUG(3,("Loaded names\n"));
559 write_browse_list(time(NULL
));
561 DEBUG(3,("Dumped names\n"));