#include "includes.h"
extern pstring global_myname;
extern fstring global_myworkgroup;
extern char **my_netbios_names;
extern struct in_addr ipzero;
extern struct in_addr allones_ip;
extern uint16 samba_nb_type;
static void become_domain_master_browser_bcast(char *);
static void become_domain_master_fail(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *fail_name)
{
struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
struct server_record *servrec;
if(!work)
{
DEBUG(0,("become_domain_master_fail: Error - cannot find \
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
return;
}
work->dom_state = DOMAIN_NONE;
if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
{
DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
in workgroup %s on subnet %s\n",
global_myname, work->work_group, subrec->subnet_name));
return;
}
servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
subrec->work_changed = True;
DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
workgroup %s on subnet %s. Couldn't register name %s.\n",
work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
}
static void become_domain_master_stage2(struct subnet_record *subrec,
struct userdata_struct *userdata,
struct nmb_name *registered_name,
uint16 nb_flags,
int ttl, struct in_addr registered_ip)
{
struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
struct server_record *servrec;
if(!work)
{
DEBUG(0,("become_domain_master_stage2: Error - cannot find \
workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
return;
}
if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
{
DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
in workgroup %s on subnet %s\n",
global_myname, registered_name->name, subrec->subnet_name));
work->dom_state = DOMAIN_NONE;
return;
}
work->dom_state = DOMAIN_MST;
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
subrec->work_changed = True;
if( DEBUGLVL( 0 ) )
{
dbgtext( "*****\n\nSamba server %s ", global_myname );
dbgtext( "is now a domain master browser for " );
dbgtext( "workgroup %s ", work->work_group );
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
}
if( subrec == unicast_subnet )
{
struct nmb_name nmbname;
struct in_addr my_first_ip;
make_nmb_name(&nmbname, global_myname, 0x20);
work->dmb_name = nmbname;
my_first_ip = *iface_n_ip(0);
putip((char *)&work->dmb_addr, &my_first_ip);
become_domain_master_browser_bcast(work->work_group);
}
else
{
insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
}
}
static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
{
struct work_record *work;
DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
{
DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
wg_name, subrec->subnet_name));
return;
}
DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
work->dom_state = DOMAIN_WAIT;
register_name(subrec, work->work_group,0x1b,samba_nb_type,
become_domain_master_stage2,
become_domain_master_fail, NULL);
}
static void become_domain_master_query_success(struct subnet_record *subrec,
struct userdata_struct *userdata,
struct nmb_name *nmbname, struct in_addr ip,
struct res_rec *rrec)
{
if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
{
if( DEBUGLVL( 3 ) )
{
dbgtext( "become_domain_master_query_success():\n" );
dbgtext( "Our address (%s) ", inet_ntoa(ip) );
dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
dbgtext( "(domain master browser name) " );
dbgtext( "on subnet %s.\n", subrec->subnet_name );
dbgtext( "Continuing with domain master code.\n" );
}
become_domain_master_stage1(subrec, nmbname->name);
}
else
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "become_domain_master_query_success:\n" );
dbgtext( "There is already a domain master browser at " );
dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
}
}
}
static void become_domain_master_query_fail(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *question_name, int fail_code)
{
if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
{
DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
querying WINS server for name %s.\n",
fail_code, nmb_namestr(question_name)));
return;
}
become_domain_master_stage1(subrec, question_name->name);
}
static void become_domain_master_browser_bcast(char *workgroup_name)
{
struct subnet_record *subrec;
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
{
struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
if (work && (work->dom_state == DOMAIN_NONE))
{
struct nmb_name nmbname;
make_nmb_name(&nmbname,workgroup_name,0x1b);
if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "become_domain_master_browser_bcast:\n" );
dbgtext( "Attempting to become domain master browser on " );
dbgtext( "workgroup %s on subnet %s\n",
workgroup_name, subrec->subnet_name );
}
DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
query_name(subrec, nmbname.name, nmbname.name_type,
become_domain_master_query_success,
become_domain_master_query_fail,
NULL);
}
}
}
}
static void become_domain_master_browser_wins(char *workgroup_name)
{
struct work_record *work;
work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
if (work && (work->dom_state == DOMAIN_NONE))
{
struct nmb_name nmbname;
make_nmb_name(&nmbname,workgroup_name,0x1b);
if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "become_domain_master_browser_wins:\n" );
dbgtext( "Attempting to become domain master browser " );
dbgtext( "on workgroup %s, subnet %s.\n",
workgroup_name, unicast_subnet->subnet_name );
}
DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
for domain master browser name %s on workgroup %s\n",
inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
query_name(unicast_subnet, nmbname.name, nmbname.name_type,
become_domain_master_query_success,
become_domain_master_query_fail,
NULL);
}
}
}
void add_domain_names(time_t t)
{
static time_t lastrun = 0;
if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
return;
lastrun = t;
if (lp_domain_logons())
add_logon_names();
if(lp_domain_master())
{
if(we_are_a_wins_client())
{
become_domain_master_browser_wins(global_myworkgroup);
}
else
become_domain_master_browser_bcast(global_myworkgroup);
}
}