mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
nisppass.c: Fixed incorrect parameter usage.
nmbd_become_lmb.c: Add 'force_new_election' parameter to some functions.
This allows the start of the election to be done *after*
the demotion from local master browser is done.
Also changed code so release of 1d name is done
immediately to allow other local master to gain it.
nmbd_elections.c: Ensured no elections are run until we have registered
the WORKGROUP<1e> name that we must listen on to participate
in elections.
nmbd_incomingdgrams.c: Use force_new_election code.
nmbd_namelistdb.c: Make update_name_in_namelist static.
nmbd_subnetdb.c: Fix bug in comparison function. We cannot use memcmp
as structure packing may make this fail.
nmbd_packets.c: Ensure that we only send one release packet when
sending a broadcast packet.
nmbd_workgroupdb.c: Ensure we put the correct value in the ElectionCriterion field.
nmblib.c: Ensure make_nmb_name zero's the struct nmb_name.
Jeremy.
(This used to be commit 1fcb094ba0
)
This commit is contained in:
parent
bc39cff279
commit
d8b0a8bab2
@ -1260,8 +1260,8 @@ void unbecome_local_master_success(struct subnet_record *subrec,
|
||||
struct in_addr released_ip);
|
||||
void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
|
||||
struct nmb_name *fail_name);
|
||||
void release_1d_name( struct subnet_record *subrec, char *workgroup_name);
|
||||
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work);
|
||||
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
|
||||
BOOL force_new_election);
|
||||
void become_local_master_browser(struct subnet_record *subrec, struct work_record *work);
|
||||
void set_workgroup_local_master_browser_name( struct work_record *work, char *newname);
|
||||
|
||||
@ -1335,8 +1335,6 @@ void refresh_my_names(time_t t);
|
||||
|
||||
void set_samba_nb_type(void);
|
||||
BOOL ms_browser_name( char *name, int type );
|
||||
void update_name_in_namelist( struct subnet_record *subrec,
|
||||
struct name_record *namerec );
|
||||
void remove_name_from_namelist( struct subnet_record *subrec,
|
||||
struct name_record *namerec );
|
||||
struct name_record *find_name_on_subnet( struct subnet_record *subrec,
|
||||
|
@ -762,6 +762,7 @@ static int build_dgram(char *buf,struct packet_struct *p)
|
||||
******************************************************************/
|
||||
void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
|
||||
{
|
||||
memset((char *)n, '\0', sizeof(struct nmb_name));
|
||||
StrnCpy(n->name,name,15);
|
||||
strupper(n->name);
|
||||
n->name_type = (unsigned int)type & 0xFF;
|
||||
|
@ -78,7 +78,8 @@ static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
|
||||
state back to potential browser, or none.
|
||||
******************************************************************/
|
||||
|
||||
static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name )
|
||||
static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name,
|
||||
BOOL force_new_election )
|
||||
{
|
||||
struct work_record *work;
|
||||
struct server_record *servrec;
|
||||
@ -129,6 +130,8 @@ in workgroup %s on subnet %s\n",
|
||||
|
||||
remove_permanent_name_from_unicast( subrec, &nmbname);
|
||||
|
||||
if(force_new_election)
|
||||
work->needelection = True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -140,11 +143,15 @@ void unbecome_local_master_success(struct subnet_record *subrec,
|
||||
struct nmb_name *released_name,
|
||||
struct in_addr released_ip)
|
||||
{
|
||||
BOOL force_new_election = False;
|
||||
|
||||
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
|
||||
|
||||
DEBUG(3,("unbecome_local_master_success: released name %s.\n",
|
||||
namestr(released_name)));
|
||||
|
||||
/* Now reset the workgroup and server state. */
|
||||
reset_workgroup_state( subrec, released_name->name );
|
||||
reset_workgroup_state( subrec, released_name->name, force_new_election );
|
||||
|
||||
DEBUG(0,("\n%s ***** Samba name server %s has stopped being a local master browser for workgroup %s \
|
||||
on subnet %s *****\n\n", timestring(), global_myname, released_name->name, subrec->subnet_name));
|
||||
@ -159,6 +166,10 @@ void unbecome_local_master_fail(struct subnet_record *subrec, struct response_re
|
||||
struct nmb_name *fail_name)
|
||||
{
|
||||
struct name_record *namerec;
|
||||
struct userdata_struct *userdata = rrec->userdata;
|
||||
BOOL force_new_election = False;
|
||||
|
||||
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
|
||||
|
||||
DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
|
||||
Removing from namelist anyway.\n", namestr(fail_name)));
|
||||
@ -169,19 +180,18 @@ Removing from namelist anyway.\n", namestr(fail_name)));
|
||||
remove_name_from_namelist(subrec, namerec);
|
||||
|
||||
/* Now reset the workgroup and server state. */
|
||||
reset_workgroup_state( subrec, fail_name->name );
|
||||
reset_workgroup_state( subrec, fail_name->name, force_new_election );
|
||||
|
||||
DEBUG(0,("\n%s ***** Samba name server %s has stopped being a local master browser for workgroup %s \
|
||||
on subnet %s *****\n\n", timestring(), global_myname, fail_name->name, subrec->subnet_name));
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Utility function to remove the WORKGROUP<1d> name called by both
|
||||
success and fail of releasing the MSBROWSE name.
|
||||
Utility function to remove the WORKGROUP<1d> name.
|
||||
******************************************************************/
|
||||
|
||||
void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
|
||||
static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
|
||||
BOOL force_new_election)
|
||||
{
|
||||
struct nmb_name nmbname;
|
||||
struct name_record *namerec;
|
||||
@ -189,10 +199,26 @@ void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
|
||||
make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
|
||||
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
|
||||
{
|
||||
struct userdata_struct *userdata;
|
||||
|
||||
if((userdata = (struct userdata_struct *)malloc(
|
||||
sizeof(struct userdata_struct) + sizeof(BOOL))) == NULL)
|
||||
{
|
||||
DEBUG(0,("release_1d_name: malloc fail.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
userdata->copy_fn = NULL;
|
||||
userdata->free_fn = NULL;
|
||||
userdata->userdata_len = sizeof(BOOL);
|
||||
memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
|
||||
|
||||
release_name(subrec, namerec,
|
||||
unbecome_local_master_success,
|
||||
unbecome_local_master_fail,
|
||||
NULL);
|
||||
userdata);
|
||||
|
||||
free((char *)userdata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,8 +236,6 @@ static void release_msbrowse_name_success(struct subnet_record *subrec,
|
||||
|
||||
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
||||
remove_permanent_name_from_unicast( subrec, released_name);
|
||||
|
||||
release_1d_name( subrec, userdata->data );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -222,7 +246,6 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
|
||||
struct response_record *rrec,
|
||||
struct nmb_name *fail_name)
|
||||
{
|
||||
struct userdata_struct *userdata = rrec->userdata;
|
||||
struct name_record *namerec;
|
||||
|
||||
DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
|
||||
@ -235,20 +258,19 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
|
||||
|
||||
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
||||
remove_permanent_name_from_unicast( subrec, fail_name);
|
||||
|
||||
release_1d_name( subrec, userdata->data );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Unbecome the local master browser.
|
||||
Unbecome the local master browser. If force_new_election is true, restart
|
||||
the election process after we've unbecome the local master.
|
||||
******************************************************************/
|
||||
|
||||
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work)
|
||||
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
|
||||
BOOL force_new_election)
|
||||
{
|
||||
struct server_record *servrec;
|
||||
struct name_record *namerec;
|
||||
struct nmb_name nmbname;
|
||||
struct userdata_struct *userdata;
|
||||
|
||||
/* Sanity check. */
|
||||
|
||||
@ -267,17 +289,12 @@ in workgroup %s on subnet %s\n",
|
||||
/* Set the state to unbecoming. */
|
||||
work->mst_state = MST_UNBECOMING_MASTER;
|
||||
|
||||
/* Setup the userdata for the MSBROWSE name release. */
|
||||
if((userdata = (struct userdata_struct *)malloc( sizeof(struct userdata_struct) + sizeof(fstring)+1)) == NULL)
|
||||
{
|
||||
DEBUG(0,("unbecome_local_master_browser: malloc fail.\n"));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Release the WORKGROUP<1d> name asap to allow another machine to
|
||||
* claim it.
|
||||
*/
|
||||
|
||||
userdata->copy_fn = NULL;
|
||||
userdata->free_fn = NULL;
|
||||
userdata->userdata_len = strlen(work->work_group)+1;
|
||||
pstrcpy(userdata->data, work->work_group);
|
||||
release_1d_name( subrec, work->work_group, force_new_election);
|
||||
|
||||
/* Deregister any browser names we may have. */
|
||||
make_nmb_name(&nmbname, MSBROWSE, 0x1, scope);
|
||||
@ -286,10 +303,16 @@ in workgroup %s on subnet %s\n",
|
||||
release_name(subrec, namerec,
|
||||
release_msbrowse_name_success,
|
||||
release_msbrowse_name_fail,
|
||||
userdata);
|
||||
NULL);
|
||||
}
|
||||
|
||||
free((char *)userdata);
|
||||
/*
|
||||
* Ensure we have sent and processed these release packets
|
||||
* before returning - we don't want to process any election
|
||||
* packets before dealing with the 1d release.
|
||||
*/
|
||||
|
||||
retransmit_or_expire_response_records(time(NULL));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -394,7 +417,7 @@ workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
|
||||
}
|
||||
|
||||
/* Roll back all the way by calling unbecome_local_master_browser(). */
|
||||
unbecome_local_master_browser(subrec, work);
|
||||
unbecome_local_master_browser(subrec, work, False);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -465,7 +488,7 @@ in workgroup %s on subnet %s\n",
|
||||
return;
|
||||
}
|
||||
|
||||
reset_workgroup_state( subrec, work->work_group );
|
||||
reset_workgroup_state( subrec, work->work_group, False );
|
||||
|
||||
DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
|
||||
workgroup %s on subnet %s. Couldn't register name %s.\n",
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
extern int DEBUGLEVEL;
|
||||
|
||||
extern pstring scope;
|
||||
|
||||
extern pstring global_myname;
|
||||
extern fstring global_myworkgroup;
|
||||
|
||||
@ -58,7 +60,7 @@ static void send_election_dgram(struct subnet_record *subrec, char *workgroup_na
|
||||
p = skip_string(p,1);
|
||||
|
||||
send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||
server_name, 0,
|
||||
global_myname, 0,
|
||||
workgroup_name, 0x1e,
|
||||
subrec->bcast_ip, subrec->myip);
|
||||
}
|
||||
@ -117,7 +119,7 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
|
||||
not to become the local master, but we still need one,
|
||||
having detected that one doesn't exist.
|
||||
*/
|
||||
send_election_dgram(subrec, work->work_group, 0, 0, global_myname);
|
||||
send_election_dgram(subrec, work->work_group, 0, 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,8 +173,8 @@ void run_elections(time_t t)
|
||||
|
||||
struct subnet_record *subrec;
|
||||
|
||||
/* Send election packets once a second - note */
|
||||
if (lastime && (t - lastime <= 0))
|
||||
/* Send election packets once every 2 seconds - note */
|
||||
if (lastime && (t - lastime < 2))
|
||||
return;
|
||||
|
||||
lastime = t;
|
||||
@ -185,6 +187,20 @@ void run_elections(time_t t)
|
||||
{
|
||||
if (work->RunningElection)
|
||||
{
|
||||
/*
|
||||
* We can only run an election for a workgroup if we have
|
||||
* registered the WORKGROUP<1e> name, as that's the name
|
||||
* we must listen to.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
|
||||
make_nmb_name(&nmbname, work->work_group, 0x1e, scope);
|
||||
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
||||
DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
|
||||
yet registered on subnet %s\n", namestr(&nmbname), subrec->subnet_name ));
|
||||
continue;
|
||||
}
|
||||
|
||||
send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
|
||||
t - StartupTime, global_myname);
|
||||
|
||||
@ -308,7 +324,7 @@ is not my workgroup.\n", work->work_group, subrec->subnet_name ));
|
||||
DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
|
||||
work->work_group, subrec->subnet_name ));
|
||||
if (AM_LOCAL_MASTER_BROWSER(work))
|
||||
unbecome_local_master_browser(subrec, work);
|
||||
unbecome_local_master_browser(subrec, work, False);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -335,12 +351,29 @@ BOOL check_elections(void)
|
||||
/* Only start an election if we are in the potential browser state. */
|
||||
if (work->needelection && !work->RunningElection && AM_POTENTIAL_MASTER_BROWSER(work))
|
||||
{
|
||||
/*
|
||||
* We can only run an election for a workgroup if we have
|
||||
* registered the WORKGROUP<1e> name, as that's the name
|
||||
* we must listen to.
|
||||
*/
|
||||
struct nmb_name nmbname;
|
||||
|
||||
make_nmb_name(&nmbname, work->work_group, 0x1e, scope);
|
||||
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
||||
DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
|
||||
yet registered on subnet %s\n", namestr(&nmbname), subrec->subnet_name ));
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
|
||||
work->work_group, subrec->subnet_name ));
|
||||
|
||||
work->ElectionCount = 0;
|
||||
work->RunningElection = True;
|
||||
work->needelection = False;
|
||||
|
||||
/* Send a force election packet to begin. */
|
||||
send_election_dgram(subrec, work->work_group, 0, 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -318,12 +318,10 @@ a local master browser for workgroup %s and we think we are master. Forcing elec
|
||||
|
||||
/* We should demote ourself and force an election. */
|
||||
|
||||
unbecome_local_master_browser( subrec, work);
|
||||
unbecome_local_master_browser( subrec, work, True);
|
||||
|
||||
/* The actual election requests are handled in
|
||||
nmbd_election.c */
|
||||
|
||||
work->needelection = True;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -722,10 +720,7 @@ request from %s IP %s state=0x%X\n",
|
||||
for (work = sr->workgrouplist; work; work = work->next)
|
||||
{
|
||||
if (AM_LOCAL_MASTER_BROWSER(work))
|
||||
{
|
||||
unbecome_local_master_browser(sr, work);
|
||||
work->needelection = True;
|
||||
}
|
||||
unbecome_local_master_browser(sr, work, True);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static void upcase_name( struct nmb_name *target, struct nmb_name *source )
|
||||
* Add a new or overwrite an existing namelist entry.
|
||||
* ************************************************************************** **
|
||||
*/
|
||||
void update_name_in_namelist( struct subnet_record *subrec,
|
||||
static void update_name_in_namelist( struct subnet_record *subrec,
|
||||
struct name_record *namerec )
|
||||
{
|
||||
struct name_record *oldrec = NULL;
|
||||
|
@ -602,6 +602,17 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a broadcast release packet, only send once.
|
||||
* This will cause us to remove the name asap. JRA.
|
||||
*/
|
||||
|
||||
if(bcast)
|
||||
{
|
||||
rrec->repeat_count = 0;
|
||||
rrec->repeat_time = 0;
|
||||
}
|
||||
|
||||
return rrec;
|
||||
}
|
||||
|
||||
|
@ -75,12 +75,27 @@ static void add_subnet(struct subnet_record *subrec)
|
||||
|
||||
/* CRH!!! */
|
||||
/* ************************************************************************** ** * This will go away when we move to a "real" database back-end.
|
||||
Note that we cannot use memcmp here as we have no control
|
||||
over how the struct nmb_name structures are packed in memory. JRA.
|
||||
* ************************************************************************** ** */
|
||||
int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
|
||||
{
|
||||
struct name_record *NR = (struct name_record *)Node;
|
||||
struct nmb_name *nmbname = (struct nmb_name *)Item;
|
||||
int ret;
|
||||
|
||||
return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
|
||||
if(nmb_name_equal( &NR->name, nmbname))
|
||||
return 0;
|
||||
|
||||
ret = strcmp( nmbname->name, NR->name.name);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
ret = strcmp( nmbname->scope, NR->name.scope);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
return nmbname->name_type - NR->name.name_type;
|
||||
} /* namelist_entry_compare */
|
||||
/* CRH!!! */
|
||||
|
||||
|
@ -125,7 +125,7 @@ static struct work_record *create_workgroup(char *name, int ttl)
|
||||
/* WfWg uses 01040b01 */
|
||||
/* Win95 uses 01041501 */
|
||||
/* NTAS uses ???????? */
|
||||
work->ElectionCriterion = (MAINTAIN_LIST)|(ELECTION_VERSION<<8);
|
||||
work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8);
|
||||
work->ElectionCriterion |= (lp_os_level() << 24);
|
||||
if (lp_domain_master())
|
||||
work->ElectionCriterion |= 0x80;
|
||||
|
@ -195,7 +195,7 @@ struct nisp_enum_info
|
||||
static void *startnisppwent(BOOL update)
|
||||
{
|
||||
static struct nisp_enum_info res;
|
||||
res.result = nisp_get_nis_list(lp_smb_pass_file());
|
||||
res.result = nisp_get_nis_list(lp_smb_passwd_file());
|
||||
res.enum_entry = 0;
|
||||
return res.result != NULL ? &res : NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user