summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nameannounce.c3
-rw-r--r--source3/namedbname.c16
-rw-r--r--source3/namedbresp.c11
-rw-r--r--source3/namedbserver.c10
-rw-r--r--source3/namedbsubnet.c15
-rw-r--r--source3/namedbwork.c18
-rw-r--r--source3/nameelect.c50
-rw-r--r--source3/namepacket.c7
-rw-r--r--source3/nameresp.c25
-rw-r--r--source3/nameserv.c121
-rw-r--r--source3/namework.c2
11 files changed, 172 insertions, 106 deletions
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index e4ef868bb6..63dfc1555b 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -421,7 +421,8 @@ void announce_master(void)
time_t t = time(NULL);
BOOL am_master = False; /* are we a master of some sort? :-) */
- if (last && (t-last < CHECK_TIME_MST_ANNOUNCE * 60))
+ if (!last) last = t;
+ if (t-last < CHECK_TIME_MST_ANNOUNCE * 60)
return;
last = t;
diff --git a/source3/namedbname.c b/source3/namedbname.c
index 3bff6dae7a..82b19077f9 100644
--- a/source3/namedbname.c
+++ b/source3/namedbname.c
@@ -222,21 +222,21 @@ void dump_names(void)
/* XXXX i have little imagination as to how to output nb_flags as
anything other than as a hexadecimal number :-) */
- sprintf(data, "%s#%02x %s %ld %2x",
+ sprintf(data, "%s#%02x %s %2x %ld",
n->name.name,n->name.name_type, /* XXXX ignore the scope for now */
inet_ntoa(n->ip),
- n->death_time,
- n->nb_flags);
+ n->nb_flags,
+ n->death_time);
fprintf(f, "%s\n", data);
}
DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip)));
DEBUG(3,("%15s ", inet_ntoa(d->mask_ip)));
- DEBUG(3,("%s %15s TTL=%15d NBFLAGS=%2x\n",
+ DEBUG(3,("%-19s %15s NB=%2x TTL=%ld \n",
namestr(&n->name),
inet_ntoa(n->ip),
- n->death_time?n->death_time-t:0,
- n->nb_flags));
+ n->nb_flags,
+ n->death_time?n->death_time-t:0));
}
fclose(f);
@@ -490,6 +490,8 @@ struct name_record *search_for_name(struct subnet_record **d,
if (*d == NULL) return NULL;
+ DEBUG(4,("subnet %s ", inet_ntoa((*d)->bcast_ip)));
+
/* now try DNS lookup. */
if (!n)
{
@@ -497,7 +499,7 @@ struct name_record *search_for_name(struct subnet_record **d,
unsigned long a;
/* only do DNS lookups if the query is for type 0x20 or type 0x0 */
- if (!dns_type)
+ if (!dns_type && name_type != 0x1b)
{
DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n"));
return NULL;
diff --git a/source3/namedbresp.c b/source3/namedbresp.c
index a9abc5d9b5..c453d9bbec 100644
--- a/source3/namedbresp.c
+++ b/source3/namedbresp.c
@@ -50,6 +50,9 @@ void add_response_record(struct subnet_record *d,
num_response_packets++; /* count of total number of packets still around */
+ DEBUG(4,("adding response record id:%d num_records:%d\n",
+ n->response_id, num_response_packets));
+
if (!d->responselist)
{
d->responselist = n;
@@ -89,7 +92,7 @@ void remove_response_record(struct subnet_record *d,
create a name query response record
**************************************************************************/
struct response_record *make_response_queue_record(enum state_type state,
- int id,int fd,
+ int id,uint16 fd,
int quest_type, char *name,int type, int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
@@ -114,8 +117,8 @@ struct response_record *make_response_queue_record(enum state_type state,
n->reply_to_ip = reply_to_ip;
n->repeat_interval = 1; /* XXXX should be in ms */
- n->repeat_count = 4;
- n->repeat_time = time(NULL) + n->repeat_interval;
+ n->repeat_count = 3; /* 3 retries */
+ n->repeat_time = time(NULL) + n->repeat_interval; /* initial retry time */
n->num_msgs = 0;
@@ -138,6 +141,8 @@ struct response_record *find_response_record(struct subnet_record **d,
for (n = (*d)->responselist; n; n = n->next)
{
if (n->response_id == id) {
+ DEBUG(4, ("found response record on %s: %d\n",
+ inet_ntoa((*d)->bcast_ip), id));
return n;
}
}
diff --git a/source3/namedbserver.c b/source3/namedbserver.c
index 74c7a96baa..de0cda79cc 100644
--- a/source3/namedbserver.c
+++ b/source3/namedbserver.c
@@ -46,9 +46,11 @@ extern BOOL updatedlists;
/*******************************************************************
expire old servers in the serverlist
- time of -1 indicates everybody dies
+ time of -1 indicates everybody dies except those with time of 0
+ remove_all_servers indicates everybody dies.
******************************************************************/
-void remove_old_servers(struct work_record *work, time_t t)
+void remove_old_servers(struct work_record *work, time_t t,
+ BOOL remove_all)
{
struct server_record *s;
struct server_record *nexts;
@@ -56,7 +58,7 @@ void remove_old_servers(struct work_record *work, time_t t)
/* expire old entries in the serverlist */
for (s = work->serverlist; s; s = nexts)
{
- if (t == -1 || (s->death_time && s->death_time < t))
+ if (remove_all || (s->death_time && (t == -1 || s->death_time < t)))
{
DEBUG(3,("Removing dead server %s\n",s->serv.name));
updatedlists = True;
@@ -195,7 +197,7 @@ void expire_servers(time_t t)
for (work = d->workgrouplist; work; work = work->next)
{
- remove_old_servers(work, t);
+ remove_old_servers(work, t, False);
}
}
}
diff --git a/source3/namedbsubnet.c b/source3/namedbsubnet.c
index 5ede7b0b81..6b187b21bb 100644
--- a/source3/namedbsubnet.c
+++ b/source3/namedbsubnet.c
@@ -272,18 +272,22 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
void write_browse_list(void)
{
struct subnet_record *d;
-
pstring fname,fnamenew;
FILE *f;
+
+ static time_t lasttime = 0;
+ time_t t = time(NULL);
+
+ if (!lasttime) lasttime = t;
+ if (!updatedlists || t - lasttime < 5) return;
- if (!updatedlists) return;
+ lasttime = t;
+ updatedlists = False;
+ updatecount++;
dump_names();
dump_workgroups();
- updatedlists = False;
- updatecount++;
-
strcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
strcat(fname,"/");
@@ -337,4 +341,3 @@ void write_browse_list(void)
DEBUG(3,("Wrote browse list %s\n",fname));
}
-
diff --git a/source3/namedbwork.c b/source3/namedbwork.c
index 7937aa4512..88f66a7b15 100644
--- a/source3/namedbwork.c
+++ b/source3/namedbwork.c
@@ -134,7 +134,8 @@ static struct work_record *make_workgroup(char *name)
remove workgroups
******************************************************************/
struct work_record *remove_workgroup(struct subnet_record *d,
- struct work_record *work)
+ struct work_record *work,
+ BOOL remove_all_servers)
{
struct work_record *ret_work = NULL;
@@ -142,16 +143,19 @@ struct work_record *remove_workgroup(struct subnet_record *d,
DEBUG(3,("Removing old workgroup %s\n", work->work_group));
- remove_old_servers(work, -1);
-
ret_work = work->next;
+
+ remove_old_servers(work, -1, remove_all_servers);
- if (work->prev) work->prev->next = work->next;
- if (work->next) work->next->prev = work->prev;
+ if (!work->serverlist)
+ {
+ if (work->prev) work->prev->next = work->next;
+ if (work->next) work->next->prev = work->prev;
- if (d->workgrouplist == work) d->workgrouplist = work->next;
+ if (d->workgrouplist == work) d->workgrouplist = work->next;
- free(work);
+ free(work);
+ }
return ret_work;
}
diff --git a/source3/nameelect.c b/source3/nameelect.c
index 386e7b0bab..e115b0d881 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -96,31 +96,32 @@ void browser_gone(char *work_name, struct in_addr ip)
struct subnet_record *d = find_subnet(ip);
struct work_record *work = find_workgroupstruct(d, work_name, False);
+ /* i don't know about this workgroup, therefore i don't care */
if (!work || !d) return;
-
- if (strequal(work->work_group, lp_workgroup()) &&
- ismybcast(d->bcast_ip))
- {
+
+ if (strequal(work->work_group, lp_workgroup()) && d->my_interface)
+ {
DEBUG(2,("Forcing election on %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip)));
/* we can attempt to become master browser */
work->needelection = True;
- }
+ }
else
- {
- /* XXXX note: this will delete entries that have been added in by
- lmhosts as well. a flag to ensure that these are not deleted may
- be considered */
-
- /* workgroup with no master browser is not the default workgroup:
- it's also not on our subnet. therefore delete it: it can be
- recreated dynamically */
-
- send_election(d, work->work_group, 0, 0, myname);
- remove_workgroup(d, work);
- }
+ {
+ /* local interfaces: force an election */
+ if (d->my_interface)
+ send_election(d, work->work_group, 0, 0, myname);
+
+ /* only removes workgroup completely on a local interface or
+ if there are no server entries on the remote interface.
+ (persistent lmhost entries on a remote interface will stop
+ the workgroup being removed. persistent lmhosts entries on
+ a local interface _will_ be removed).
+ */
+ remove_workgroup(d, work, d->my_interface);
+ }
}
@@ -247,7 +248,8 @@ void become_master(struct subnet_record *d, struct work_record *work)
if (!work) return;
- DEBUG(2,("Becoming master for %s (stage %d)",work->work_group,work->state));
+ DEBUG(2,("Becoming master for %s (currently at stage %d)\n",
+ work->work_group,work->state));
switch (work->state)
{
@@ -261,7 +263,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
- DEBUG(2,("first stage: register ^1^2__MSBROWSE__^2^1\n"));
+ DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
/* add special browser name */
add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
@@ -275,7 +277,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
/* add server entry on successful registration of MSBROWSE */
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
- DEBUG(2,("second stage: register as master browser\n"));
+ DEBUG(3,("go to second stage: register as master browser\n"));
/* add master name */
add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
@@ -298,13 +300,13 @@ void become_master(struct subnet_record *d, struct work_record *work)
if (lp_domain_master())
{
- DEBUG(2,("third stage: register as domain master\n"));
+ DEBUG(3,("third stage: register as domain master\n"));
/* add domain master name */
add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
}
else
{
- DEBUG(2,("samba not configured as a domain master: no third stage.\n"));
+ DEBUG(3,("samba not configured as a domain master: no third stage.\n"));
}
break;
@@ -323,7 +325,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->ServerType |= SV_TYPE_DOMAIN_CTRL;
work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
}
- DEBUG(2,("fourth stage: samba is now a domain master.\n"));
+ DEBUG(3,("fourth stage: samba is now a domain master.\n"));
add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
}
@@ -332,7 +334,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN:
{
/* nothing else to become, at the moment: we are top-dog. */
- DEBUG(2,("fifth stage: there isn't one yet!\n"));
+ DEBUG(3,("fifth stage: there isn't one yet!\n"));
break;
}
}
diff --git a/source3/namepacket.c b/source3/namepacket.c
index 38b8ed0653..5afdb8af0e 100644
--- a/source3/namepacket.c
+++ b/source3/namepacket.c
@@ -81,9 +81,10 @@ void initiate_netbios_packet(uint16 *id,
bzero((char *)&p,sizeof(p));
- update_name_trn_id();
-
- if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
+ if (*id == 0xffff) {
+ update_name_trn_id();
+ *id = name_trn_id; /* allow resending with same id */
+ }
nmb->header.name_trn_id = *id;
nmb->header.opcode = opcode;
diff --git a/source3/nameresp.c b/source3/nameresp.c
index 0b38c4bb9a..3a9d46bf9d 100644
--- a/source3/nameresp.c
+++ b/source3/nameresp.c
@@ -35,8 +35,6 @@ extern pstring scope;
extern struct in_addr ipzero;
extern struct in_addr ipgrp;
-extern int num_response_packets;
-
/***************************************************************************
deals with an entry before it dies
@@ -174,14 +172,17 @@ static void dead_netbios_entry(struct subnet_record *d,
******************************************************************/
void expire_netbios_response_entries()
{
- struct response_record *n;
- struct response_record *nextn;
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
- for (n = d->responselist; n; n = nextn)
+ {
+ struct response_record *n, *nextn;
+
+ for (n = d->responselist; n; n = nextn)
{
- if (n->repeat_time < time(NULL))
+ nextn = n->next;
+
+ if (n->repeat_time <= time(NULL))
{
if (n->repeat_count > 0)
{
@@ -192,10 +193,13 @@ void expire_netbios_response_entries()
n->repeat_time += n->repeat_interval; /* XXXX ms needed */
n->repeat_count--;
+
}
else
{
- nextn = n->next;
+ DEBUG(4,("timeout response %d for %s %s\n",
+ n->response_id, namestr(&n->name),
+ inet_ntoa(n->send_ip)));
dead_netbios_entry (d,n); /* process the non-response */
remove_response_record(d,n); /* remove the non-response */
@@ -203,8 +207,8 @@ void expire_netbios_response_entries()
continue;
}
}
- nextn = n->next;
}
+ }
}
@@ -274,7 +278,10 @@ struct response_record *queue_netbios_packet(struct subnet_record *d,
initiate_netbios_packet(&id, fd, quest_type, name, name_type,
nb_flags, bcast, recurse, send_ip);
- if (id == 0xffff) return NULL;
+ if (id == 0xffff) {
+ DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
+ return NULL;
+ }
if ((n = make_response_queue_record(state,id,fd,
quest_type,name,name_type,nb_flags,ttl,
diff --git a/source3/nameserv.c b/source3/nameserv.c
index 056c943cd6..9fc578d009 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -45,6 +45,10 @@ extern struct subnet_record *subnetlist;
/****************************************************************************
remove an entry from the name list
+
+ note: the name will _always_ be removed: it's just a matter of when.
+ XXXX at present, the name is removed _even_ if a WINS server says keep it.
+
****************************************************************************/
void remove_name_entry(struct subnet_record *d, char *name,int type)
{
@@ -52,43 +56,62 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
a de-registration packet to the local subnet before removing the
name from its local-subnet name database. */
- if (lp_wins_support())
+ struct name_record n;
+ struct name_record *n2=NULL;
+
+ make_nmb_name(&n.name,name,type,scope);
+
+ if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
+ {
+ /* check name isn't already being de-registered */
+ if (NAME_DEREG(n2->nb_flags))
+ return;
+
+ /* mark the name as in the process of deletion. */
+ n2->nb_flags &= NB_DEREG;
+ }
+
+ if (ip_equal(d->bcast_ip, ipgrp))
+ {
+ if (lp_wins_support())
{
- /* we are a WINS server. */
- /* XXXX assume that if we are a WINS server that we are therefore
- not pointing to another WINS server as well. this may later NOT
- actually be true */
- remove_netbios_name(d,name,type,SELF,ipzero);
+ /* we are a WINS server. */
+ /* XXXX assume that if we are a WINS server that we are therefore
+ not pointing to another WINS server as well. this may later NOT
+ actually be true
+ */
+ remove_netbios_name(d,name,type,SELF,ipzero);
}
- else
+ else
{
/* not a WINS server: cannot just remove our own names: we have to
- ask permission from the WINS server, or if no reply is received,
- _then_ we can remove the name */
-
- struct name_record n;
- struct name_record *n2=NULL;
-
- make_nmb_name(&n.name,name,type,scope);
+ release them on the network first. ask permission from the WINS
+ server, or if no reply is received, then we can remove the name */
- if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
- {
- /* check name isn't already being de-registered */
- if (NAME_DEREG(n2->nb_flags))
- return;
+ queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
+ name, type, 0, 0,
+ False, True, ipzero, ipzero);
+ }
+ }
+ else
+ {
+ /* local interface: cannot just remove our own names: we have to
+ release them on the network first. once no reply is received,
+ then we can remove the name. */
- /* mark the name as in the process of deletion. */
- n2->nb_flags &= NB_DEREG;
- }
- queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
+ queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
name, type, 0, 0,
- False, True, ipzero, ipzero);
- }
+ True, True, d->bcast_ip, d->bcast_ip);
+ }
}
/****************************************************************************
add an entry to the name list
+
+ big note: our name will _always_ be added (if there are no objections).
+ it's just a matter of when this will be done (e.g after a time-out).
+
****************************************************************************/
void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
{
@@ -104,28 +127,38 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
if (find_name(d->namelist, &n, SELF, ipzero))
re_reg = True;
- /* always add our own entries */
- /* a time-to-live allows us to refresh this name with the WINS server. */
- add_netbios_entry(d,name,type,
- nb_flags,GET_TTL(0),
- SELF,ipzero,False,lp_wins_support());
-
/* XXXX BUG: if samba is offering WINS support, it should still add the
name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
regarding the point about M-nodes. */
- if (!lp_wins_support())
+ if (ip_equal(d->bcast_ip, ipgrp))
{
- /* samba isn't supporting WINS itself: register the name using broadcast
- or with another WINS server.
- XXXX note: we may support WINS and also know about other WINS servers
- in the future.
- */
-
- queue_netbios_pkt_wins(d,ClientNMB,
+ if (lp_wins_support())
+ {
+ /* we are a WINS server. */
+ /* XXXX assume that if we are a WINS server that we are therefore
+ not pointing to another WINS server as well. this may later NOT
+ actually be true
+ */
+
+ add_netbios_entry(d,name,type,nb_flags,0,
+ SELF,ipzero,False,lp_wins_support());
+ }
+ else
+ {
+ /* a time-to-live allows us to refresh this name with the WINS server. */
+ queue_netbios_pkt_wins(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
name, type, nb_flags, GET_TTL(0),
False, True, ipzero, ipzero);
+ }
+ }
+ else
+ {
+ queue_netbios_packet(d,ClientNMB,
+ re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
+ name, type, nb_flags, GET_TTL(0),
+ True, True, d->bcast_ip, d->bcast_ip);
}
}
@@ -148,6 +181,8 @@ void add_my_names(void)
for (d = subnetlist; d; d = d->next)
{
+ if (!d->my_interface) continue;
+
/* these names need to be refreshed with the WINS server */
add_my_name_entry(d, myname,0x20,NB_ACTIVE);
add_my_name_entry(d, myname,0x03,NB_ACTIVE);
@@ -160,8 +195,8 @@ void add_my_names(void)
add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
- if (wins) {
- /* the 0x1c name gets added by any WINS server it seems */
+ if (lp_domain_logons() && lp_domain_master()) {
+ /* XXXX the 0x1c is apparently something to do with domain logons */
add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
}
}
@@ -246,8 +281,11 @@ void query_refresh_names(void)
if (!d) return;
+ if (!lasttime) lasttime = t;
if (t - lasttime < NAME_POLL_INTERVAL) return;
+ lasttime = time(NULL);
+
for (n = d->namelist; n; n = n->next)
{
/* only do unique, registered names */
@@ -277,3 +315,4 @@ void query_refresh_names(void)
n->refresh_time += name_refresh_time;
}
}
+
diff --git a/source3/namework.c b/source3/namework.c
index d6a94f17aa..85a07a7dc9 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -622,7 +622,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
- for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
+ for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
}
add_my_subnets(lp_workgroup());
}