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
32 extern int DEBUGLEVEL;
34 extern pstring debugf;
35 pstring servicesf = CONFIGFILE;
42 extern pstring myhostname;
43 static pstring host_file;
44 extern pstring myname;
46 /* are we running as a daemon ? */
47 static BOOL is_daemon = False;
49 /* machine comment for host announcements */
50 pstring ServerComment="";
52 static BOOL got_bcast = False;
53 static BOOL got_myip = False;
54 static BOOL got_nmask = False;
56 /* what server type are we currently */
58 time_t StartupTime =0;
60 struct in_addr ipzero;
63 /****************************************************************************
65 ****************************************************************************/
66 static int sig_hup(void)
70 DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
72 reload_services(True);
75 #ifndef DONT_REINSTALL_SIG
76 signal(SIGHUP,SIGNAL_CAST sig_hup);
81 /****************************************************************************
83 ****************************************************************************/
84 static int sig_pipe(void)
88 DEBUG(0,("Got SIGPIPE\n"));
96 /*******************************************************************
97 prepare to dump a core file - carefully!
98 ********************************************************************/
99 static BOOL dump_core(void)
103 strcpy(dname,debugf);
104 if ((p=strrchr(dname,'/'))) *p=0;
105 strcat(dname,"/corefiles");
107 sys_chown(dname,getuid(),getgid());
109 if (chdir(dname)) return(False);
116 getrlimit(RLIMIT_CORE, &rlp);
117 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
118 setrlimit(RLIMIT_CORE, &rlp);
119 getrlimit(RLIMIT_CORE, &rlp);
120 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
126 DEBUG(0,("Dumping core in %s\n",dname));
132 /****************************************************************************
133 possibly continue after a fault
134 ****************************************************************************/
135 static void fault_continue(void)
142 /*******************************************************************
143 expire old names from the namelist and server list
144 ******************************************************************/
145 static void expire_names_and_servers(void)
147 static time_t lastrun = 0;
148 time_t t = time(NULL);
150 if (!lastrun) lastrun = t;
151 if (t < lastrun + 5) return;
158 /*****************************************************************************
159 reload the services file
160 **************************************************************************/
161 BOOL reload_services(BOOL test)
164 extern fstring remote_machine;
166 strcpy(remote_machine,"nmbd");
171 strcpy(fname,lp_configfile());
172 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
174 strcpy(servicesf,fname);
179 if (test && !lp_file_list_changed())
182 ret = lp_load(servicesf,True);
184 /* perhaps the config filename is now set */
186 DEBUG(3,("services not loaded\n"));
187 reload_services(True);
195 /****************************************************************************
196 load a netbios hosts file
197 ****************************************************************************/
198 static void load_hosts_file(char *fname)
200 FILE *f = fopen(fname,"r");
203 DEBUG(2,("Can't open lmhosts file %s\n",fname));
209 if (!fgets_slash(line,sizeof(pstring),f)) continue;
211 if (*line == '#') continue;
216 pstring ip,name,mask,flags,extra;
220 struct in_addr ipaddr;
221 struct in_addr ipmask;
222 enum name_source source = LMHOSTS;
232 if (next_token(&ptr,ip ,NULL)) ++count;
233 if (next_token(&ptr,name ,NULL)) ++count;
234 if (next_token(&ptr,mask ,NULL)) ++count;
235 if (next_token(&ptr,flags,NULL)) ++count;
236 if (next_token(&ptr,extra,NULL)) ++count;
238 if (count <= 0) continue;
240 if (count > 0 && count < 2) {
241 DEBUG(0,("Ill formed hosts line [%s]\n",line));
245 /* work out if we need to shuffle the tokens along due to the
246 optional subnet mask argument */
248 if (strchr(mask, 'G') || strchr(mask, 'S') || strchr(mask, 'M')) {
249 strcpy(flags, mask );
250 /* default action for no subnet mask */
251 strcpy(mask, inet_ntoa(Netmask));
254 DEBUG(4, ("lmhost entry: %s %s %s %s\n", ip, name, mask, flags));
256 if (strchr(flags,'G') || strchr(flags,'S'))
259 if (strchr(flags,'M') && !group) {
264 ipaddr = *interpret_addr2(ip);
265 ipmask = *interpret_addr2(mask);
268 add_domain_entry(ipaddr, ipmask, name, True);
270 add_netbios_entry(name,0x20,NB_ACTIVE,0,source,ipaddr);
279 /****************************************************************************
280 The main select loop.
281 ***************************************************************************/
282 static void process(void)
288 run_election = check_elections();
289 listen_for_packets(run_election);
298 expire_names_and_servers();
299 expire_netbios_response_entries(time(NULL)-10);
303 check_master_browser();
308 /****************************************************************************
309 open the socket communication
310 ****************************************************************************/
311 static BOOL open_sockets(BOOL isdaemon, int port)
316 if ((hp = Get_Hostbyname(myhostname)) == 0) {
317 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
322 ClientNMB = open_socket_in(SOCK_DGRAM, port,0);
326 ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
331 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
333 set_socket_options(ClientNMB,"SO_BROADCAST");
334 set_socket_options(ClientDGRAM,"SO_BROADCAST");
336 DEBUG(3,("Sockets opened.\n"));
341 /*******************************************************************
342 check that a IP, bcast and netmask and consistent. Must be a 1s
344 ******************************************************************/
345 static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast, struct in_addr nmask)
347 unsigned long a_ip,a_bcast,a_nmask;
349 a_ip = ntohl(ip.s_addr);
350 a_bcast = ntohl(bcast.s_addr);
351 a_nmask = ntohl(nmask.s_addr);
353 /* check the netmask is sane */
354 if (((a_nmask>>24)&0xFF) != 0xFF) {
355 DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
359 /* check the IP and bcast are on the same net */
360 if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
361 DEBUG(0,("IP and broadcast are on different nets!\n"));
365 /* check the IP and bcast are on the same net */
366 if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
367 DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
375 /****************************************************************************
376 initialise connect, service and file structs
377 ****************************************************************************/
378 static BOOL init_structs()
380 if (!get_myname(myhostname,got_myip?NULL:&myip))
383 /* Read the broadcast address from the interface */
385 struct in_addr ip0,ip1,ip2;
389 if (!(got_bcast && got_nmask))
391 get_broadcast(&ip0,&ip1,&ip2);
403 DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
404 DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
405 DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
407 if (!ip_consistent(myip,bcast_ip,Netmask)) {
408 DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
409 DEBUG(0,("You are likely to experience problems with this setup!\n"));
415 strcpy(myname,myhostname);
416 p = strchr(myname,'.');
423 /****************************************************************************
425 ****************************************************************************/
426 static void usage(char *pname)
428 DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
430 printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
431 printf("Version %s\n",VERSION);
432 printf("\t-D become a daemon\n");
433 printf("\t-p port listen on the specified port\n");
434 printf("\t-d debuglevel set the debuglevel\n");
435 printf("\t-l log basename. Basename for log/debug files\n");
436 printf("\t-n netbiosname. the netbios name to advertise for this host\n");
437 printf("\t-B broadcast address the address to use for broadcasts\n");
438 printf("\t-N netmask the netmask to use for subnet determination\n");
439 printf("\t-H hosts file load a netbios hosts file\n");
440 printf("\t-G group name add a group name to be part of\n");
441 printf("\t-I ip-address override the IP address\n");
442 printf("\t-C comment sets the machine comment that appears in browse lists\n");
447 /****************************************************************************
449 **************************************************************************/
450 int main(int argc,char *argv[])
459 StartupTime = time(NULL);
463 strcpy(debugf,NMBLOGFILE);
465 setup_logging(argv[0],False);
467 charset_initialise();
469 ipzero = *interpret_addr2("0.0.0.0");
472 strcpy(host_file,LMHOSTSFILE);
475 /* this is for people who can't start the program correctly */
476 while (argc > 1 && (*argv[1] != '-')) {
481 fault_setup(fault_continue);
483 signal(SIGHUP,SIGNAL_CAST sig_hup);
488 while ((opt = getopt (argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
493 strcpy(servicesf,optarg);
496 strcpy(ServerComment,optarg);
499 if (got_bcast && got_nmask) {
500 add_domain_entry(bcast_ip,Netmask,optarg, True);
502 DEBUG(0, ("Warning: option -G %s added before broadcast and netmask.\n",
504 DEBUG(0, ("Assuming default values: bcast %s netmask %s\n",
505 inet_ntoa(bcast_ip), inet_ntoa(Netmask))); /* (i hope) */
509 strcpy(host_file,optarg);
512 myip = *interpret_addr2(optarg);
516 bcast_ip = *interpret_addr2(optarg);
520 Netmask = *interpret_addr2(optarg);
524 strcpy(myname,optarg);
527 sprintf(debugf,"%s.nmb",optarg);
530 strcpy(scope,optarg);
537 DEBUGLEVEL = atoi(optarg);
547 if (!is_a_socket(0)) {
554 DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
555 DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
559 if (!reload_services(False))
562 if (!is_daemon && !is_a_socket(0)) {
563 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
568 DEBUG(2,("%s becoming a daemon\n",timestring()));
572 DEBUG(3,("Opening sockets %d\n", port));
574 if (!open_sockets(is_daemon,port)) return 1;
577 load_hosts_file(host_file);
578 DEBUG(3,("Loaded hosts file\n"));
582 strcpy(ServerComment,"Samba %v");
583 string_sub(ServerComment,"%v",VERSION);
584 string_sub(ServerComment,"%h",myhostname);
589 DEBUG(3,("Checked names\n"));
593 DEBUG(3,("Dumped names\n"));