#include "includes.h"
extern struct in_addr allones_ip;
extern uint16 samba_nb_type;
static void become_domain_master_browser_bcast(const char *);
static void become_domain_master_fail(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *fail_name)
{
unstring failname;
struct work_record *work;
struct server_record *servrec;
pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
work = find_workgroup_on_subnet(subrec, failname);
if(!work) {
DEBUG(0,("become_domain_master_fail: Error - cannot find \
workgroup %s on subnet %s\n", failname, 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)
{
unstring regname;
struct work_record *work;
struct server_record *servrec;
pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
work = find_workgroup_on_subnet( subrec, regname);
if(!work) {
DEBUG(0,("become_domain_master_stage2: Error - cannot find \
workgroup %s on subnet %s\n", regname, 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(), regname, 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;
struct in_addr *nip;
make_nmb_name(&nmbname, global_myname(), 0x20);
work->dmb_name = nmbname;
nip = iface_n_ip(0);
if (!nip) {
DEBUG(0,("become_domain_master_stage2: Error. iface_n_ip returned NULL\n"));
return;
}
my_first_ip = *nip;
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, const 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)
{
unstring name;
pull_ascii_nstring(name, sizeof(name), nmbname->name);
if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(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, 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), 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)
{
unstring name;
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;
}
pull_ascii_nstring(name, sizeof(name), question_name->name);
become_domain_master_stage1(subrec, name);
}
static void become_domain_master_browser_bcast(const 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, workgroup_name, nmbname.name_type,
become_domain_master_query_success,
become_domain_master_query_fail,
NULL);
}
}
}
}
static void become_domain_master_browser_wins(const 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 from 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, workgroup_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(lp_workgroup());
} else {
become_domain_master_browser_bcast(lp_workgroup());
}
}
}