/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
#include "includes.h"
-extern int DEBUGLEVEL;
-extern pstring scope;
extern pstring global_myname;
extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
{
/* The name needs to be created on the unicast subnet. */
- add_name_to_subnet( unicast_subnet, nmbname->name, nmbname->name_type,
- nb_type, PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
+ (void)add_name_to_subnet( unicast_subnet, nmbname->name,
+ nmbname->name_type, nb_type,
+ PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
}
else
{
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;
* master browser.
*/
- make_nmb_name(&nmbname, work->work_group, 0x1d, scope);
+ make_nmb_name(&nmbname, work->work_group, 0x1d);
remove_permanent_name_from_unicast( subrec, &nmbname);
+ if(force_new_election)
+ work->needelection = True;
}
/*******************************************************************
Unbecome the local master browser name release success function.
******************************************************************/
-void unbecome_local_master_success(struct subnet_record *subrec,
+static void unbecome_local_master_success(struct subnet_record *subrec,
struct userdata_struct *userdata,
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)));
+ nmb_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));
+ if( DEBUGLVL( 0 ) )
+ {
+ dbgtext( "*****\n\n" );
+ dbgtext( "Samba name server %s ", global_myname );
+ dbgtext( "has stopped being a local master browser " );
+ dbgtext( "for workgroup %s ", released_name->name );
+ dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+ }
}
Unbecome the local master browser name release fail function.
******************************************************************/
-void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
+static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
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)));
+Removing from namelist anyway.\n", nmb_namestr(fail_name)));
/* Do it anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
remove_name_from_namelist(subrec, namerec);
/* Now reset the workgroup and server state. */
- reset_workgroup_state( subrec, fail_name->name );
-
- 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));
+ reset_workgroup_state( subrec, fail_name->name, force_new_election );
+ if( DEBUGLVL( 0 ) )
+ {
+ dbgtext( "*****\n\n" );
+ dbgtext( "Samba name server %s ", global_myname );
+ dbgtext( "has stopped being a local master browser " );
+ dbgtext( "for workgroup %s ", fail_name->name );
+ dbgtext( "on subnet %s\n\n*****\n", 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;
- make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
+ make_nmb_name(&nmbname, workgroup_name, 0x1d);
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
{
+ struct userdata_struct *userdata;
+ int size = sizeof(struct userdata_struct) + sizeof(BOOL);
+
+ if((userdata = (struct userdata_struct *)malloc(size)) == 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);
+
+ zero_free(userdata, size);
}
}
struct in_addr released_ip)
{
DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
- namestr(released_name), subrec->subnet_name ));
+ nmb_namestr(released_name), subrec->subnet_name ));
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
remove_permanent_name_from_unicast( subrec, released_name);
-
- release_1d_name( subrec, userdata->data );
}
/*******************************************************************
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.",
- namestr(fail_name), subrec->subnet_name ));
+ nmb_namestr(fail_name), subrec->subnet_name ));
/* Release the name anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
/* 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. */
DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
on subnet %s\n",work->work_group, subrec->subnet_name));
- if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
+ if(find_server_in_workgroup( work, global_myname) == NULL)
{
DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
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);
+ make_nmb_name(&nmbname, MSBROWSE, 0x1);
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
{
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));
}
/****************************************************************************
master browser as soon as possible that we are a local master browser. */
reset_announce_timer();
- DEBUG(0,("\n%s ***** Samba name server %s is now a local master browser for workgroup %s \
-on subnet %s *****\n\n", timestring(), global_myname, work->work_group, subrec->subnet_name));
+ if( DEBUGLVL( 0 ) )
+ {
+ dbgtext( "*****\n\n" );
+ dbgtext( "Samba name server %s ", global_myname );
+ dbgtext( "is now a local master browser " );
+ dbgtext( "for workgroup %s ", work->work_group );
+ dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+ }
}
struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
-Failed to become a local master browser.\n", namestr(fail_name), subrec->subnet_name));
+Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
if(!work)
{
}
/* Roll back all the way by calling unbecome_local_master_browser(). */
- unbecome_local_master_browser(subrec, work);
+ unbecome_local_master_browser(subrec, work, False);
}
/****************************************************************************
{
char *work_name = rrec->userdata->data;
struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
- struct server_record *servrec;
if(!work)
{
return;
}
- if((servrec = find_server_in_workgroup(work, global_myname)) == NULL)
+ if(find_server_in_workgroup(work, global_myname) == NULL)
{
DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
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",
- work->work_group, subrec->subnet_name, namestr(fail_name)));
+ work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
}
/******************************************************************
void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
{
- struct server_record *servrec;
struct userdata_struct *userdata;
+ int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
/* Sanity check. */
if (!lp_local_master())
return;
}
- if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
+ if(find_server_in_workgroup( work, global_myname) == NULL)
{
DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
in workgroup %s on subnet %s\n",
subrec->work_changed = True;
/* Setup the userdata_struct. */
- if((userdata = (struct userdata_struct *)malloc(sizeof(struct userdata_struct) + sizeof(fstring)+1)) == NULL)
+ if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
{
DEBUG(0,("become_local_master_browser: malloc fail.\n"));
return;
become_local_master_fail1,
userdata);
- free((char *)userdata);
+ zero_free(userdata, size);
}
/***************************************************************