summaryrefslogtreecommitdiff
path: root/source3/nameelect.c
diff options
context:
space:
mode:
authorSamba Release Account <samba-bugs@samba.org>1996-07-04 19:19:26 +0000
committerSamba Release Account <samba-bugs@samba.org>1996-07-04 19:19:26 +0000
commit7812ff08135318e74f5c286fe4773de8d1423969 (patch)
tree0ff953c4eb4bf2dfa3eb27d5f227a8a8c1384461 /source3/nameelect.c
parent9a08bb015caaf36095244d00b83184e0ebcfdfef (diff)
downloadsamba-7812ff08135318e74f5c286fe4773de8d1423969.tar.gz
samba-7812ff08135318e74f5c286fe4773de8d1423969.tar.bz2
samba-7812ff08135318e74f5c286fe4773de8d1423969.zip
modified become_master() to a state-based system. becoming a master
is now performed in stages: wait for each NetBIOS name to be successfully registered before proceeding to the next stage. tied implicit name registration and release (broadcast method) to the same piece of code as explicit method (via WINS server). created special_browser_name() function that checks __MSBROWSE__ name: this name is ignored by WINS servers apparently. fixed likely incompatibility between refresh_my_names() and add_my_names(). (netbios entries were unlikely to be refreshed). NOTE: none of these changes have been tested. at all. lkcl (This used to be commit 7719fb06524a66ce5e3f30f3152ddb1e200c97f3)
Diffstat (limited to 'source3/nameelect.c')
-rw-r--r--source3/nameelect.c206
1 files changed, 176 insertions, 30 deletions
diff --git a/source3/nameelect.c b/source3/nameelect.c
index 855ea26348..bb219415b8 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -34,6 +34,7 @@ extern int DEBUGLEVEL;
extern pstring scope;
extern pstring myname;
+extern struct in_addr ipzero;
/* machine comment for host announcements */
extern pstring ServerComment;
@@ -149,50 +150,182 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
}
+/****************************************************************************
+ un-register a SELF name that got rejected.
+
+ if this name happens to be rejected when samba is in the process
+ of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
+ or WORKGROUP(1b)) then we must stop being a master browser. sad.
+
+ **************************************************************************/
+void name_unregister_work(struct subnet_record *d, char *name, int name_type)
+{
+ struct work_record *work;
+
+ remove_netbios_name(d,name,name_type,SELF,ipzero);
+
+ if (!(work = find_workgroupstruct(d, name, False))) return;
+
+ if (special_browser_name(name, name_type) ||
+ (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
+ (name_type == 0x1d || name_type == 0x1b)))
+ {
+ int remove_type = 0;
+
+ if (special_browser_name(name, name_type))
+ remove_type = SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
+ if (name_type == 0x1d)
+ remove_type = SV_TYPE_MASTER_BROWSER;
+ if (name_type == 0x1b)
+ remove_type = SV_TYPE_DOMAIN_MASTER;
+
+ become_nonmaster(d, work, remove_type);
+ }
+}
+
+
+/****************************************************************************
+ registers a name.
+
+ if the name being added is a SELF name, we must additionally check
+ whether to proceed to the next stage in samba becoming a master browser.
+
+ **************************************************************************/
+void name_register_work(struct subnet_record *d, char *name, int name_type,
+ int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
+{
+ enum name_source source = ismyip(ip) ? SELF : REGISTER;
+
+ if (source == SELF)
+ {
+ struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
+
+ if (work && work->state != MST_NONE)
+ {
+ /* samba is in the process of working towards master browser-ness.
+ initiate the next stage.
+ */
+ become_master(d, work);
+ }
+ }
+ add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
+}
+
+
/*******************************************************************
- become the master browser
+ become the master browser.
+
+ this is done in stages. note that this could take a while,
+ particularly on a broadcast subnet, as we have to wait for
+ the implicit registration of each name to be accepted.
+
+ as each name is successfully registered, become_master() is
+ called again, in order to initiate the next stage. see
+ dead_netbios_entry() - deals with implicit name registration
+ and response_name_reg() - deals with explicit registration
+ with a WINS server.
+
+ stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1.
+ stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d)
+ stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b)
+ stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...)
+
+ XXXX note: this code still does not cope with the distinction
+ between different types of nodes, particularly between M and P
+ nodes. that comes later.
+
******************************************************************/
-static void become_master(struct subnet_record *d, struct work_record *work)
+void become_master(struct subnet_record *d, struct work_record *work)
{
- uint32 domain_type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_SERVER_UNIX | 0x00400000;
+ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_SERVER_UNIX|0x00400000;
if (!work) return;
- DEBUG(2,("Becoming master for %s\n",work->work_group));
+ DEBUG(2,("Becoming master for %s (stage %d)",work->work_group,work->state));
- work->ServerType |= SV_TYPE_MASTER_BROWSER;
- work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
- work->ElectionCriterion |= 0x5;
+ switch (work->state)
+ {
+ case MST_NONE: /* while we were nothing but a server... */
+ {
+ work->state = MST_WON; /* election win was successful */
+
+ work->ElectionCriterion |= 0x5;
+
+ /* update our server status */
+ 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"));
+
+ /* add special browser name */
+ add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
+
+ break;
+ }
+ case MST_WON: /* while nothing had happened except we won an election... */
+ {
+ work->state = MST_MSB; /* registering MSBROWSE was successful */
+
+ /* 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"));
+
+ /* add master name */
+ add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
- /* add browse, master and general names to database or register with WINS */
- add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
- add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
+ break;
+ }
+ case MST_MSB: /* while we were still only registered MSBROWSE state */
+ {
+ work->state = MST_BROWSER; /* registering WORKGROUP(1d) was successful */
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_MASTER_BROWSER;
+ add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
+
+ if (d->my_interface && work->serverlist == NULL) /* no servers! */
+ {
+ /* ask all servers on our local net to announce to us */
+ announce_request(work, d->bcast_ip);
+ }
+
+ if (lp_domain_master())
+ {
+ DEBUG(2,("third stage: register as domain master\n"));
+ /* add domain master name */
+ add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
+ }
- if (lp_domain_master())
+ break;
+ }
+ case MST_BROWSER: /* while we were still a master browser... */
{
- DEBUG(4,("Domain master: adding names...\n"));
-
- /* add domain master and domain member names or register with WINS */
- add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
-
- work->ServerType |= SV_TYPE_DOMAIN_MASTER;
+ work->state = MST_DOMAIN; /* registering WORKGROUP(1b) was successful */
+
+ /* update our server status */
+ if (lp_domain_master())
+ {
+ work->ServerType |= SV_TYPE_DOMAIN_MASTER;
- if (lp_domain_logons())
- {
- work->ServerType |= SV_TYPE_DOMAIN_CTRL;
- work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
- }
- }
-
- /* update our server status */
- add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
- add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
+ if (lp_domain_logons())
+ {
+ work->ServerType |= SV_TYPE_DOMAIN_CTRL;
+ work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
+ }
+ DEBUG(2,("fourth stage: samba is now a domain master.\n"));
+ add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True);
+ }
- if (d->my_interface)
+ break;
+ }
+ case MST_DOMAIN:
{
- /* ask all servers on our local net to announce to us */
- announce_request(work, d->bcast_ip);
+ /* nothing else to become, at the moment: we are top-dog. */
+ DEBUG(2,("fifth stage: there isn't one yet!\n"));
+ break;
}
+ }
}
@@ -222,6 +355,7 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
work->ElectionCriterion &= ~0x4;
+ work->state = MST_NONE;
/* announce ourselves as no longer active as a master browser. */
announce_server(d, work, work->work_group, myname, 0, 0);
@@ -231,10 +365,19 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
work->ServerType = new_server_type;
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
+ {
+ if (work->state == MST_DOMAIN)
+ work->state = MST_BROWSER;
remove_name_entry(d,work->work_group,0x1b);
+
+ }
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
+ {
+ if (work->state >= MST_BROWSER)
+ work->state = MST_NONE;
remove_name_entry(d,work->work_group,0x1d);
+ }
}
@@ -270,6 +413,8 @@ void run_elections(void)
work->work_group,inet_ntoa(d->bcast_ip)));
work->RunningElection = False;
+ work->state = MST_NONE;
+
become_master(d, work);
}
}
@@ -340,6 +485,7 @@ void process_election(struct packet_struct *p,char *buf)
{
work->needelection = True;
work->ElectionCount=0;
+ work->state = MST_NONE;
}
}
else