summaryrefslogtreecommitdiffstats
path: root/source/nmbd
diff options
context:
space:
mode:
Diffstat (limited to 'source/nmbd')
-rw-r--r--source/nmbd/asyncdns.c4
-rw-r--r--source/nmbd/nmbd.c163
-rw-r--r--source/nmbd/nmbd_become_dmb.c10
-rw-r--r--source/nmbd/nmbd_browserdb.c2
-rw-r--r--source/nmbd/nmbd_browsesync.c8
-rw-r--r--source/nmbd/nmbd_elections.c5
-rw-r--r--source/nmbd/nmbd_incomingdgrams.c34
-rw-r--r--source/nmbd/nmbd_incomingrequests.c7
-rw-r--r--source/nmbd/nmbd_mynames.c78
-rw-r--r--source/nmbd/nmbd_namelistdb.c4
-rw-r--r--source/nmbd/nmbd_namequery.c2
-rw-r--r--source/nmbd/nmbd_nameregister.c7
-rw-r--r--source/nmbd/nmbd_packets.c119
-rw-r--r--source/nmbd/nmbd_processlogon.c91
-rw-r--r--source/nmbd/nmbd_responserecordsdb.c2
-rw-r--r--source/nmbd/nmbd_sendannounce.c12
-rw-r--r--source/nmbd/nmbd_serverlistdb.c5
-rw-r--r--source/nmbd/nmbd_subnetdb.c74
-rw-r--r--source/nmbd/nmbd_synclists.c8
-rw-r--r--source/nmbd/nmbd_winsproxy.c2
-rw-r--r--source/nmbd/nmbd_winsserver.c77
-rw-r--r--source/nmbd/nmbd_workgroupdb.c31
22 files changed, 484 insertions, 261 deletions
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c
index 67e55ebd508..99e697b4705 100644
--- a/source/nmbd/asyncdns.c
+++ b/source/nmbd/asyncdns.c
@@ -52,7 +52,7 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_a
#ifndef SYNC_DNS
static int fd_in = -1, fd_out = -1;
-static int child_pid = -1;
+static pid_t child_pid = -1;
static int in_dns;
/* this is the structure that is passed between the parent and child */
@@ -147,7 +147,7 @@ void start_async_dns(void)
fd_out = fd2[1];
close(fd1[1]);
close(fd2[0]);
- DEBUG(0,("started asyncdns process %d\n", child_pid));
+ DEBUG(0,("started asyncdns process %d\n", (int)child_pid));
return;
}
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 1471254b4ea..533c06351f1 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -1,7 +1,7 @@
/*
- Unix SMB/NetBIOS implementation.
+ Unix SMB/Netbios implementation.
Version 1.9.
- NBT NetBIOS routines and daemon - version 2
+ NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,6 @@ int ClientNMB = -1;
int ClientDGRAM = -1;
int global_nmb_port = -1;
-extern pstring myhostname;
static pstring host_file;
extern pstring global_myname;
extern fstring global_myworkgroup;
@@ -86,6 +85,8 @@ static void sig_term(int sig)
/**************************************************************************** **
catch a sighup
**************************************************************************** */
+static VOLATILE SIG_ATOMIC_T reload_after_sighup = False;
+
static void sig_hup(int sig)
{
BlockSignals( True, SIGHUP );
@@ -95,9 +96,8 @@ static void sig_hup(int sig)
write_browse_list( 0, True );
dump_all_namelists();
- reload_services( True );
- set_samba_nb_type();
+ reload_after_sighup = True;
BlockSignals(False,SIGHUP);
@@ -184,6 +184,67 @@ static void expire_names_and_servers(time_t t)
expire_workgroups_and_servers(t);
} /* expire_names_and_servers */
+
+/************************************************************************** **
+reload the list of network interfaces
+ ************************************************************************** */
+static void reload_interfaces(time_t t)
+{
+ static time_t lastt;
+ int n;
+ struct subnet_record *subrec;
+ extern BOOL rescan_listen_set;
+
+ if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return;
+ lastt = t;
+
+ if (!interfaces_changed()) return;
+
+ /* the list of probed interfaces has changed, we may need to add/remove
+ some subnets */
+ load_interfaces();
+
+ /* find any interfaces that need adding */
+ for (n=iface_count() - 1; n >= 0; n--) {
+ struct interface *iface = get_interface(n);
+ for (subrec=subnetlist; subrec; subrec=subrec->next) {
+ if (ip_equal(iface->ip, subrec->myip) &&
+ ip_equal(iface->nmask, subrec->mask_ip)) break;
+ }
+ if (!subrec) {
+ /* it wasn't found! add it */
+ DEBUG(2,("Found new interface %s\n",
+ inet_ntoa(iface->ip)));
+ subrec = make_normal_subnet(iface);
+ if (subrec) register_my_workgroup_one_subnet(subrec);
+ }
+ }
+
+ /* find any interfaces that need deleting */
+ for (subrec=subnetlist; subrec; subrec=subrec->next) {
+ for (n=iface_count() - 1; n >= 0; n--) {
+ struct interface *iface = get_interface(n);
+ if (ip_equal(iface->ip, subrec->myip) &&
+ ip_equal(iface->nmask, subrec->mask_ip)) break;
+ }
+ if (n == -1) {
+ /* oops, an interface has disapeared. This is
+ tricky, we don't dare actually free the
+ interface as it could be being used, so
+ instead we just wear the memory leak and
+ remove it from the list of interfaces without
+ freeing it */
+ DEBUG(2,("Deleting dead interface %s\n",
+ inet_ntoa(subrec->myip)));
+ close_subnet(subrec);
+ }
+ }
+
+ rescan_listen_set = True;
+}
+
+
+
/**************************************************************************** **
reload the services file
**************************************************************************** */
@@ -395,6 +456,20 @@ static void process(void)
* regularly sync with any other DMBs we know about
*/
sync_all_dmbs(t);
+
+ /*
+ * Reload the services file if we got a sighup.
+ */
+
+ if(reload_after_sighup) {
+ reload_services( True );
+ reopen_logs();
+ reload_interfaces(0);
+ reload_after_sighup = False;
+ }
+
+ /* check for new network interfaces */
+ reload_interfaces(t);
}
} /* process */
@@ -412,11 +487,11 @@ static BOOL open_sockets(BOOL isdaemon, int port)
*/
if ( isdaemon )
- ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
+ ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
else
ClientNMB = 0;
- ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0);
+ ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
if ( ClientNMB == -1 )
return( False );
@@ -446,7 +521,7 @@ static BOOL init_structs(void)
if (! *global_myname)
{
- fstrcpy( global_myname, myhostname );
+ fstrcpy( global_myname, myhostname() );
p = strchr( global_myname, '.' );
if (p)
*p = 0;
@@ -509,7 +584,7 @@ static BOOL init_structs(void)
*p = 0;
strlower( local_machine );
- DEBUG( 5, ("NetBIOS name list:-\n") );
+ DEBUG( 5, ("Netbios name list:-\n") );
for( n=0; my_netbios_names[n]; n++ )
DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
@@ -521,20 +596,21 @@ static BOOL init_structs(void)
**************************************************************************** */
static void usage(char *pname)
{
- DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
-
- printf( "Usage: %s [-n name] [-D] [-p port] [-d debuglevel] ", pname );
- printf( "[-l log basename]\n" );
- printf( "Version %s\n", VERSION );
- printf( "\t-D become a daemon\n" );
- printf( "\t-p port listen on the specified port\n" );
- printf( "\t-d debuglevel set the debuglevel\n" );
+
+ printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
+ printf( " [-n name] [-p port] [-s configuration file] [-i scope]\n" );
+ printf( "\t-D Become a daemon\n" );
+ printf( "\t-a Append to log file (default)\n" );
+ printf( "\t-o Overwrite log file, don't append\n" );
+ printf( "\t-h Print usage\n" );
+ printf( "\t-V Print version\n" );
+ printf( "\t-H hosts file Load a netbios hosts file\n" );
+ printf( "\t-d debuglevel Set the debuglevel\n" );
printf( "\t-l log basename. Basename for log/debug files\n" );
- printf( "\t-n netbiosname. " );
- printf( "the netbios name to advertise for this host\n");
- printf( "\t-H hosts file load a netbios hosts file\n" );
- printf( "\t-a append to log file (default)\n" );
- printf( "\t-o overwrite log file, don't append\n" );
+ printf( "\t-n netbiosname. Primary netbios name\n" );
+ printf( "\t-p port Listen on the specified port\n" );
+ printf( "\t-s configuration file Configuration file name\n" );
+ printf( "\t-i scope NetBIOS scope\n" );
printf( "\n");
} /* usage */
@@ -583,6 +659,11 @@ static void usage(char *pname)
CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
+#if defined(SIGFPE)
+ /* we are never interested in SIGFPE */
+ BlockSignals(True,SIGFPE);
+#endif
+
/* Setup the signals that allow the debug log level
to by dynamically changed. */
@@ -590,16 +671,16 @@ static void usage(char *pname)
SIGUSR1 and SIGUSR2 to do debug level changes. */
#ifndef MEM_MAN
#if defined(SIGUSR1)
- CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
+ CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
#endif /* SIGUSR1 */
#if defined(SIGUSR2)
- CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
+ CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
#endif /* SIGUSR2 */
#endif /* MEM_MAN */
while( EOF !=
- (opt = getopt( argc, argv, "aos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) )
+ (opt = getopt( argc, argv, "Vaos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) )
{
switch (opt)
{
@@ -646,9 +727,14 @@ static void usage(char *pname)
usage(argv[0]);
exit(0);
break;
+ case 'V':
+ printf( "Version %s\n", VERSION );
+ exit(0);
+ break;
default:
if( !is_a_socket(0) )
{
+ DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
usage(argv[0]);
exit(0);
}
@@ -658,15 +744,9 @@ static void usage(char *pname)
reopen_logs();
- DEBUG( 1, ( "NetBIOS nameserver version %s started.\n", VERSION ) );
+ DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
- if( !get_myname( myhostname, NULL) )
- {
- DEBUG( 0, ( "Unable to get my hostname - exiting.\n" ) );
- return -1;
- }
-
if ( !reload_services(False) )
return(-1);
@@ -677,10 +757,13 @@ static void usage(char *pname)
reload_services( True );
- if (!init_myworkgroup())
- {
- exit(1);
- }
+ fstrcpy( global_myworkgroup, lp_workgroup() );
+
+ if (strequal(global_myworkgroup,"*"))
+ {
+ DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
+ exit(1);
+ }
set_samba_nb_type();
@@ -696,6 +779,14 @@ static void usage(char *pname)
become_daemon();
}
+#ifndef SYNC_DNS
+ /* Setup the async dns. We do it here so it doesn't have all the other
+ stuff initialised and thus chewing memory and sockets */
+ if(lp_we_are_a_wins_server()) {
+ start_async_dns();
+ }
+#endif
+
if (!directory_exist(lp_lockdir(), NULL)) {
mkdir(lp_lockdir(), 0755);
}
diff --git a/source/nmbd/nmbd_become_dmb.c b/source/nmbd/nmbd_become_dmb.c
index cbef1db4b7e..ae809607dc6 100644
--- a/source/nmbd/nmbd_become_dmb.c
+++ b/source/nmbd/nmbd_become_dmb.c
@@ -157,6 +157,16 @@ in workgroup %s on subnet %s\n",
*/
become_domain_master_browser_bcast(work->work_group);
}
+ else
+ {
+ /*
+ * Now we are a domain master on a broadcast subnet, we need to add
+ * the WORKGROUP<1b> name to the unicast subnet so that we can answer
+ * unicast requests sent to this name. This bug wasn't found for a while
+ * as it is strange to have a DMB without using WINS. JRA.
+ */
+ insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
+ }
}
/****************************************************************************
diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c
index 12ce00df4f2..10d22431e91 100644
--- a/source/nmbd/nmbd_browserdb.c
+++ b/source/nmbd/nmbd_browserdb.c
@@ -99,7 +99,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name,
return( NULL );
}
- bzero( (char *)browc, sizeof( *browc ) );
+ memset( (char *)browc, '\0', sizeof( *browc ) );
/* For a new lmb entry we want to sync with it after one minute. This
will allow it time to send out a local announce and build its
diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c
index eafcc79c0aa..b177fb524e9 100644
--- a/source/nmbd/nmbd_browsesync.c
+++ b/source/nmbd/nmbd_browsesync.c
@@ -32,7 +32,7 @@ extern pstring global_myname;
extern fstring global_myworkgroup;
/* This is our local master browser list database. */
-extern struct ubi_dlList lmb_browserlist[];
+extern ubi_dlList lmb_browserlist[];
/****************************************************************************
As a domain master browser, do a sync with a local master browser.
@@ -128,7 +128,7 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_
return;
}
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
CVAL(p,0) = ANN_MasterAnnouncement;
p++;
@@ -324,7 +324,7 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec,
putip((char *)&work->dmb_addr, &ipzero);
/* Now initiate the node status request. */
- bzero((char *)&nmbname, sizeof(nmbname));
+ memset((char *)&nmbname, '\0',sizeof(nmbname));
nmbname.name[0] = '*';
/* Put the workgroup name into the userdata so we know
@@ -549,7 +549,7 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub
for(i = 0; i < rrec->rdlength / 6; i++)
{
/* Initiate the node status requests. */
- bzero((char *)&nmbname, sizeof(nmbname));
+ memset((char *)&nmbname, '\0', sizeof(nmbname));
nmbname.name[0] = '*';
putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c
index 8f876eab0c5..8e1605dbba9 100644
--- a/source/nmbd/nmbd_elections.c
+++ b/source/nmbd/nmbd_elections.c
@@ -46,7 +46,7 @@ static void send_election_dgram(struct subnet_record *subrec, char *workgroup_na
DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
workgroup_name, subrec->subnet_name ));
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
CVAL(p,0) = ANN_Election; /* Election opcode. */
p++;
@@ -135,6 +135,9 @@ void check_master_browser_exists(time_t t)
struct subnet_record *subrec;
char *workgroup_name = global_myworkgroup;
+ if (!lastrun)
+ lastrun = t;
+
if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
return;
diff --git a/source/nmbd/nmbd_incomingdgrams.c b/source/nmbd/nmbd_incomingdgrams.c
index 41aaebd9b1b..b8be579779f 100644
--- a/source/nmbd/nmbd_incomingdgrams.c
+++ b/source/nmbd/nmbd_incomingdgrams.c
@@ -546,10 +546,11 @@ static void send_backup_list_response(struct subnet_record *subrec,
char outbuf[1024];
char *p, *countptr;
unsigned int count = 0;
- int len;
+#if 0
struct server_record *servrec;
+#endif
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
@@ -572,9 +573,20 @@ static void send_backup_list_response(struct subnet_record *subrec,
p = skip_string(p,1);
/* Look for backup browsers in this workgroup. */
+
+#if 0
+ /* we don't currently send become_backup requests so we should never
+ send any other servers names out as backups for our
+ workgroup. That's why this is commented out (tridge) */
+
+ /*
+ * NB. Note that the struct work_record here is not neccessarily
+ * attached to the subnet *subrec.
+ */
+
for (servrec = work->serverlist; servrec; servrec = servrec->next)
{
- len = PTR_DIFF(p, outbuf);
+ int len = PTR_DIFF(p, outbuf);
if((sizeof(outbuf) - len) < 16)
break;
@@ -596,11 +608,10 @@ static void send_backup_list_response(struct subnet_record *subrec,
p = skip_string(p,1);
}
+#endif
SCVAL(countptr, 0, count);
- len = PTR_DIFF(p, outbuf);
-
DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
send_to_name->name, inet_ntoa(sendto_ip), count));
@@ -630,6 +641,7 @@ void process_get_backup_list_request(struct subnet_record *subrec,
uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
int name_type = dgram->dest_name.name_type;
char *workgroup_name = dgram->dest_name.name;
+ struct subnet_record *search_subrec = subrec;
DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
@@ -646,13 +658,19 @@ void process_get_backup_list_request(struct subnet_record *subrec,
return;
}
- if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
+ if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL)
{
DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
-subnet %s.\n", workgroup_name, subrec->subnet_name));
+subnet %s.\n", workgroup_name, search_subrec->subnet_name));
return;
}
+ /*
+ * If the packet was sent to WORKGROUP<1b> instead
+ * of WORKGROUP<1d> then it was unicast to us a domain master
+ * browser. Change search subrec to unicast.
+ */
+
if(name_type == 0x1b)
{
/* We must be a domain master browser in order to
@@ -664,6 +682,8 @@ subnet %s.\n", workgroup_name, subrec->subnet_name));
and I am not a domain master browser.\n", workgroup_name));
return;
}
+
+ search_subrec = unicast_subnet;
}
else if (name_type == 0x1d)
{
diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
index dd5a23e0b0d..7c46204445c 100644
--- a/source/nmbd/nmbd_incomingrequests.c
+++ b/source/nmbd/nmbd_incomingrequests.c
@@ -176,8 +176,9 @@ void process_name_refresh_request(struct subnet_record *subrec,
and send an error reply back.
*/
DEBUG(0,("process_name_refresh_request: unicast name registration request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
+received for name %s from IP %s on subnet %s.\n",
nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ DEBUG(0,("Error - should be sent to WINS server\n"));
send_name_registration_response(FMT_ERR, 0, p);
return;
@@ -366,7 +367,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
strequal(qname, namerec->name.name)))
{
/* Start with the name. */
- bzero(buf,18);
+ memset(buf,'\0',18);
slprintf(buf, 17, "%-15.15s",namerec->name.name);
strupper(buf);
@@ -421,7 +422,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
/* We don't send any stats as they could be used to attack
the protocol. */
- bzero(buf,46);
+ memset(buf,'\0',46);
buf += 46;
diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c
index 64cb8ea9e93..c36df21e7b0 100644
--- a/source/nmbd/nmbd_mynames.c
+++ b/source/nmbd/nmbd_mynames.c
@@ -43,6 +43,47 @@ static void my_name_register_failed(struct subnet_record *subrec,
nmb_namestr(nmbname), subrec->subnet_name));
}
+
+/****************************************************************************
+ Add my workgroup and my given names to one subnet
+ Also add the magic Samba names.
+ **************************************************************************/
+void register_my_workgroup_one_subnet(struct subnet_record *subrec)
+{
+ int i;
+
+ struct work_record *work;
+
+ /* Create the workgroup on the subnet. */
+ if((work = create_workgroup_on_subnet(subrec, global_myworkgroup,
+ PERMANENT_TTL)) == NULL) {
+ DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \
+Exiting.\n", global_myworkgroup, subrec->subnet_name));
+ return;
+ }
+
+ /* Each subnet entry, except for the wins_server_subnet has
+ the magic Samba names. */
+ add_samba_names_to_subnet(subrec);
+
+ /* Register all our names including aliases. */
+ for (i=0; my_netbios_names[i]; i++) {
+ register_name(subrec, my_netbios_names[i],0x20,samba_nb_type,
+ NULL,
+ my_name_register_failed, NULL);
+ register_name(subrec, my_netbios_names[i],0x03,samba_nb_type,
+ NULL,
+ my_name_register_failed, NULL);
+ register_name(subrec, my_netbios_names[i],0x00,samba_nb_type,
+ NULL,
+ my_name_register_failed, NULL);
+ }
+
+ /* Initiate election processing, register the workgroup names etc. */
+ initiate_myworkgroup_startup(subrec, work);
+}
+
+
/****************************************************************************
Add my workgroup and my given names to the subnet lists.
Also add the magic Samba names.
@@ -51,38 +92,13 @@ static void my_name_register_failed(struct subnet_record *subrec,
BOOL register_my_workgroup_and_names(void)
{
struct subnet_record *subrec;
- struct work_record *work;
int i;
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
+ for(subrec = FIRST_SUBNET;
+ subrec;
+ subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
{
- /* Create the workgroup on the subnet. */
- if((work = create_workgroup_on_subnet(subrec, global_myworkgroup, PERMANENT_TTL)) == NULL)
- {
- DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \
-Exiting.\n", global_myworkgroup, subrec->subnet_name));
- return False;
- }
-
- /* Each subnet entry, except for the wins_server_subnet has the magic Samba names. */
- add_samba_names_to_subnet(subrec);
-
- /* Register all our names including aliases. */
- for (i=0; my_netbios_names[i]; i++)
- {
- register_name(subrec, my_netbios_names[i],0x20,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names[i],0x03,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names[i],0x00,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- }
-
- /* Initiate election processing, register the workgroup names etc. */
- initiate_myworkgroup_startup(subrec, work);
+ register_my_workgroup_one_subnet(subrec);
}
/* If we are not a WINS client, we still need to add the magic Samba
@@ -180,6 +196,10 @@ void refresh_my_names(time_t t)
{
struct name_record *namerec;
+ /* B nodes don't send out name refresh requests, see RFC 1001, 15.5.1 */
+ if (subrec != unicast_subnet)
+ continue;
+
for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
namerec;
namerec = (struct name_record *)ubi_trNext( namerec ) )
diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c
index 0bc5fd875a7..dbb8be1f2d5 100644
--- a/source/nmbd/nmbd_namelistdb.c
+++ b/source/nmbd/nmbd_namelistdb.c
@@ -42,8 +42,6 @@ void set_samba_nb_type(void)
samba_nb_type = NB_MFLAG; /* samba is a 'hybrid' node type. */
else
samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */
-
- DEBUG(10,("set_samba_nb_type: %x\n", samba_nb_type));
} /* set_samba_nb_type */
/* ************************************************************************** **
@@ -201,7 +199,7 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
return( NULL );
}
- bzero( (char *)namerec, sizeof(*namerec) );
+ memset( (char *)namerec, '\0', sizeof(*namerec) );
namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr)
* num_ips );
if( NULL == namerec->data.ip )
diff --git a/source/nmbd/nmbd_namequery.c b/source/nmbd/nmbd_namequery.c
index fae045882f2..8c415548421 100644
--- a/source/nmbd/nmbd_namequery.c
+++ b/source/nmbd/nmbd_namequery.c
@@ -193,7 +193,7 @@ BOOL query_name(struct subnet_record *subrec, char *name, int type,
struct res_rec rrec;
int i;
- bzero((char *)&rrec, sizeof(struct res_rec));
+ memset((char *)&rrec, '\0', sizeof(struct res_rec));
/* Fake up the needed res_rec just in case it's used. */
rrec.rr_name = nmbname;
diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c
index 069e262987e..1e819cc88f6 100644
--- a/source/nmbd/nmbd_nameregister.c
+++ b/source/nmbd/nmbd_nameregister.c
@@ -54,6 +54,13 @@ static void register_name_response(struct subnet_record *subrec,
/* Sanity check. Ensure that the answer name in the incoming packet is the
same as the requested name in the outgoing packet. */
+ if(!question_name || !answer_name)
+ {
+ DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
+ question_name ? "question_name" : "answer_name" ));
+ return;
+ }
+
if(!nmb_name_equal(question_name, answer_name))
{
DEBUG(0,("register_name_response: Answer name %s differs from question \
diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c
index 66c774a6e98..0a7696a4663 100644
--- a/source/nmbd/nmbd_packets.c
+++ b/source/nmbd/nmbd_packets.c
@@ -37,6 +37,9 @@ extern struct in_addr loopback_ip;
static void queue_packet(struct packet_struct *packet);
+BOOL rescan_listen_set = False;
+
+
/*******************************************************************
The global packet linked-list. Incoming entries are
added to the end of this list. It is supposed to remain fairly
@@ -91,6 +94,43 @@ void set_nb_flags(char *buf, uint16 nb_flags)
}
/***************************************************************************
+Dumps out the browse packet data.
+**************************************************************************/
+
+static void debug_browse_data(char *outbuf, int len)
+{
+ int i,j;
+
+ DEBUG( 4, ( "debug_browse_data():\n" ) );
+ for (i = 0; i < len; i+= 16)
+ {
+ DEBUGADD( 4, ( "%3x char ", i ) );
+
+ for (j = 0; j < 16; j++)
+ {
+ unsigned char x = outbuf[i+j];
+ if (x < 32 || x > 127)
+ x = '.';
+
+ if (i+j >= len)
+ break;
+ DEBUGADD( 4, ( "%c", x ) );
+ }
+
+ DEBUGADD( 4, ( "%*s hex", 16-j, "" ) );
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i+j >= len)
+ break;
+ DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) );
+ }
+
+ DEBUGADD( 4, ("\n") );
+ }
+}
+
+/***************************************************************************
Generates the unique transaction identifier
**************************************************************************/
@@ -143,7 +183,6 @@ static BOOL send_netbios_packet(struct packet_struct *p)
static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmbname,
BOOL bcast,
- BOOL rec_des,
struct in_addr to_ip)
{
struct packet_struct *packet = NULL;
@@ -156,13 +195,13 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb
return NULL;
}
- bzero((char *)packet,sizeof(*packet));
+ memset((char *)packet,'\0',sizeof(*packet));
nmb = &packet->packet.nmb;
nmb->header.name_trn_id = generate_name_trn_id();
nmb->header.response = False;
- nmb->header.nm_flags.recursion_desired = rec_des;
+ nmb->header.nm_flags.recursion_desired = False;
nmb->header.nm_flags.recursion_available = False;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = False;
@@ -203,13 +242,17 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet,
return False;
}
- bzero((char *)nmb->additional,sizeof(struct res_rec));
+ memset((char *)nmb->additional,'\0',sizeof(struct res_rec));
nmb->additional->rr_name = nmb->question.question_name;
nmb->additional->rr_type = RR_TYPE_NB;
nmb->additional->rr_class = RR_CLASS_IN;
- nmb->additional->ttl = lp_max_ttl();
+ /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
+ if (nmb->header.nm_flags.bcast)
+ nmb->additional->ttl = PERMANENT_TTL;
+ else
+ nmb->additional->ttl = lp_max_ttl();
nmb->additional->rdlength = 6;
@@ -431,12 +474,11 @@ struct response_record *queue_register_name( struct subnet_record *subrec,
struct packet_struct *p;
struct response_record *rrec;
BOOL bcast = (subrec == unicast_subnet) ? False : True;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des,
+ if(( p = create_and_init_netbios_packet(nmbname, bcast,
subrec->bcast_ip)) == NULL)
return NULL;
@@ -481,7 +523,6 @@ struct response_record *queue_register_multihomed_name( struct subnet_record *su
struct packet_struct *p;
struct response_record *rrec;
BOOL bcast = False;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
BOOL ret;
/* Sanity check. */
@@ -495,7 +536,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name ));
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des,
+ if(( p = create_and_init_netbios_packet(nmbname, bcast,
subrec->bcast_ip)) == NULL)
return NULL;
@@ -542,14 +583,13 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
struct in_addr release_ip)
{
BOOL bcast = (subrec == unicast_subnet) ? False : True;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
struct packet_struct *p;
struct response_record *rrec;
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des,
+ if(( p = create_and_init_netbios_packet(nmbname, bcast,
subrec->bcast_ip)) == NULL)
return NULL;
@@ -601,14 +641,13 @@ struct response_record *queue_refresh_name( struct subnet_record *subrec,
struct in_addr refresh_ip)
{
BOOL bcast = (subrec == unicast_subnet) ? False : True;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
struct packet_struct *p;
struct response_record *rrec;
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(&namerec->name, bcast,rec_des,
+ if(( p = create_and_init_netbios_packet(&namerec->name, bcast,
subrec->bcast_ip)) == NULL)
return NULL;
@@ -650,7 +689,6 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
struct packet_struct *p;
struct response_record *rrec;
BOOL bcast = True;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
if ((subrec == unicast_subnet) || (subrec == wins_server_subnet))
bcast = False;
@@ -658,7 +696,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(nmbname, bcast,rec_des,
+ if(( p = create_and_init_netbios_packet(nmbname, bcast,
subrec->bcast_ip)) == NULL)
return NULL;
@@ -700,10 +738,8 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
struct packet_struct *p;
struct response_record *rrec;
BOOL bcast = False;
- BOOL rec_des = True;
- if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des,
- to_ip)) == NULL)
+ if(( p = create_and_init_netbios_packet(nmbname, bcast, to_ip)) == NULL)
return NULL;
if(initiate_name_query_packet_from_wins_server( p ) == False)
@@ -745,7 +781,6 @@ struct response_record *queue_node_status( struct subnet_record *subrec,
struct packet_struct *p;
struct response_record *rrec;
BOOL bcast = False;
- BOOL rec_des = (subrec == wins_server_subnet) ? True : False;
/* Sanity check. */
if(subrec != unicast_subnet)
@@ -758,7 +793,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name ));
if(assert_check_subnet(subrec))
return NULL;
- if(( p = create_and_init_netbios_packet(nmbname, bcast,rec_des,
+ if(( p = create_and_init_netbios_packet(nmbname, bcast,
send_ip)) == NULL)
return NULL;
@@ -895,10 +930,10 @@ for id %hu\n",
nmb->header.nscount = 0;
nmb->header.arcount = 0;
- bzero((char*)&nmb->question,sizeof(nmb->question));
+ memset((char*)&nmb->question,'\0',sizeof(nmb->question));
nmb->answers = &answers;
- bzero((char*)nmb->answers,sizeof(*nmb->answers));
+ memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
nmb->answers->rr_name = orig_nmb->question.question_name;
nmb->answers->rr_type = orig_nmb->question.question_type;
@@ -1013,45 +1048,43 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
{
case ANN_HostAnnouncement:
{
+ debug_browse_data(buf, len);
process_host_announce(subrec, p, buf+1);
break;
}
case ANN_DomainAnnouncement:
{
+ debug_browse_data(buf, len);
process_workgroup_announce(subrec, p, buf+1);
break;
}
case ANN_LocalMasterAnnouncement:
{
+ debug_browse_data(buf, len);
process_local_master_announce(subrec, p, buf+1);
break;
}
case ANN_AnnouncementRequest:
{
+ debug_browse_data(buf, len);
process_announce_request(subrec, p, buf+1);
break;
}
case ANN_Election:
{
+ debug_browse_data(buf, len);
process_election(subrec, p, buf+1);
break;
}
case ANN_GetBackupListReq:
{
-
- /* This is one occasion where we change a subnet that is
- given to us. If the packet was sent to WORKGROUP<1b> instead
- of WORKGROUP<1d> then it was unicast to us a domain master
- browser. Change subrec to unicast.
- */
- if(dgram->dest_name.name_type == 0x1b)
- subrec = unicast_subnet;
-
+ debug_browse_data(buf, len);
process_get_backup_list_request(subrec, p, buf+1);
break;
}
case ANN_GetBackupListResp:
{
+ debug_browse_data(buf, len);
/* We never send ANN_GetBackupListReq so we
should never get these. */
DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \
@@ -1060,6 +1093,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
}
case ANN_ResetBrowserState:
{
+ debug_browse_data(buf, len);
process_reset_browser(subrec, p, buf+1);
break;
}
@@ -1069,6 +1103,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
on the unicast subnet. */
subrec = unicast_subnet;
+ debug_browse_data(buf, len);
process_master_browser_announce(subrec, p, buf+1);
break;
}
@@ -1077,6 +1112,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
/*
* We don't currently implement this. Log it just in case.
*/
+ debug_browse_data(buf, len);
DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \
command ANN_BecomeBackup from %s IP %s to %s\n",
subrec->subnet_name, nmb_namestr(&dgram->source_name),
@@ -1085,6 +1121,7 @@ command ANN_BecomeBackup from %s IP %s to %s\n",
}
default:
{
+ debug_browse_data(buf, len);
DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \
command code %d from %s IP %s to %s\n",
subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
@@ -1123,7 +1160,7 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop
{
case ANN_HostAnnouncement:
{
- dump_data(4, buf, len);
+ debug_browse_data(buf, len);
process_lm_host_announce(subrec, p, buf+1);
break;
}
@@ -1208,11 +1245,10 @@ static void process_dgram(struct packet_struct *p)
nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name),
inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len));
+
if (len <= 0)
return;
- dump_data(100, buf2, len);
-
/* Datagram packet received for the browser mailslot */
if (strequal(smb_buf(buf),BROWSE_MAILSLOT))
{
@@ -1687,6 +1723,10 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
}
*listen_number = (count*2) + 2;
+
+ if (*ppset) free(*ppset);
+ if (*psock_array) free(*psock_array);
+
*ppset = pset;
*psock_array = sock_array;
@@ -1710,13 +1750,14 @@ BOOL listen_for_packets(BOOL run_election)
int dns_fd;
#endif
- if(listen_set == NULL)
+ if(listen_set == NULL || rescan_listen_set)
{
if(create_listen_fdset(&listen_set, &sock_array, &listen_number))
{
DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
return True;
}
+ rescan_listen_set = False;
}
memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
@@ -1749,7 +1790,7 @@ BOOL listen_for_packets(BOOL run_election)
BlockSignals(False, SIGUSR2);
#endif /* SIGUSR2 */
- selrtn = sys_select(256,&fds,NULL, &timeout);
+ selrtn = sys_select(FD_SETSIZE,&fds,&timeout);
/* We can only take signals when we are in the select - block them again here. */
@@ -1864,7 +1905,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
char *ptr,*p2;
char tmp[4];
- bzero((char *)&p,sizeof(p));
+ memset((char *)&p,'\0',sizeof(p));
if(ismyip(dest_ip))
loopback_this_packet = True;
@@ -1873,7 +1914,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
/* DIRECT GROUP or UNIQUE datagram. */
dgram->header.msg_type = unique ? 0x10 : 0x11;
- dgram->header.flags.node_type = M_NODE | 0x40;
+ dgram->header.flags.node_type = M_NODE;
dgram->header.flags.first = True;
dgram->header.flags.more = False;
dgram->header.dgm_id = name_trn_id;
@@ -1920,7 +1961,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
nmb_namestr(&dgram->source_name), inet_ntoa(src_ip)));
DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip)));
- dump_data(4, buf, len);
+ debug_browse_data(buf, len);
if(loopback_this_packet)
{
diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c
index a515c2706d4..279ab1c764f 100644
--- a/source/nmbd/nmbd_processlogon.c
+++ b/source/nmbd/nmbd_processlogon.c
@@ -50,6 +50,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len,
uint32 domainsidsize;
char *getdc;
char *uniuser; /* Unicode user name. */
+ pstring ascuser;
char *unicomp; /* Unicode computer name. */
memset(outbuf, 0, sizeof(outbuf));
@@ -117,7 +118,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) ));
q = align2(unicomp, buf);
- q = skip_unibuf(q, buf+len-q);
+ q = skip_unicode_string(q, 1);
ntversion = IVAL(q, 0);
q += 4;
@@ -134,19 +135,17 @@ logons are not enabled.\n", inet_ntoa(p->ip) ));
fstrcpy(reply_name,my_name);
fstrcpy(q, reply_name);
+
q = skip_string(q, 1); /* PDC name */
- /* PDC and domain name */
-#if 0
- if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0)
-#endif
- {
+ if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0) {
q = align2(q, buf);
- q = ascii_to_unibuf(q, my_name, outbuf+sizeof(outbuf)-q-2);
- q = ascii_to_unibuf(q, global_myworkgroup, outbuf+sizeof(outbuf)-q-2);
+ dos_PutUniCode(q, my_name, sizeof(pstring)); /* PDC name */
+ q = skip_unicode_string(q, 1);
- ntversion = 0x01;
+ dos_PutUniCode(q, global_myworkgroup,sizeof(pstring)); /* Domain name*/
+ q = skip_unicode_string(q, 1);
SIVAL(q, 0, ntversion);
q += 4;
@@ -166,10 +165,10 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
send_mailslot(True, getdc,
outbuf,PTR_DIFF(q,outbuf),
- my_name,
- 0x0,
- dgram->source_name.name,
- dgram->source_name.name_type,
+ dgram->dest_name.name,
+ dgram->dest_name.name_type,
+ dgram->source_name.name,
+ dgram->source_name.name_type,
p->ip, *iface_ip(p->ip), p->port);
return;
}
@@ -180,20 +179,13 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
q += 2;
unicomp = q;
- uniuser = skip_unibuf(unicomp, buf+len-q);
- getdc = skip_unibuf(uniuser, buf+len-q);
+ uniuser = skip_unicode_string(unicomp,1);
+ getdc = skip_unicode_string(uniuser,1);
q = skip_string(getdc,1);
- q += 4; /* skip Account Control Bits */
+ q += 4;
domainsidsize = IVAL(q, 0);
q += 4;
-
- if (domainsidsize != 0)
- {
- q += domainsidsize;
- q += 2;
- q = align4(q, buf);
- }
-
+ q += domainsidsize + 3;
ntversion = IVAL(q, 0);
q += 4;
lmnttoken = SVAL(q, 0);
@@ -201,7 +193,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
lm20token = SVAL(q, 0);
q += 2;
- DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %x\n", domainsidsize, ntversion));
+ DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
/*
* we respond regadless of whether the machine is in our password
@@ -209,43 +201,28 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
* Let's ignore the SID.
*/
+ pstrcpy(ascuser, dos_unistr(uniuser));
+ DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
+
fstrcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */
fstrcpy(reply_name+2,my_name);
- ntversion = 0x01;
- lmnttoken = 0xffff;
- lm20token = 0xffff;
-
- if (DEBUGLVL(3))
- {
- fstring ascuser;
- fstring asccomp;
-
- unibuf_to_ascii(ascuser, uniuser, sizeof(ascuser)-1);
- unibuf_to_ascii(asccomp, unicomp, sizeof(asccomp)-1);
-
- DEBUGADD(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
- asccomp,inet_ntoa(p->ip), ascuser, reply_name,
- global_myworkgroup, SAMLOGON_R, lmnttoken));
- }
+ DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
+ dos_unistr(unicomp),inet_ntoa(p->ip), ascuser, reply_name, global_myworkgroup,
+ SAMLOGON_R ,lmnttoken));
/* Construct reply. */
q = outbuf;
- if (uniuser[0] == 0)
- {
- SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
- }
- else
- {
- SSVAL(q, 0, SAMLOGON_R);
- }
+ SSVAL(q, 0, SAMLOGON_R);
q += 2;
- /* Logon server, trust account, domain */
- q = ascii_to_unibuf(q, reply_name, outbuf+sizeof(outbuf)-q-2);
- q = uni_strncpy(q, uniuser, outbuf+sizeof(outbuf)-q-2);
- q = ascii_to_unibuf(q, lp_workgroup(), outbuf+sizeof(outbuf)-q-2);
+ dos_PutUniCode(q, reply_name,sizeof(pstring));
+ q = skip_unicode_string(q, 1);
+ unistrcpy(q, uniuser);
+ q = skip_unicode_string(q, 1); /* User name (workstation trust account) */
+ dos_PutUniCode(q, lp_workgroup(),sizeof(pstring));
+ q = skip_unicode_string(q, 1); /* Domain name. */
SIVAL(q, 0, ntversion);
q += 4;
@@ -258,10 +235,10 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
send_mailslot(True, getdc,
outbuf,PTR_DIFF(q,outbuf),
- my_name,
- 0x0,
- dgram->source_name.name,
- dgram->source_name.name_type,
+ dgram->dest_name.name,
+ dgram->dest_name.name_type,
+ dgram->source_name.name,
+ dgram->source_name.name_type,
p->ip, *iface_ip(p->ip), p->port);
break;
}
diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c
index 0c698760bb6..fe294647732 100644
--- a/source/nmbd/nmbd_responserecordsdb.c
+++ b/source/nmbd/nmbd_responserecordsdb.c
@@ -119,7 +119,7 @@ struct response_record *make_response_record( struct subnet_record *subrec,
return NULL;
}
- bzero((char *)rrec, sizeof(*rrec));
+ memset((char *)rrec, '\0', sizeof(*rrec));
rrec->response_id = nmb->header.name_trn_id;
diff --git a/source/nmbd/nmbd_sendannounce.c b/source/nmbd/nmbd_sendannounce.c
index 38c8deafe72..87115a1eb0d 100644
--- a/source/nmbd/nmbd_sendannounce.c
+++ b/source/nmbd/nmbd_sendannounce.c
@@ -46,7 +46,7 @@ void send_browser_reset(int reset_type, char *to_name, int to_type, struct in_ad
DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
reset_type, to_name, to_type, inet_ntoa(to_ip) ));
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
CVAL(p,0) = ANN_ResetBrowserState;
p++;
@@ -73,7 +73,7 @@ void broadcast_announce_request(struct subnet_record *subrec, struct work_record
DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
to subnet %s\n", work->work_group, subrec->subnet_name));
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
CVAL(p,0) = ANN_AnnouncementRequest;
p++;
@@ -101,7 +101,7 @@ static void send_announcement(struct subnet_record *subrec, int announce_type,
pstring outbuf;
char *p;
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf+1;
CVAL(outbuf,0) = announce_type;
@@ -142,7 +142,7 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type
pstring outbuf;
char *p=outbuf;
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
SSVAL(p,0,announce_type);
SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
@@ -504,7 +504,7 @@ void announce_remote(time_t t)
if (!*s)
return;
- comment = lp_serverstring();
+ comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH);
for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); )
{
@@ -587,7 +587,7 @@ for workgroup %s on subnet %s.\n", global_myworkgroup, FIRST_SUBNET->subnet_name
return;
}
- bzero(outbuf,sizeof(outbuf));
+ memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
CVAL(p,0) = ANN_MasterAnnouncement;
p++;
diff --git a/source/nmbd/nmbd_serverlistdb.c b/source/nmbd/nmbd_serverlistdb.c
index d30e8da64ce..41009bc68f0 100644
--- a/source/nmbd/nmbd_serverlistdb.c
+++ b/source/nmbd/nmbd_serverlistdb.c
@@ -156,7 +156,7 @@ workgroup %s. This is a bug.\n", name, work->work_group));
return NULL;
}
- bzero((char *)servrec,sizeof(*servrec));
+ memset((char *)servrec,'\0',sizeof(*servrec));
servrec->subnet = work->subnet;
@@ -399,7 +399,8 @@ void write_browse_list(time_t t, BOOL force_write)
slprintf(tmp, sizeof(tmp)-1, "\"%s\"", my_netbios_names[i]);
fprintf(fp, "%-25s ", tmp);
fprintf(fp, "%08x ", stype);
- slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", lp_serverstring());
+ slprintf(tmp, sizeof(tmp)-1, "\"%s\" ",
+ string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
fprintf(fp, "%-30s", tmp);
fprintf(fp, "\"%s\"\n", global_myworkgroup);
}
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
index 527efa9dd83..37b50f85250 100644
--- a/source/nmbd/nmbd_subnetdb.c
+++ b/source/nmbd/nmbd_subnetdb.c
@@ -55,22 +55,7 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
static void add_subnet(struct subnet_record *subrec)
{
- struct subnet_record *subrec2;
-
- if (!subnetlist)
- {
- subnetlist = subrec;
- subrec->prev = NULL;
- subrec->next = NULL;
- return;
- }
-
- for (subrec2 = subnetlist; subrec2->next; subrec2 = subrec2->next)
- ;
-
- subrec2->next = subrec;
- subrec->next = NULL;
- subrec->prev = subrec2;
+ DLIST_ADD(subnetlist, subrec);
}
/* ************************************************************************** **
@@ -96,19 +81,41 @@ static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
- nmb_namestr(Iname), nmb_namestr(&NR->name), sizeof(struct nmb_name) );
+ nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
}
return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
} /* namelist_entry_compare */
+
+/****************************************************************************
+stop listening on a subnet
+we don't free the record as we don't have proper reference counting for it
+yet and it may be in use by a response record
+ ****************************************************************************/
+void close_subnet(struct subnet_record *subrec)
+{
+ DLIST_REMOVE(subnetlist, subrec);
+
+ if (subrec->dgram_sock != -1) {
+ close(subrec->dgram_sock);
+ subrec->dgram_sock = -1;
+ }
+ if (subrec->nmb_sock != -1) {
+ close(subrec->nmb_sock);
+ subrec->nmb_sock = -1;
+ }
+}
+
+
+
/****************************************************************************
Create a subnet entry.
****************************************************************************/
static struct subnet_record *make_subnet(char *name, enum subnet_type type,
- struct in_addr myip, struct in_addr bcast_ip,
- struct in_addr mask_ip)
+ struct in_addr myip, struct in_addr bcast_ip,
+ struct in_addr mask_ip)
{
struct subnet_record *subrec = NULL;
int nmb_sock, dgram_sock;
@@ -130,7 +137,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type,
* Fail the subnet creation if this fails.
*/
- if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr)) == -1)
+ if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1)
{
if( DEBUGLVL( 0 ) )
{
@@ -142,7 +149,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type,
return NULL;
}
- if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1)
+ if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1)
{
if( DEBUGLVL( 0 ) )
{
@@ -170,7 +177,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type,
return(NULL);
}
- bzero( (char *)subrec, sizeof(*subrec) );
+ memset( (char *)subrec, '\0', sizeof(*subrec) );
(void)ubi_trInitTree( subrec->namelist,
namelist_entry_compare,
ubi_trOVERWRITE );
@@ -202,6 +209,23 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type,
return subrec;
}
+
+/****************************************************************************
+ Create a normal subnet
+**************************************************************************/
+struct subnet_record *make_normal_subnet(struct interface *iface)
+{
+ struct subnet_record *subrec;
+
+ subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
+ iface->ip, iface->bcast, iface->nmask);
+ if (subrec) {
+ add_subnet(subrec);
+ }
+ return subrec;
+}
+
+
/****************************************************************************
Create subnet entries.
**************************************************************************/
@@ -225,13 +249,9 @@ BOOL create_subnets(void)
for (i = 0 ; i < num_interfaces; i++)
{
- struct subnet_record *subrec;
struct interface *iface = get_interface(i);
- if((subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
- iface->ip, iface->bcast,iface->nmask)) == NULL)
- return False;
- add_subnet(subrec);
+ if (!make_normal_subnet(iface)) return False;
}
/*
diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c
index aab1e4349ca..fb51be4d8f2 100644
--- a/source/nmbd/nmbd_synclists.c
+++ b/source/nmbd/nmbd_synclists.c
@@ -40,7 +40,7 @@ struct sync_record {
fstring server;
pstring fname;
struct in_addr ip;
- int pid;
+ pid_t pid;
};
/* a linked list of current sync connections */
@@ -92,7 +92,7 @@ static void sync_child(char *name, int nm_type,
return;
}
- if (!cli_session_setup(&cli, local_machine, "", "", 1, "", 0, workgroup)) {
+ if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) {
cli_shutdown(&cli);
return;
}
@@ -103,7 +103,7 @@ static void sync_child(char *name, int nm_type,
}
/* Fetch a workgroup list. */
- cli_NetServerEnum(&cli, workgroup,
+ cli_NetServerEnum(&cli, cli.server_domain?cli.server_domain:workgroup,
local_type|SV_TYPE_DOMAIN_ENUM,
callback);
@@ -147,7 +147,7 @@ void sync_browse_lists(struct work_record *work,
slprintf(s->fname, sizeof(pstring)-1,
"%s/sync.%d", lp_lockdir(), counter++);
- string_sub(s->fname,"//", "/");
+ all_string_sub(s->fname,"//", "/", 0);
DLIST_ADD(syncs, s);
diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c
index 43beb9acd85..1398ebd299a 100644
--- a/source/nmbd/nmbd_winsproxy.c
+++ b/source/nmbd/nmbd_winsproxy.c
@@ -207,7 +207,7 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec,
sizeof(struct packet_struct *)];
struct userdata_struct *userdata = (struct userdata_struct *)ud;
- bzero(ud, sizeof(ud));
+ memset(ud, '\0', sizeof(ud));
userdata->copy_fn = wins_proxy_userdata_copy_fn;
userdata->free_fn = wins_proxy_userdata_free_fn;
diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
index 35ca5af62c4..45e93351674 100644
--- a/source/nmbd/nmbd_winsserver.c
+++ b/source/nmbd/nmbd_winsserver.c
@@ -30,6 +30,41 @@ extern int DEBUGLEVEL;
extern struct in_addr ipzero;
+/****************************************************************************
+possibly call the WINS hook external program when a WINS change is made
+*****************************************************************************/
+static void wins_hook(char *operation, struct name_record *namerec, int ttl)
+{
+ pstring command;
+ char *cmd = lp_wins_hook();
+ char *p;
+ int i;
+
+ if (!cmd || !*cmd) return;
+
+ for (p=namerec->name.name; *p; p++) {
+ if (!(isalnum((int)*p) || strchr("._-",*p))) {
+ DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
+ return;
+ }
+ }
+
+ p = command;
+ p += slprintf(p, sizeof(command), "%s %s %s %02x %d",
+ cmd,
+ operation,
+ namerec->name.name,
+ namerec->name.name_type,
+ ttl);
+
+ for (i=0;i<namerec->data.num_ips;i++) {
+ p += slprintf(p, sizeof(command) - (p-command), " %s", inet_ntoa(namerec->data.ip[i]));
+ }
+
+ DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
+ smbrun(command, NULL, False);
+}
+
/****************************************************************************
hash our interfaces and netbios names settings
@@ -147,11 +182,6 @@ BOOL initialise_wins(void)
add_samba_names_to_subnet(wins_server_subnet);
-#ifndef SYNC_DNS
- /* Setup the async dns. */
- start_async_dns();
-#endif
-
pstrcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
pstrcat(fname,"/");
@@ -456,6 +486,7 @@ does not match group bit in WINS for this name.\n", nmb_namestr(question), group
*/
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
else if(group)
@@ -636,7 +667,7 @@ void wins_process_name_registration_request(struct subnet_record *subrec,
int ttl = get_ttl_from_packet(nmb);
struct name_record *namerec = NULL;
struct in_addr from_ip;
- BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;;
+ BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
putip((char *)&from_ip,&nmb->additional->rdata[2]);
@@ -715,7 +746,7 @@ to register name %s. Name already exists in WINS with source type %d.\n",
if(!registering_group_name && (question->name_type == 0x1d))
{
DEBUG(3,("wins_process_name_registration_request: Ignoring request \
-to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
+to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
send_wins_name_registration_response(0, ttl, p);
return;
}
@@ -785,6 +816,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
*/
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
}
@@ -801,6 +833,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
{
update_name_ttl( namerec, ttl );
send_wins_name_registration_response( 0, ttl, p );
+ wins_hook("refresh", namerec, ttl);
return;
}
@@ -858,6 +891,9 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
(void)add_name_to_subnet( subrec, question->name, question->name_type,
nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
+ if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
+ wins_hook("add", namerec, ttl);
+ }
send_wins_name_registration_response(0, ttl, p);
}
@@ -916,6 +952,7 @@ a subsequent IP addess.\n", nmb_namestr(question_name) ));
add_ip_to_name_record(namerec, from_ip);
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, orig_reg_packet);
+ wins_hook("add", namerec, ttl);
orig_reg_packet->locked = False;
free_packet(orig_reg_packet);
@@ -1082,11 +1119,16 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
* It's one of our names and one of our IP's. Ensure the IP is in the record and
* update the ttl.
*/
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
+ if(!find_ip_in_name_record(namerec, from_ip)) {
+ add_ip_to_name_record(namerec, from_ip);
+ wins_hook("add", namerec, ttl);
+ } else {
+ wins_hook("refresh", namerec, ttl);
+ }
+
+ update_name_ttl(namerec, ttl);
+ send_wins_name_registration_response(0, ttl, p);
+ return;
}
}
@@ -1099,6 +1141,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
{
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
@@ -1158,6 +1201,10 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
(void)add_name_to_subnet( subrec, question->name, question->name_type,
nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
+ if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
+ wins_hook("add", namerec, ttl);
+ }
+
send_wins_name_registration_response(0, ttl, p);
}
@@ -1253,7 +1300,7 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p,
int ttl = 0;
int i;
- bzero(rdata,6);
+ memset(rdata,'\0',6);
if(rcode == 0)
{
@@ -1495,6 +1542,8 @@ release name %s as IP %s is not one of the known IP's for this name.\n",
send_wins_name_release_response(0, p);
remove_ip_from_name_record(namerec, from_ip);
+ wins_hook("delete", namerec, 0);
+
/*
* Remove the name entirely if no IP addresses left.
*/
@@ -1552,7 +1601,7 @@ void wins_write_database(BOOL background)
}
slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST);
- string_sub(fname,"//", "/");
+ all_string_sub(fname,"//", "/", 0);
slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid());
if((fp = sys_fopen(fnamenew,"w")) == NULL)
diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c
index 0f66b140a81..5514e78dc1c 100644
--- a/source/nmbd/nmbd_workgroupdb.c
+++ b/source/nmbd/nmbd_workgroupdb.c
@@ -43,26 +43,9 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */
static void add_workgroup(struct subnet_record *subrec, struct work_record *work)
{
- struct work_record *w2;
-
- work->subnet = subrec;
-
- if (!subrec->workgrouplist)
- {
- subrec->workgrouplist = work;
- work->prev = NULL;
- work->next = NULL;
- return;
- }
-
- for (w2 = subrec->workgrouplist; w2->next; w2 = w2->next)
- ;
-
- w2->next = work;
- work->next = NULL;
- work->prev = w2;
-
- subrec->work_changed = True;
+ work->subnet = subrec;
+ DLIST_ADD(subrec->workgrouplist, work);
+ subrec->work_changed = True;
}
/****************************************************************************
@@ -80,7 +63,7 @@ static struct work_record *create_workgroup(char *name, int ttl)
DEBUG(0,("create_workgroup: malloc fail !\n"));
return NULL;
}
- bzero((char *)work, sizeof(*work));
+ memset((char *)work, '\0', sizeof(*work));
StrnCpy(work->work_group,name,sizeof(work->work_group)-1);
work->serverlist = NULL;
@@ -254,7 +237,8 @@ void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_reco
if we are so configured. */
if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) &&
- (subrec != wins_server_subnet) && lp_preferred_master())
+ (subrec != wins_server_subnet) && lp_preferred_master() &&
+ lp_local_master())
{
DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \
workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
@@ -283,7 +267,8 @@ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY,
- PERMANENT_TTL, lp_serverstring());
+ PERMANENT_TTL,
+ string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \
on subnet %s\n", name, subrec->subnet_name));
}