1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

Half-way though the big conversion of all nmbd access to wire elements being

converted to pull/push_ascii. This will not work right at the moment for non
English codepages, but compiles - I will finish the work over the weekend.
Then nmbd should be completely codepage correct.
Jeremy.
This commit is contained in:
Jeremy Allison 0001-01-01 00:00:00 +00:00
parent daf7b5fbd9
commit 236d6adadf
12 changed files with 1896 additions and 1984 deletions

View File

@ -176,124 +176,116 @@ enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
enum master_state
{
MST_NONE,
MST_POTENTIAL,
MST_BACKUP,
MST_MSB,
MST_BROWSER,
MST_UNBECOMING_MASTER
enum master_state {
MST_NONE,
MST_POTENTIAL,
MST_BACKUP,
MST_MSB,
MST_BROWSER,
MST_UNBECOMING_MASTER
};
enum domain_state
{
DOMAIN_NONE,
DOMAIN_WAIT,
DOMAIN_MST
enum domain_state {
DOMAIN_NONE,
DOMAIN_WAIT,
DOMAIN_MST
};
enum logon_state
{
LOGON_NONE,
LOGON_WAIT,
LOGON_SRV
enum logon_state {
LOGON_NONE,
LOGON_WAIT,
LOGON_SRV
};
struct subnet_record;
struct nmb_data
{
uint16 nb_flags; /* Netbios flags. */
int num_ips; /* Number of ip entries. */
struct in_addr *ip; /* The ip list for this name. */
struct nmb_data {
uint16 nb_flags; /* Netbios flags. */
int num_ips; /* Number of ip entries. */
struct in_addr *ip; /* The ip list for this name. */
enum name_source source; /* Where the name came from. */
enum name_source source; /* Where the name came from. */
time_t death_time; /* The time the record must be removed (do not remove if 0). */
time_t refresh_time; /* The time the record should be refreshed. */
time_t death_time; /* The time the record must be removed (do not remove if 0). */
time_t refresh_time; /* The time the record should be refreshed. */
SMB_BIG_UINT id; /* unique id */
struct in_addr wins_ip; /* the adress of the wins server this record comes from */
SMB_BIG_UINT id; /* unique id */
struct in_addr wins_ip; /* the adress of the wins server this record comes from */
int wins_flags; /* similar to the netbios flags but different ! */
int wins_flags; /* similar to the netbios flags but different ! */
};
/* This structure represents an entry in a local netbios name list. */
struct name_record
{
ubi_trNode node[1];
struct subnet_record *subnet;
struct nmb_name name; /* The netbios name. */
struct nmb_data data; /* The netbios data. */
};
struct name_record {
ubi_trNode node[1];
struct subnet_record *subnet;
struct nmb_name name; /* The netbios name. */
struct nmb_data data; /* The netbios data. */
};
/* Browser cache for synchronising browse lists. */
struct browse_cache_record
{
ubi_dlNode node[1];
pstring lmb_name;
pstring work_group;
struct in_addr ip;
time_t sync_time;
time_t death_time; /* The time the record must be removed. */
};
struct browse_cache_record {
ubi_dlNode node[1];
pstring lmb_name;
pstring work_group;
struct in_addr ip;
time_t sync_time;
time_t death_time; /* The time the record must be removed. */
};
/* This is used to hold the list of servers in my domain, and is
contained within lists of domains. */
struct server_record
{
struct server_record *next;
struct server_record *prev;
struct server_record {
struct server_record *next;
struct server_record *prev;
struct subnet_record *subnet;
struct subnet_record *subnet;
struct server_info_struct serv;
time_t death_time;
struct server_info_struct serv;
time_t death_time;
};
/* A workgroup structure. It contains a list of servers. */
struct work_record
{
struct work_record *next;
struct work_record *prev;
struct work_record {
struct work_record *next;
struct work_record *prev;
struct subnet_record *subnet;
struct subnet_record *subnet;
struct server_record *serverlist;
struct server_record *serverlist;
/* Stage of development from non-local-master up to local-master browser. */
enum master_state mst_state;
/* Stage of development from non-local-master up to local-master browser. */
enum master_state mst_state;
/* Stage of development from non-domain-master to domain-master browser. */
enum domain_state dom_state;
/* Stage of development from non-domain-master to domain-master browser. */
enum domain_state dom_state;
/* Stage of development from non-logon-server to logon server. */
enum logon_state log_state;
/* Stage of development from non-logon-server to logon server. */
enum logon_state log_state;
/* Work group info. */
fstring work_group;
int token; /* Used when communicating with backup browsers. */
fstring local_master_browser_name; /* Current local master browser. */
/* Work group info. */
fstring work_group;
int token; /* Used when communicating with backup browsers. */
fstring local_master_browser_name; /* Current local master browser. */
/* Announce info. */
time_t lastannounce_time;
int announce_interval;
BOOL needannounce;
/* Announce info. */
time_t lastannounce_time;
int announce_interval;
BOOL needannounce;
/* Timeout time for this workgroup. 0 means permanent. */
time_t death_time;
/* Timeout time for this workgroup. 0 means permanent. */
time_t death_time;
/* Election info */
BOOL RunningElection;
BOOL needelection;
int ElectionCount;
uint32 ElectionCriterion;
/* Election info */
BOOL RunningElection;
BOOL needelection;
int ElectionCount;
uint32 ElectionCriterion;
/* Domain master browser info. Used for efficient syncs. */
struct nmb_name dmb_name;
struct in_addr dmb_addr;
/* Domain master browser info. Used for efficient syncs. */
struct nmb_name dmb_name;
struct in_addr dmb_addr;
};
/* typedefs needed to define copy & free functions for userdata. */
@ -305,10 +297,10 @@ typedef void (*userdata_free_fn)(struct userdata_struct *);
/* Structure to define any userdata passed around. */
struct userdata_struct {
userdata_copy_fn copy_fn;
userdata_free_fn free_fn;
unsigned int userdata_len;
char data[16]; /* 16 is to ensure alignment/padding on all systems */
userdata_copy_fn copy_fn;
userdata_free_fn free_fn;
unsigned int userdata_len;
char data[16]; /* 16 is to ensure alignment/padding on all systems */
};
struct response_record;
@ -382,33 +374,32 @@ typedef void (*node_status_fail_function)( struct subnet_record *,
/* Initiated name queries are recorded in this list to track any responses. */
struct response_record
{
struct response_record *next;
struct response_record *prev;
struct response_record {
struct response_record *next;
struct response_record *prev;
uint16 response_id;
uint16 response_id;
/* Callbacks for packets received or not. */
response_function resp_fn;
timeout_response_function timeout_fn;
/* Callbacks for packets received or not. */
response_function resp_fn;
timeout_response_function timeout_fn;
/* Callbacks for the request succeeding or not. */
success_function success_fn;
fail_function fail_fn;
/* Callbacks for the request succeeding or not. */
success_function success_fn;
fail_function fail_fn;
struct packet_struct *packet;
struct packet_struct *packet;
struct userdata_struct *userdata;
struct userdata_struct *userdata;
int num_msgs;
int num_msgs;
time_t repeat_time;
time_t repeat_interval;
int repeat_count;
time_t repeat_time;
time_t repeat_interval;
int repeat_count;
/* Recursion protection. */
BOOL in_expiration_processing;
/* Recursion protection. */
BOOL in_expiration_processing;
};
/* A subnet structure. It contains a list of workgroups and netbios names. */
@ -420,42 +411,41 @@ struct response_record
*/
enum subnet_type {
NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
};
struct subnet_record
{
struct subnet_record *next;
struct subnet_record *prev;
struct subnet_record {
struct subnet_record *next;
struct subnet_record *prev;
char *subnet_name; /* For Debug identification. */
enum subnet_type type; /* To catagorize the subnet. */
char *subnet_name; /* For Debug identification. */
enum subnet_type type; /* To catagorize the subnet. */
struct work_record *workgrouplist; /* List of workgroups. */
ubi_trRoot namelist[1]; /* List of netbios names. */
struct response_record *responselist; /* List of responses expected. */
struct work_record *workgrouplist; /* List of workgroups. */
ubi_trRoot namelist[1]; /* List of netbios names. */
struct response_record *responselist; /* List of responses expected. */
BOOL namelist_changed;
BOOL work_changed;
BOOL namelist_changed;
BOOL work_changed;
struct in_addr bcast_ip;
struct in_addr mask_ip;
struct in_addr myip;
int nmb_sock; /* socket to listen for unicast 137. */
int dgram_sock; /* socket to listen for unicast 138. */
struct in_addr bcast_ip;
struct in_addr mask_ip;
struct in_addr myip;
int nmb_sock; /* socket to listen for unicast 137. */
int dgram_sock; /* socket to listen for unicast 138. */
};
/* A resource record. */
struct res_rec {
struct nmb_name rr_name;
int rr_type;
int rr_class;
int ttl;
int rdlength;
char rdata[MAX_DGRAM_SIZE];
struct nmb_name rr_name;
int rr_type;
int rr_class;
int ttl;
int rdlength;
char rdata[MAX_DGRAM_SIZE];
};
/* Define these so we can pass info back to caller of name_query */
@ -467,35 +457,34 @@ struct res_rec {
#define NM_FLAGS_B 0x01 /* Broadcast */
/* An nmb packet. */
struct nmb_packet
{
struct {
int name_trn_id;
int opcode;
BOOL response;
struct {
BOOL bcast;
BOOL recursion_available;
BOOL recursion_desired;
BOOL trunc;
BOOL authoritative;
} nm_flags;
int rcode;
int qdcount;
int ancount;
int nscount;
int arcount;
} header;
struct nmb_packet {
struct {
int name_trn_id;
int opcode;
BOOL response;
struct {
BOOL bcast;
BOOL recursion_available;
BOOL recursion_desired;
BOOL trunc;
BOOL authoritative;
} nm_flags;
int rcode;
int qdcount;
int ancount;
int nscount;
int arcount;
} header;
struct {
struct nmb_name question_name;
int question_type;
int question_class;
} question;
struct {
struct nmb_name question_name;
int question_type;
int question_class;
} question;
struct res_rec *answers;
struct res_rec *nsrecs;
struct res_rec *additional;
struct res_rec *answers;
struct res_rec *nsrecs;
struct res_rec *additional;
};
/* msg_type field options - from rfc1002. */
@ -511,23 +500,23 @@ struct nmb_packet
/* A datagram - this normally contains SMB data in the data[] array. */
struct dgram_packet {
struct {
int msg_type;
struct {
enum node_type node_type;
BOOL first;
BOOL more;
} flags;
int dgm_id;
struct in_addr source_ip;
int source_port;
int dgm_length;
int packet_offset;
} header;
struct nmb_name source_name;
struct nmb_name dest_name;
int datasize;
char data[MAX_DGRAM_SIZE];
struct {
int msg_type;
struct {
enum node_type node_type;
BOOL first;
BOOL more;
} flags;
int dgm_id;
struct in_addr source_ip;
int source_port;
int dgm_length;
int packet_offset;
} header;
struct nmb_name source_name;
struct nmb_name dest_name;
int datasize;
char data[MAX_DGRAM_SIZE];
};
/* Define a structure used to queue packets. This will be a linked
@ -535,18 +524,18 @@ struct dgram_packet {
struct packet_struct
{
struct packet_struct *next;
struct packet_struct *prev;
BOOL locked;
struct in_addr ip;
int port;
int fd;
time_t timestamp;
enum packet_type packet_type;
union {
struct nmb_packet nmb;
struct dgram_packet dgram;
} packet;
struct packet_struct *next;
struct packet_struct *prev;
BOOL locked;
struct in_addr ip;
int port;
int fd;
time_t timestamp;
enum packet_type packet_type;
union {
struct nmb_packet nmb;
struct dgram_packet dgram;
} packet;
};
/* NETLOGON opcodes */

View File

@ -124,6 +124,7 @@ size_t __unsafe_string_function_usage_here_char__(void);
#define pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1)
#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
#define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1)
#define nstrcpy(d,s) safe_strcpy((d), (s),sizeof(nstring)-1)
/* the addition of the DEVELOPER checks in safe_strcpy means we must
* update a lot of code. To make this a little easier here are some

View File

@ -1484,9 +1484,11 @@ struct cnotify_fns {
#include "smb_macros.h"
typedef char nstring[16];
/* A netbios name structure. */
struct nmb_name {
char name[16];
nstring name;
char scope[64];
unsigned int name_type;
};
@ -1494,7 +1496,7 @@ struct nmb_name {
/* A netbios node status array element. */
struct node_status {
char name[16];
nstring name;
unsigned char type;
unsigned char flags;
};

View File

@ -529,6 +529,11 @@ size_t push_ascii_pstring(void *dest, const char *src)
return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
}
size_t push_ascii_nstring(void *dest, const char *src)
{
return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
}
/**
* Copy a string from a dos codepage source to a unix char* destination.
*
@ -582,6 +587,11 @@ size_t pull_ascii_fstring(char *dest, const void *src)
return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
}
size_t pull_ascii_nstring(char *dest, const void *src)
{
return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
}
/**
* Copy a string from a char* src to a unicode destination.
*

View File

@ -303,6 +303,7 @@ static BOOL reload_nmbd_services(BOOL test)
* We use buf here to return BOOL result to process() when reload_interfaces()
* detects that there are no subnets.
**************************************************************************** */
static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len)
{
write_browse_list( 0, True );
@ -650,126 +651,120 @@ static BOOL open_sockets(BOOL isdaemon, int port)
log_stdout = True;
}
if ( log_stdout && Fork ) {
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
exit(1);
}
if ( log_stdout && Fork ) {
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
exit(1);
}
setup_logging( argv[0], log_stdout );
setup_logging( argv[0], log_stdout );
reopen_logs();
reopen_logs();
DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
if ( !reload_nmbd_services(False) )
return(-1);
if ( !reload_nmbd_services(False) )
return(-1);
if(!init_names())
return -1;
if(!init_names())
return -1;
reload_nmbd_services( True );
reload_nmbd_services( True );
if (strequal(lp_workgroup(),"*"))
{
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
exit(1);
}
if (strequal(lp_workgroup(),"*")) {
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
exit(1);
}
set_samba_nb_type();
set_samba_nb_type();
if (!is_daemon && !is_a_socket(0))
{
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
is_daemon = True;
}
if (!is_daemon && !is_a_socket(0)) {
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
is_daemon = True;
}
if (is_daemon && !opt_interactive)
{
DEBUG( 2, ( "Becoming a daemon.\n" ) );
become_daemon(Fork);
}
if (is_daemon && !opt_interactive) {
DEBUG( 2, ( "Becoming a daemon.\n" ) );
become_daemon(Fork);
}
#if HAVE_SETPGID
/*
* If we're interactive we want to set our own process group for
* signal management.
*/
if (opt_interactive)
setpgid( (pid_t)0, (pid_t)0 );
/*
* If we're interactive we want to set our own process group for
* signal management.
*/
if (opt_interactive)
setpgid( (pid_t)0, (pid_t)0 );
#endif
#ifndef SYNC_DNS
/* Setup the async dns. We do it here so it doesn't have all the other
stuff initialised and thus chewing memory and sockets */
if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
start_async_dns();
}
/* Setup the async dns. We do it here so it doesn't have all the other
stuff initialised and thus chewing memory and sockets */
if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
start_async_dns();
}
#endif
if (!directory_exist(lp_lockdir(), NULL)) {
mkdir(lp_lockdir(), 0755);
}
if (!directory_exist(lp_lockdir(), NULL)) {
mkdir(lp_lockdir(), 0755);
}
pidfile_create("nmbd");
message_init();
message_register(MSG_FORCE_ELECTION, nmbd_message_election);
message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
message_register(MSG_SHUTDOWN, nmbd_terminate);
message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
pidfile_create("nmbd");
message_init();
message_register(MSG_FORCE_ELECTION, nmbd_message_election);
message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
message_register(MSG_SHUTDOWN, nmbd_terminate);
message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
if ( !open_sockets( is_daemon, global_nmb_port ) ) {
kill_async_dns_child();
return 1;
}
if ( !open_sockets( is_daemon, global_nmb_port ) ) {
kill_async_dns_child();
return 1;
}
/* Determine all the IP addresses we have. */
load_interfaces();
/* Determine all the IP addresses we have. */
load_interfaces();
/* Create an nmbd subnet record for each of the above. */
if( False == create_subnets() )
{
DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
kill_async_dns_child();
exit(1);
}
/* Create an nmbd subnet record for each of the above. */
if( False == create_subnets() ) {
DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
kill_async_dns_child();
exit(1);
}
/* Load in any static local names. */
load_lmhosts_file(dyn_LMHOSTSFILE);
DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
/* Load in any static local names. */
load_lmhosts_file(dyn_LMHOSTSFILE);
DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
/* If we are acting as a WINS server, initialise data structures. */
if( !initialise_wins() )
{
DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
kill_async_dns_child();
exit(1);
}
/* If we are acting as a WINS server, initialise data structures. */
if( !initialise_wins() ) {
DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
kill_async_dns_child();
exit(1);
}
/*
* Register nmbd primary workgroup and nmbd names on all
* the broadcast subnets, and on the WINS server (if specified).
* Also initiate the startup of our primary workgroup (start
* elections if we are setup as being able to be a local
* master browser.
*/
/*
* Register nmbd primary workgroup and nmbd names on all
* the broadcast subnets, and on the WINS server (if specified).
* Also initiate the startup of our primary workgroup (start
* elections if we are setup as being able to be a local
* master browser.
*/
if( False == register_my_workgroup_and_names() )
{
DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
kill_async_dns_child();
exit(1);
}
if( False == register_my_workgroup_and_names() ) {
DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
kill_async_dns_child();
exit(1);
}
/* We can only take signals in the select. */
BlockSignals( True, SIGTERM );
/* We can only take signals in the select. */
BlockSignals( True, SIGTERM );
process();
process();
if (dbf)
x_fclose(dbf);
kill_async_dns_child();
return(0);
if (dbf)
x_fclose(dbf);
kill_async_dns_child();
return(0);
}

View File

@ -3,7 +3,7 @@
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
Copyright (C) Jeremy Allison 1994-1998
Copyright (C) Jeremy Allison 1994-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -37,36 +37,37 @@ 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;
nstring failname;
struct work_record *work;
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;
}
pull_ascii_nstring(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;
}
/* Set the state back to DOMAIN_NONE. */
work->dom_state = DOMAIN_NONE;
/* Set the state back to DOMAIN_NONE. */
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 \
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;
}
global_myname(), work->work_group, subrec->subnet_name));
return;
}
/* Update our server status. */
servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
/* Update our server status. */
servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
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)));
work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
}
/****************************************************************************
@ -79,115 +80,112 @@ static void become_domain_master_stage2(struct subnet_record *subrec,
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;
nstring regname;
struct work_record *work;
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;
}
pull_ascii_nstring(regname, registered_name->name);
work = find_workgroup_on_subnet( subrec, regname);
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
{
DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
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(), registered_name->name, subrec->subnet_name));
work->dom_state = DOMAIN_NONE;
return;
}
global_myname(), regname, subrec->subnet_name));
work->dom_state = DOMAIN_NONE;
return;
}
/* Set the state in the workgroup structure. */
work->dom_state = DOMAIN_MST; /* Become domain master. */
/* Set the state in the workgroup structure. */
work->dom_state = DOMAIN_MST; /* Become domain master. */
/* Update our server status. */
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
/* Update our server status. */
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Tell the namelist writer to write out a change. */
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( 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;
if( subrec == unicast_subnet ) {
struct nmb_name nmbname;
struct in_addr my_first_ip;
/* Put our name and first IP address into the
workgroup struct as domain master browser. This
will stop us syncing with ourself if we are also
a local master browser. */
/* Put our name and first IP address into the
workgroup struct as domain master browser. This
will stop us syncing with ourself if we are also
a local master browser. */
make_nmb_name(&nmbname, global_myname(), 0x20);
make_nmb_name(&nmbname, global_myname(), 0x20);
work->dmb_name = nmbname;
/* Pick the first interface ip address as the domain master browser ip. */
my_first_ip = *iface_n_ip(0);
work->dmb_name = nmbname;
/* Pick the first interface ip address as the domain master browser ip. */
my_first_ip = *iface_n_ip(0);
putip((char *)&work->dmb_addr, &my_first_ip);
putip((char *)&work->dmb_addr, &my_first_ip);
/* We successfully registered by unicast with the
WINS server. We now expect to become the domain
master on the local subnets. If this fails, it's
probably a 1.9.16p2 to 1.9.16p11 server's fault.
/* We successfully registered by unicast with the
WINS server. We now expect to become the domain
master on the local subnets. If this fails, it's
probably a 1.9.16p2 to 1.9.16p11 server's fault.
This is a configuration issue that should be addressed
by the network administrator - you shouldn't have
several machines configured as a domain master browser
for the same WINS scope (except if they are 1.9.17 or
greater, and you know what you're doing.
This is a configuration issue that should be addressed
by the network administrator - you shouldn't have
several machines configured as a domain master browser
for the same WINS scope (except if they are 1.9.17 or
greater, and you know what you're doing.
see docs/DOMAIN.txt.
see docs/DOMAIN.txt.
*/
become_domain_master_browser_bcast(work->work_group);
}
else
{
/*
* Now we are a domain master on a broadcast subnet, we need to add
* the WORKGROUP<1b> name to the unicast subnet so that we can answer
* unicast requests sent to this name. This bug wasn't found for a while
* as it is strange to have a DMB without using WINS. JRA.
*/
insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
}
*/
become_domain_master_browser_bcast(work->work_group);
} else {
/*
* Now we are a domain master on a broadcast subnet, we need to add
* the WORKGROUP<1b> name to the unicast subnet so that we can answer
* unicast requests sent to this name. This bug wasn't found for a while
* as it is strange to have a DMB without using WINS. JRA.
*/
insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
}
}
/****************************************************************************
Start the name registration process when becoming a Domain Master Browser
on a subnet.
****************************************************************************/
****************************************************************************/
static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name)
{
struct work_record *work;
struct work_record *work;
DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
/* First, find the workgroup on the subnet. */
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;
}
/* First, find the workgroup on the subnet. */
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;
DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
work->dom_state = DOMAIN_WAIT;
/* WORKGROUP<1b> is the domain master browser name. */
register_name(subrec, work->work_group,0x1b,samba_nb_type,
become_domain_master_stage2,
become_domain_master_fail, NULL);
/* WORKGROUP<1b> is the domain master browser name. */
register_name(subrec, work->work_group,0x1b,samba_nb_type,
become_domain_master_stage2,
become_domain_master_fail, NULL);
}
/****************************************************************************
@ -202,37 +200,35 @@ static void become_domain_master_query_success(struct subnet_record *subrec,
struct nmb_name *nmbname, struct in_addr ip,
struct res_rec *rrec)
{
/* If the given ip is not ours, then we can't become a domain
controler as the name is already registered.
*/
nstring name;
pull_ascii_nstring(name, nmbname->name);
/* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
address or zero ip for this query. Pretend this is ok. */
/* If the given ip is not ours, then we can't become a domain
controler as the name is already registered.
*/
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" );
}
/* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
address or zero ip for this query. Pretend this is ok. */
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 );
}
}
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 );
}
}
}
/****************************************************************************
@ -245,18 +241,21 @@ static void become_domain_master_query_fail(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *question_name, int fail_code)
{
/* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
then this is a failure. Otherwise, not finding the name is what we want. */
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;
}
nstring name;
/* Otherwise - not having the name allows us to register it. */
become_domain_master_stage1(subrec, question_name->name);
/* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
then this is a failure. Otherwise, not finding the name is what we want. */
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;
}
/* Otherwise - not having the name allows us to register it. */
pull_ascii_nstring(name, question_name->name);
become_domain_master_stage1(subrec, name);
}
/****************************************************************************
@ -265,47 +264,43 @@ querying WINS server for name %s.\n",
static void become_domain_master_browser_bcast(const char *workgroup_name)
{
struct subnet_record *subrec;
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);
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 (work && (work->dom_state == DOMAIN_NONE)) {
struct nmb_name nmbname;
make_nmb_name(&nmbname,workgroup_name,0x1b);
/*
* Check for our name on the given broadcast subnet first, only initiate
* further processing if we cannot find it.
*/
/*
* Check for our name on the given broadcast subnet first, only initiate
* further processing if we cannot find it.
*/
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 );
}
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 );
}
/* Send out a query to establish whether there's a
domain controller on the local subnet. If not,
we can become a domain controller.
*/
/* Send out a query to establish whether there's a
domain controller on the local subnet. If not,
we can become a domain controller.
*/
DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
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);
}
}
}
query_name(subrec, workgroup_name, nmbname.name_type,
become_domain_master_query_success,
become_domain_master_query_fail,
NULL);
}
}
}
}
/****************************************************************************
@ -314,46 +309,43 @@ for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_nam
static void become_domain_master_browser_wins(const char *workgroup_name)
{
struct work_record *work;
struct work_record *work;
work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
if (work && (work->dom_state == DOMAIN_NONE))
{
struct nmb_name nmbname;
if (work && (work->dom_state == DOMAIN_NONE)) {
struct nmb_name nmbname;
make_nmb_name(&nmbname,workgroup_name,0x1b);
make_nmb_name(&nmbname,workgroup_name,0x1b);
/*
* Check for our name on the unicast subnet first, only initiate
* further processing if we cannot find it.
*/
/*
* Check for our name on the unicast subnet first, only initiate
* further processing if we cannot find it.
*/
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 );
}
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 );
}
/* Send out a query to establish whether there's a
domain master broswer registered with WINS. If not,
we can become a domain master browser.
*/
/* Send out a query to establish whether there's a
domain master broswer registered with WINS. If not,
we can become a domain master browser.
*/
DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
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));
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);
}
}
query_name(unicast_subnet, workgroup_name, nmbname.name_type,
become_domain_master_query_success,
become_domain_master_query_fail,
NULL);
}
}
}
/****************************************************************************
@ -363,34 +355,32 @@ for domain master browser name %s on workgroup %s\n",
void add_domain_names(time_t t)
{
static time_t lastrun = 0;
static time_t lastrun = 0;
if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
return;
if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
return;
lastrun = t;
lastrun = t;
/* Do the "internet group" - <1c> names. */
if (lp_domain_logons())
add_logon_names();
/* Do the "internet group" - <1c> names. */
if (lp_domain_logons())
add_logon_names();
/* Do the domain master names. */
if(lp_domain_master())
{
if(we_are_a_wins_client())
{
/* We register the WORKGROUP<1b> name with the WINS
server first, and call add_domain_master_bcast()
only if this is successful.
/* Do the domain master names. */
if(lp_domain_master()) {
if(we_are_a_wins_client()) {
/* We register the WORKGROUP<1b> name with the WINS
server first, and call add_domain_master_bcast()
only if this is successful.
This results in domain logon services being gracefully provided,
as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
cannot provide domain master / domain logon services.
*/
become_domain_master_browser_wins(lp_workgroup());
}
else
become_domain_master_browser_bcast(lp_workgroup());
}
This results in domain logon services being gracefully provided,
as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
cannot provide domain master / domain logon services.
*/
become_domain_master_browser_wins(lp_workgroup());
} else {
become_domain_master_browser_bcast(lp_workgroup());
}
}
}

View File

@ -3,7 +3,7 @@
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
Copyright (C) Jeremy Allison 1994-1998
Copyright (C) Jeremy Allison 1994-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -33,21 +33,20 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
void insert_permanent_name_into_unicast( struct subnet_record *subrec,
struct nmb_name *nmbname, uint16 nb_type )
{
struct name_record *namerec;
nstring name;
struct name_record *namerec;
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
{
/* The name needs to be created on the unicast subnet. */
(void)add_name_to_subnet( unicast_subnet, nmbname->name,
nmbname->name_type, nb_type,
PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
}
else
{
/* The name already exists on the unicast subnet. Add our local
IP for the given broadcast subnet to the name. */
add_ip_to_name_record( namerec, subrec->myip);
}
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
pull_ascii_nstring(name, nmbname->name);
/* The name needs to be created on the unicast subnet. */
(void)add_name_to_subnet( unicast_subnet, name,
nmbname->name_type, nb_type,
PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
} else {
/* The name already exists on the unicast subnet. Add our local
IP for the given broadcast subnet to the name. */
add_ip_to_name_record( namerec, subrec->myip);
}
}
/*******************************************************************
@ -57,15 +56,14 @@ void insert_permanent_name_into_unicast( struct subnet_record *subrec,
static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
struct nmb_name *nmbname )
{
struct name_record *namerec;
struct name_record *namerec;
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
{
/* Remove this broadcast subnet IP address from the name. */
remove_ip_from_name_record( namerec, subrec->myip);
if(namerec->data.num_ips == 0)
remove_name_from_namelist( unicast_subnet, namerec);
}
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
/* Remove this broadcast subnet IP address from the name. */
remove_ip_from_name_record( namerec, subrec->myip);
if(namerec->data.num_ips == 0)
remove_name_from_namelist( unicast_subnet, namerec);
}
}
/*******************************************************************
@ -73,60 +71,58 @@ 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, const char *workgroup_name,
BOOL force_new_election )
{
struct work_record *work;
struct server_record *servrec;
struct nmb_name nmbname;
struct work_record *work;
struct server_record *servrec;
struct nmb_name nmbname;
if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
{
DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
subnet %s.\n", workgroup_name, subrec->subnet_name ));
return;
}
return;
}
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
{
DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
in workgroup %s on subnet %s\n",
global_myname(), work->work_group, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
global_myname(), work->work_group, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
/* Update our server status - remove any master flag and replace
it with the potential browser flag. */
servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
/* Update our server status - remove any master flag and replace
it with the potential browser flag. */
servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Reset our election flags. */
work->ElectionCriterion &= ~0x4;
/* Reset our election flags. */
work->ElectionCriterion &= ~0x4;
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
/* Forget who the local master browser was for
this workgroup. */
/* Forget who the local master browser was for
this workgroup. */
set_workgroup_local_master_browser_name( work, "");
set_workgroup_local_master_browser_name( work, "");
/*
* Ensure the IP address of this subnet is not registered as one
* of the IP addresses of the WORKGROUP<1d> name on the unicast
* subnet. This undoes what we did below when we became a local
* master browser.
*/
/*
* Ensure the IP address of this subnet is not registered as one
* of the IP addresses of the WORKGROUP<1d> name on the unicast
* subnet. This undoes what we did below when we became a local
* master browser.
*/
make_nmb_name(&nmbname, work->work_group, 0x1d);
make_nmb_name(&nmbname, work->work_group, 0x1d);
remove_permanent_name_from_unicast( subrec, &nmbname);
remove_permanent_name_from_unicast( subrec, &nmbname);
if(force_new_election)
work->needelection = True;
if(force_new_election)
work->needelection = True;
}
/*******************************************************************
@ -138,24 +134,25 @@ static void unbecome_local_master_success(struct subnet_record *subrec,
struct nmb_name *released_name,
struct in_addr released_ip)
{
BOOL force_new_election = False;
BOOL force_new_election = False;
nstring relname;
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
DEBUG(3,("unbecome_local_master_success: released name %s.\n",
nmb_namestr(released_name)));
DEBUG(3,("unbecome_local_master_success: released name %s.\n",
nmb_namestr(released_name)));
/* Now reset the workgroup and server state. */
reset_workgroup_state( subrec, released_name->name, force_new_election );
/* Now reset the workgroup and server state. */
pull_ascii_nstring(relname, released_name->name);
reset_workgroup_state( subrec, relname, 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 ", released_name->name );
dbgtext( "on subnet %s\n\n*****\n", 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 ", relname );
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
}
}
@ -166,67 +163,66 @@ static void unbecome_local_master_success(struct subnet_record *subrec,
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;
struct name_record *namerec;
struct userdata_struct *userdata = rrec->userdata;
BOOL force_new_election = False;
nstring failname;
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
Removing from namelist anyway.\n", nmb_namestr(fail_name)));
/* Do it anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
if(namerec)
remove_name_from_namelist(subrec, namerec);
/* Do it anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
if(namerec)
remove_name_from_namelist(subrec, namerec);
/* Now reset the workgroup and server state. */
reset_workgroup_state( subrec, fail_name->name, force_new_election );
/* Now reset the workgroup and server state. */
pull_ascii_nstring(failname, fail_name->name);
reset_workgroup_state( subrec, failname, 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 );
}
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 ", failname );
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
}
}
/*******************************************************************
Utility function to remove the WORKGROUP<1d> name.
******************************************************************/
static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
BOOL force_new_election)
{
struct nmb_name nmbname;
struct name_record *namerec;
struct nmb_name nmbname;
struct name_record *namerec;
make_nmb_name(&nmbname, workgroup_name, 0x1d);
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
{
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
make_nmb_name(&nmbname, workgroup_name, 0x1d);
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
{
DEBUG(0,("release_1d_name: malloc fail.\n"));
return;
}
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));
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,
userdata);
release_name(subrec, namerec,
unbecome_local_master_success,
unbecome_local_master_fail,
userdata);
zero_free(userdata, size);
}
zero_free(userdata, size);
}
}
/*******************************************************************
@ -238,11 +234,11 @@ static void release_msbrowse_name_success(struct subnet_record *subrec,
struct nmb_name *released_name,
struct in_addr released_ip)
{
DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
nmb_namestr(released_name), subrec->subnet_name ));
DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
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);
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
remove_permanent_name_from_unicast( subrec, released_name);
}
/*******************************************************************
@ -253,18 +249,18 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *fail_name)
{
struct name_record *namerec;
struct name_record *namerec;
DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
nmb_namestr(fail_name), subrec->subnet_name ));
DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
nmb_namestr(fail_name), subrec->subnet_name ));
/* Release the name anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
if(namerec)
remove_name_from_namelist(subrec, namerec);
/* Release the name anyway. */
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
if(namerec)
remove_name_from_namelist(subrec, namerec);
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
remove_permanent_name_from_unicast( subrec, fail_name);
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
remove_permanent_name_from_unicast( subrec, fail_name);
}
/*******************************************************************
@ -275,50 +271,48 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
BOOL force_new_election)
{
struct name_record *namerec;
struct nmb_name nmbname;
struct name_record *namerec;
struct nmb_name nmbname;
/* Sanity check. */
DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
on subnet %s\n",work->work_group, subrec->subnet_name));
if(find_server_in_workgroup( work, global_myname()) == NULL)
{
DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
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",
global_myname(), work->work_group, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
global_myname(), work->work_group, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
/* Set the state to unbecoming. */
work->mst_state = MST_UNBECOMING_MASTER;
/* Set the state to unbecoming. */
work->mst_state = MST_UNBECOMING_MASTER;
/*
* Release the WORKGROUP<1d> name asap to allow another machine to
* claim it.
*/
/*
* Release the WORKGROUP<1d> name asap to allow another machine to
* claim it.
*/
release_1d_name( subrec, work->work_group, force_new_election);
release_1d_name( subrec, work->work_group, force_new_election);
/* Deregister any browser names we may have. */
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,
NULL);
}
/* Deregister any browser names we may have. */
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,
NULL);
}
/*
* 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.
*/
/*
* 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));
retransmit_or_expire_response_records(time(NULL));
}
/****************************************************************************
@ -332,104 +326,107 @@ static void become_local_master_stage2(struct subnet_record *subrec,
uint16 nb_flags,
int ttl, struct in_addr registered_ip)
{
int i = 0;
struct server_record *sl;
struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
struct server_record *servrec;
int i = 0;
struct server_record *sl;
struct work_record *work;
struct server_record *servrec;
nstring regname;
if(!work)
{
DEBUG(0,("become_local_master_stage2: Error - cannot find \
workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
return;
}
pull_ascii_nstring(regname, registered_name->name);
work = find_workgroup_on_subnet( subrec, regname);
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
{
DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
if(!work) {
DEBUG(0,("become_local_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_local_master_stage2: Error - cannot find server %s \
in workgroup %s on subnet %s\n",
global_myname(), registered_name->name, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
global_myname(), regname, subrec->subnet_name));
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
return;
}
DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
on subnet %s\n", work->work_group, subrec->subnet_name));
work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
/* update our server status */
servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
/* update our server status */
servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Add this name to the workgroup as local master browser. */
set_workgroup_local_master_browser_name( work, global_myname());
/* Add this name to the workgroup as local master browser. */
set_workgroup_local_master_browser_name( work, global_myname());
/* Count the number of servers we have on our list. If it's
less than 10 (just a heuristic) request the servers
to announce themselves.
*/
for( sl = work->serverlist; sl != NULL; sl = sl->next)
i++;
/* Count the number of servers we have on our list. If it's
less than 10 (just a heuristic) request the servers
to announce themselves.
*/
for( sl = work->serverlist; sl != NULL; sl = sl->next)
i++;
if (i < 10)
{
/* Ask all servers on our local net to announce to us. */
broadcast_announce_request(subrec, work);
}
if (i < 10) {
/* Ask all servers on our local net to announce to us. */
broadcast_announce_request(subrec, work);
}
/*
* Now we are a local master on a broadcast subnet, we need to add
* the WORKGROUP<1d> name to the unicast subnet so that we can answer
* unicast requests sent to this name. We can create this name directly on
* the unicast subnet as a WINS server always returns true when registering
* this name, and discards the registration. We use the number of IP
* addresses registered to this name as a reference count, as we
* remove this broadcast subnet IP address from it when we stop becoming a local
* master browser for this broadcast subnet.
*/
/*
* Now we are a local master on a broadcast subnet, we need to add
* the WORKGROUP<1d> name to the unicast subnet so that we can answer
* unicast requests sent to this name. We can create this name directly on
* the unicast subnet as a WINS server always returns true when registering
* this name, and discards the registration. We use the number of IP
* addresses registered to this name as a reference count, as we
* remove this broadcast subnet IP address from it when we stop becoming a local
* master browser for this broadcast subnet.
*/
insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
/* Reset the announce master browser timer so that we try and tell a domain
master browser as soon as possible that we are a local master browser. */
reset_announce_timer();
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 );
}
/* Reset the announce master browser timer so that we try and tell a domain
master browser as soon as possible that we are a local master browser. */
reset_announce_timer();
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 );
}
}
/****************************************************************************
Failed to register the WORKGROUP<1d> name.
****************************************************************************/
static void become_local_master_fail2(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);
nstring failname;
struct work_record *work;
DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
if(!work)
{
DEBUG(0,("become_local_master_fail2: Error - cannot find \
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
return;
}
pull_ascii_nstring(failname, fail_name->name);
work = find_workgroup_on_subnet( subrec, failname);
/* Roll back all the way by calling unbecome_local_master_browser(). */
unbecome_local_master_browser(subrec, work, False);
if(!work) {
DEBUG(0,("become_local_master_fail2: Error - cannot find \
workgroup %s on subnet %s\n", failname, subrec->subnet_name));
return;
}
/* Roll back all the way by calling unbecome_local_master_browser(). */
unbecome_local_master_browser(subrec, work, False);
}
/****************************************************************************
@ -442,35 +439,34 @@ static void become_local_master_stage1(struct subnet_record *subrec,
uint16 nb_flags,
int ttl, struct in_addr registered_ip)
{
char *work_name = userdata->data;
struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
char *work_name = userdata->data;
struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
if(!work)
{
DEBUG(0,("become_local_master_stage1: Error - cannot find \
workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
return;
}
if(!work) {
DEBUG(0,("become_local_master_stage1: Error - cannot find \
%s on subnet %s\n", work_name, subrec->subnet_name));
return;
}
DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
work->work_group));
DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
work->work_group));
work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
/*
* We registered the MSBROWSE name on a broadcast subnet, now need to add
* the MSBROWSE name to the unicast subnet so that we can answer
* unicast requests sent to this name. We create this name directly on
* the unicast subnet.
*/
/*
* We registered the MSBROWSE name on a broadcast subnet, now need to add
* the MSBROWSE name to the unicast subnet so that we can answer
* unicast requests sent to this name. We create this name directly on
* the unicast subnet.
*/
insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
/* Attempt to register the WORKGROUP<1d> name. */
register_name(subrec, work->work_group,0x1d,samba_nb_type,
become_local_master_stage2,
become_local_master_fail2,
NULL);
/* Attempt to register the WORKGROUP<1d> name. */
register_name(subrec, work->work_group,0x1d,samba_nb_type,
become_local_master_stage2,
become_local_master_fail2,
NULL);
}
/****************************************************************************
@ -481,29 +477,27 @@ static void become_local_master_fail1(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *fail_name)
{
char *work_name = rrec->userdata->data;
struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
char *work_name = rrec->userdata->data;
struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
if(!work)
{
DEBUG(0,("become_local_master_fail1: Error - cannot find \
if(!work) {
DEBUG(0,("become_local_master_fail1: Error - cannot find \
workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
return;
}
return;
}
if(find_server_in_workgroup(work, global_myname()) == NULL)
{
DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
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",
global_myname(), work->work_group, subrec->subnet_name));
return;
}
global_myname(), work->work_group, subrec->subnet_name));
return;
}
reset_workgroup_state( subrec, work->work_group, False );
reset_workgroup_state( subrec, work->work_group, False );
DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
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, nmb_namestr(fail_name)));
work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
}
/******************************************************************
@ -517,61 +511,57 @@ workgroup %s on subnet %s. Couldn't register name %s.\n",
void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
{
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
/* Sanity check. */
if (!lp_local_master())
{
DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
return;
}
/* Sanity check. */
if (!lp_local_master()) {
DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
return;
}
if(!AM_POTENTIAL_MASTER_BROWSER(work))
{
DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
work->mst_state ));
return;
}
if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
work->mst_state ));
return;
}
if(find_server_in_workgroup( work, global_myname()) == NULL)
{
DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
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",
global_myname(), work->work_group, subrec->subnet_name));
return;
}
global_myname(), work->work_group, subrec->subnet_name));
return;
}
DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
%s on subnet %s\n", work->work_group, subrec->subnet_name));
DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
work->mst_state = MST_BACKUP; /* an election win was successful */
DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
work->mst_state = MST_BACKUP; /* an election win was successful */
work->ElectionCriterion |= 0x5;
work->ElectionCriterion |= 0x5;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Tell the namelist writer to write out a change. */
subrec->work_changed = True;
/* Setup the userdata_struct. */
if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
{
DEBUG(0,("become_local_master_browser: malloc fail.\n"));
return;
}
/* Setup the userdata_struct. */
if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
DEBUG(0,("become_local_master_browser: malloc fail.\n"));
return;
}
userdata->copy_fn = NULL;
userdata->free_fn = NULL;
userdata->userdata_len = strlen(work->work_group)+1;
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
userdata->copy_fn = NULL;
userdata->free_fn = NULL;
userdata->userdata_len = strlen(work->work_group)+1;
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
/* Register the special browser group name. */
register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
become_local_master_stage1,
become_local_master_fail1,
userdata);
/* Register the special browser group name. */
register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
become_local_master_stage1,
become_local_master_fail1,
userdata);
zero_free(userdata, size);
zero_free(userdata, size);
}
/***************************************************************
@ -583,7 +573,7 @@ in workgroup %s on subnet %s\n",
void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
{
DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
for workgroup %s.\n", newname, work->work_group ));
#if 0
@ -600,5 +590,5 @@ local_master_browser_name for workgroup %s to workgroup name.\n",
}
#endif
fstrcpy(work->local_master_browser_name, newname);
fstrcpy(work->local_master_browser_name, newname);
}

View File

@ -80,8 +80,8 @@ void update_browser_death_time( struct browse_cache_record *browc )
*
* ************************************************************************** **
*/
struct browse_cache_record *create_browser_in_lmb_cache( char *work_name,
char *browser_name,
struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
const char *browser_name,
struct in_addr ip )
{
struct browse_cache_record *browc;
@ -134,7 +134,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name,
*
* ************************************************************************** **
*/
struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name )
struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name )
{
struct browse_cache_record *browc;

View File

@ -3,7 +3,7 @@
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
Copyright (C) Jeremy Allison 1994-1998
Copyright (C) Jeremy Allison 1994-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -29,74 +29,70 @@ extern ubi_dlList lmb_browserlist[];
/****************************************************************************
As a domain master browser, do a sync with a local master browser.
**************************************************************************/
static void sync_with_lmb(struct browse_cache_record *browc)
{
struct work_record *work;
struct work_record *work;
if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "sync_with_lmb:\n" );
dbgtext( "Failed to get a workgroup for a local master browser " );
dbgtext( "cache entry workgroup " );
dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
}
return;
}
if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "sync_with_lmb:\n" );
dbgtext( "Failed to get a workgroup for a local master browser " );
dbgtext( "cache entry workgroup " );
dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
}
return;
}
/* We should only be doing this if we are a domain master browser for
the given workgroup. Ensure this is so. */
/* We should only be doing this if we are a domain master browser for
the given workgroup. Ensure this is so. */
if(!AM_DOMAIN_MASTER_BROWSER(work))
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "sync_with_lmb:\n" );
dbgtext( "We are trying to sync with a local master browser " );
dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
dbgtext( "and we are not a domain master browser on this workgroup.\n" );
dbgtext( "Error!\n" );
}
return;
}
if(!AM_DOMAIN_MASTER_BROWSER(work)) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "sync_with_lmb:\n" );
dbgtext( "We are trying to sync with a local master browser " );
dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
dbgtext( "and we are not a domain master browser on this workgroup.\n" );
dbgtext( "Error!\n" );
}
return;
}
if( DEBUGLVL( 2 ) )
{
dbgtext( "sync_with_lmb:\n" );
dbgtext( "Initiating sync with local master browser " );
dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
dbgtext( "for workgroup %s\n", browc->work_group );
}
if( DEBUGLVL( 2 ) ) {
dbgtext( "sync_with_lmb:\n" );
dbgtext( "Initiating sync with local master browser " );
dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
dbgtext( "for workgroup %s\n", browc->work_group );
}
sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
}
/****************************************************************************
Sync or expire any local master browsers.
**************************************************************************/
void dmb_expire_and_sync_browser_lists(time_t t)
{
static time_t last_run = 0;
struct browse_cache_record *browc;
static time_t last_run = 0;
struct browse_cache_record *browc;
/* Only do this every 20 seconds. */
if (t - last_run < 20)
return;
/* Only do this every 20 seconds. */
if (t - last_run < 20)
return;
last_run = t;
last_run = t;
expire_lmb_browsers(t);
expire_lmb_browsers(t);
for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
browc;
browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
{
if (browc->sync_time < t)
sync_with_lmb(browc);
}
for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
browc;
browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
if (browc->sync_time < t)
sync_with_lmb(browc);
}
}
/****************************************************************************
@ -105,46 +101,43 @@ As a local master browser, send an announce packet to the domain master browser.
static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
{
pstring outbuf;
fstring myname;
char *p;
pstring outbuf;
fstring myname;
char *p;
if(ismyip(work->dmb_addr))
{
if( DEBUGLVL( 2 ) )
{
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
dbgtext( "We are both a domain and a local master browser for " );
dbgtext( "workgroup %s. ", work->work_group );
dbgtext( "Do not announce to ourselves.\n" );
}
return;
}
if(ismyip(work->dmb_addr)) {
if( DEBUGLVL( 2 ) ) {
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
dbgtext( "We are both a domain and a local master browser for " );
dbgtext( "workgroup %s. ", work->work_group );
dbgtext( "Do not announce to ourselves.\n" );
}
return;
}
memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
SCVAL(p,0,ANN_MasterAnnouncement);
p++;
memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
SCVAL(p,0,ANN_MasterAnnouncement);
p++;
fstrcpy(myname, global_myname());
strupper_m(myname);
myname[15]='\0';
push_pstring_base(p, myname, outbuf);
fstrcpy(myname, global_myname());
strupper_m(myname);
myname[15]='\0';
/* The call below does CH_UNIX -> CH_DOS conversion. JRA */
push_pstring_base(p, myname, outbuf);
p = skip_string(p,1);
p = skip_string(p,1);
if( DEBUGLVL( 4 ) )
{
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
dbgtext( "Sending local master announce to " );
dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
work->work_group );
}
if( DEBUGLVL( 4 ) ) {
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
dbgtext( "Sending local master announce to " );
dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
work->work_group );
}
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
global_myname(), 0x0, work->dmb_name.name, 0x0,
work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
}
/****************************************************************************
@ -153,17 +146,19 @@ As a local master browser, do a sync with a domain master browser.
static void sync_with_dmb(struct work_record *work)
{
if( DEBUGLVL( 2 ) )
{
dbgtext( "sync_with_dmb:\n" );
dbgtext( "Initiating sync with domain master browser " );
dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
dbgtext( "for workgroup %s\n", work->work_group );
}
nstring dmb_name;
sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type,
work->dmb_addr, False, True);
if( DEBUGLVL( 2 ) ) {
dbgtext( "sync_with_dmb:\n" );
dbgtext( "Initiating sync with domain master browser " );
dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
dbgtext( "for workgroup %s\n", work->work_group );
}
pull_ascii_nstring(dmb_name, work->dmb_name.name);
sync_browse_lists(work, dmb_name, work->dmb_name.name_type,
work->dmb_addr, False, True);
}
/****************************************************************************
@ -175,78 +170,69 @@ static void domain_master_node_status_success(struct subnet_record *subrec,
struct res_rec *answers,
struct in_addr from_ip)
{
struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
if( work == NULL )
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Unable to find workgroup " );
dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
}
return;
}
if( work == NULL ) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Unable to find workgroup " );
dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
}
return;
}
if( DEBUGLVL( 3 ) )
{
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Success in node status for workgroup " );
dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
}
if( DEBUGLVL( 3 ) ) {
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Success in node status for workgroup " );
dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
}
/* Go through the list of names found at answers->rdata and look for
the first SERVER<0x20> name. */
if(answers->rdata != NULL)
{
char *p = answers->rdata;
int numnames = CVAL(p, 0);
if(answers->rdata != NULL) {
char *p = answers->rdata;
int numnames = CVAL(p, 0);
p += 1;
p += 1;
while (numnames--)
{
char qname[17];
uint16 nb_flags;
int name_type;
while (numnames--) {
nstring qname;
uint16 nb_flags;
int name_type;
StrnCpy(qname,p,15);
name_type = CVAL(p,15);
nb_flags = get_nb_flags(&p[16]);
trim_string(qname,NULL," ");
pull_ascii_nstring(qname, p);
name_type = CVAL(p,15);
nb_flags = get_nb_flags(&p[16]);
trim_string(qname,NULL," ");
p += 18;
p += 18;
if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
{
struct nmb_name nmbname;
if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
struct nmb_name nmbname;
make_nmb_name(&nmbname, qname, name_type);
make_nmb_name(&nmbname, qname, name_type);
/* Copy the dmb name and IP address
into the workgroup struct. */
/* Copy the dmb name and IP address
into the workgroup struct. */
work->dmb_name = nmbname;
putip((char *)&work->dmb_addr, &from_ip);
work->dmb_name = nmbname;
putip((char *)&work->dmb_addr, &from_ip);
/* Do the local master browser announcement to the domain
master browser name and IP. */
announce_local_master_browser_to_domain_master_browser( work );
/* Do the local master browser announcement to the domain
master browser name and IP. */
announce_local_master_browser_to_domain_master_browser( work );
/* Now synchronise lists with the domain master browser. */
sync_with_dmb(work);
break;
}
}
}
else
if( DEBUGLVL( 0 ) )
{
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
dbgtext( "%s.\n", inet_ntoa(from_ip) );
}
/* Now synchronise lists with the domain master browser. */
sync_with_dmb(work);
break;
}
}
} else if( DEBUGLVL( 0 ) ) {
dbgtext( "domain_master_node_status_success:\n" );
dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
dbgtext( "%s.\n", inet_ntoa(from_ip) );
}
}
/****************************************************************************
@ -256,16 +242,15 @@ static void domain_master_node_status_success(struct subnet_record *subrec,
static void domain_master_node_status_fail(struct subnet_record *subrec,
struct response_record *rrec)
{
struct userdata_struct *userdata = rrec->userdata;
struct userdata_struct *userdata = rrec->userdata;
if( DEBUGLVL( 0 ) )
{
dbgtext( "domain_master_node_status_fail:\n" );
dbgtext( "Doing a node status request to the domain master browser\n" );
dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
dbgtext( "Cannot sync browser lists.\n" );
}
if( DEBUGLVL( 0 ) ) {
dbgtext( "domain_master_node_status_fail:\n" );
dbgtext( "Doing a node status request to the domain master browser\n" );
dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
dbgtext( "Cannot sync browser lists.\n" );
}
}
/****************************************************************************
@ -276,100 +261,99 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec,
struct userdata_struct *userdata_in,
struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
{
/*
* Unfortunately, finding the IP address of the Domain Master Browser,
* as we have here, is not enough. We need to now do a sync to the
* SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
* respond to the SMBSERVER name. To get this name from IP
* address we do a Node status request, and look for the first
* NAME<0x20> in the response, and take that as the server name.
* We also keep a cache of the Domain Master Browser name for this
* workgroup in the Workgroup struct, so that if the same IP addess
* is returned every time, we don't need to do the node status
* request.
*/
/*
* Unfortunately, finding the IP address of the Domain Master Browser,
* as we have here, is not enough. We need to now do a sync to the
* SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
* respond to the SMBSERVER name. To get this name from IP
* address we do a Node status request, and look for the first
* NAME<0x20> in the response, and take that as the server name.
* We also keep a cache of the Domain Master Browser name for this
* workgroup in the Workgroup struct, so that if the same IP addess
* is returned every time, we don't need to do the node status
* request.
*/
struct work_record *work;
struct nmb_name nmbname;
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
struct work_record *work;
struct nmb_name nmbname;
struct userdata_struct *userdata;
size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
nstring qname;
if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "find_domain_master_name_query_success:\n" );
dbgtext( "Failed to find workgroup %s\n", q_name->name );
}
return;
pull_ascii_nstring(qname, q_name->name);
if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "find_domain_master_name_query_success:\n" );
dbgtext( "Failed to find workgroup %s\n", qname);
}
return;
}
/* First check if we already have a dmb for this workgroup. */
if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip))
{
/* Do the local master browser announcement to the domain
master browser name and IP. */
announce_local_master_browser_to_domain_master_browser( work );
if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) {
/* Do the local master browser announcement to the domain
master browser name and IP. */
announce_local_master_browser_to_domain_master_browser( work );
/* Now synchronise lists with the domain master browser. */
sync_with_dmb(work);
return;
}
else
zero_ip(&work->dmb_addr);
/* Now synchronise lists with the domain master browser. */
sync_with_dmb(work);
return;
} else {
zero_ip(&work->dmb_addr);
}
/* Now initiate the node status request. */
/* Now initiate the node status request. */
/* We used to use the name "*",0x0 here, but some Windows
* servers don't answer that name. However we *know* they
* have the name workgroup#1b (as we just looked it up).
* So do the node status request on this name instead.
* Found at LBL labs. JRA.
*/
/* We used to use the name "*",0x0 here, but some Windows
* servers don't answer that name. However we *know* they
* have the name workgroup#1b (as we just looked it up).
* So do the node status request on this name instead.
* Found at LBL labs. JRA.
*/
make_nmb_name(&nmbname,work->work_group,0x1b);
make_nmb_name(&nmbname,work->work_group,0x1b);
/* Put the workgroup name into the userdata so we know
what workgroup we're talking to when the reply comes
back. */
/* Put the workgroup name into the userdata so we know
what workgroup we're talking to when the reply comes
back. */
/* Setup the userdata_struct - this is copied so we can use
a stack variable for this. */
if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
{
DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
return;
}
/* Setup the userdata_struct - this is copied so we can use
a stack variable for this. */
userdata->copy_fn = NULL;
userdata->free_fn = NULL;
userdata->userdata_len = strlen(work->work_group)+1;
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
return;
}
node_status( subrec, &nmbname, answer_ip,
domain_master_node_status_success,
domain_master_node_status_fail,
userdata);
userdata->copy_fn = NULL;
userdata->free_fn = NULL;
userdata->userdata_len = strlen(work->work_group)+1;
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
zero_free(userdata, size);
node_status( subrec, &nmbname, answer_ip,
domain_master_node_status_success,
domain_master_node_status_fail,
userdata);
zero_free(userdata, size);
}
/****************************************************************************
Function called when a query for a WORKGROUP<1b> name fails.
****************************************************************************/
static void find_domain_master_name_query_fail(struct subnet_record *subrec,
struct response_record *rrec,
struct nmb_name *question_name, int fail_code)
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "find_domain_master_name_query_fail:\n" );
dbgtext( "Unable to find the Domain Master Browser name " );
dbgtext( "%s for the workgroup %s.\n",
nmb_namestr(question_name), question_name->name );
dbgtext( "Unable to sync browse lists in this workgroup.\n" );
}
if( DEBUGLVL( 0 ) ) {
dbgtext( "find_domain_master_name_query_fail:\n" );
dbgtext( "Unable to find the Domain Master Browser name " );
dbgtext( "%s for the workgroup %s.\n",
nmb_namestr(question_name), question_name->name );
dbgtext( "Unable to sync browse lists in this workgroup.\n" );
}
}
/****************************************************************************
@ -381,27 +365,20 @@ full domain browse lists from it onto the given subnet.
void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
struct work_record *work)
{
struct nmb_name nmbname;
/* Only do this if we are using a WINS server. */
if(we_are_a_wins_client() == False) {
if( DEBUGLVL( 10 ) ) {
dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
dbgtext( "Ignoring, as we are not a WINS client.\n" );
}
return;
}
/* Only do this if we are using a WINS server. */
if(we_are_a_wins_client() == False)
{
if( DEBUGLVL( 10 ) )
{
dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
dbgtext( "Ignoring, as we are not a WINS client.\n" );
}
return;
}
make_nmb_name(&nmbname,work->work_group,0x1b);
/* First, query for the WORKGROUP<1b> name from the WINS server. */
query_name(unicast_subnet, nmbname.name, nmbname.name_type,
/* First, query for the WORKGROUP<1b> name from the WINS server. */
query_name(unicast_subnet, work->work_group, 0x1b,
find_domain_master_name_query_success,
find_domain_master_name_query_fail,
NULL);
}
/****************************************************************************
@ -421,89 +398,81 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub
struct res_rec *answers,
struct in_addr from_ip)
{
struct work_record *work;
fstring server_name;
struct work_record *work;
fstring server_name;
server_name[0] = 0;
server_name[0] = 0;
if( DEBUGLVL( 3 ) )
{
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
}
if( DEBUGLVL( 3 ) ) {
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
}
/*
* Go through the list of names found at answers->rdata and look for
* the first WORKGROUP<0x1b> name.
*/
/*
* Go through the list of names found at answers->rdata and look for
* the first WORKGROUP<0x1b> name.
*/
if(answers->rdata != NULL)
{
char *p = answers->rdata;
int numnames = CVAL(p, 0);
if(answers->rdata != NULL) {
char *p = answers->rdata;
int numnames = CVAL(p, 0);
p += 1;
p += 1;
while (numnames--)
{
char qname[17];
uint16 nb_flags;
int name_type;
while (numnames--) {
nstring qname;
uint16 nb_flags;
int name_type;
StrnCpy(qname,p,15);
name_type = CVAL(p,15);
nb_flags = get_nb_flags(&p[16]);
trim_string(qname,NULL," ");
pull_ascii_nstring(qname, p);
name_type = CVAL(p,15);
nb_flags = get_nb_flags(&p[16]);
trim_string(qname,NULL," ");
p += 18;
p += 18;
if(!(nb_flags & NB_GROUP) && (name_type == 0x00) &&
server_name[0] == 0) {
/* this is almost certainly the server netbios name */
fstrcpy(server_name, qname);
continue;
}
if(!(nb_flags & NB_GROUP) && (name_type == 0x00) &&
server_name[0] == 0) {
/* this is almost certainly the server netbios name */
fstrcpy(server_name, qname);
continue;
}
if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
{
if( DEBUGLVL( 5 ) )
{
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
dbgtext( "is a domain master browser for workgroup " );
dbgtext( "%s. Adding this name.\n", qname );
}
if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
if( DEBUGLVL( 5 ) ) {
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
dbgtext( "is a domain master browser for workgroup " );
dbgtext( "%s. Adding this name.\n", qname );
}
/*
* If we don't already know about this workgroup, add it
* to the workgroup list on the unicast_subnet.
*/
if((work = find_workgroup_on_subnet( subrec, qname)) == NULL)
{
struct nmb_name nmbname;
/*
* Add it - with an hour in the cache.
*/
if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
return;
/*
* If we don't already know about this workgroup, add it
* to the workgroup list on the unicast_subnet.
*/
/* remember who the master is */
fstrcpy(work->local_master_browser_name, server_name);
make_nmb_name(&nmbname, server_name, 0x20);
work->dmb_name = nmbname;
work->dmb_addr = from_ip;
}
break;
}
}
}
else
if( DEBUGLVL( 0 ) )
{
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
dbgtext( "%s.\n", inet_ntoa(from_ip) );
}
if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
struct nmb_name nmbname;
/*
* Add it - with an hour in the cache.
*/
if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
return;
/* remember who the master is */
fstrcpy(work->local_master_browser_name, server_name);
make_nmb_name(&nmbname, server_name, 0x20);
work->dmb_name = nmbname;
work->dmb_addr = from_ip;
}
break;
}
}
} else if( DEBUGLVL( 0 ) ) {
dbgtext( "get_domain_master_name_node_status_success:\n" );
dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
dbgtext( "%s.\n", inet_ntoa(from_ip) );
}
}
/****************************************************************************
@ -513,13 +482,12 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub
static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
struct response_record *rrec)
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "get_domain_master_name_node_status_fail:\n" );
dbgtext( "Doing a node status request to the domain master browser " );
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
dbgtext( "Cannot get workgroup name.\n" );
}
if( DEBUGLVL( 0 ) ) {
dbgtext( "get_domain_master_name_node_status_fail:\n" );
dbgtext( "Doing a node status request to the domain master browser " );
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
dbgtext( "Cannot get workgroup name.\n" );
}
}
/****************************************************************************
@ -530,58 +498,53 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub
struct userdata_struct *userdata_in,
struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
{
/*
* We now have a list of all the domain master browsers for all workgroups
* that have registered with the WINS server. Now do a node status request
* to each one and look for the first 1b name in the reply. This will be
* the workgroup name that we will add to the unicast subnet as a 'non-local'
* workgroup.
*/
/*
* We now have a list of all the domain master browsers for all workgroups
* that have registered with the WINS server. Now do a node status request
* to each one and look for the first 1b name in the reply. This will be
* the workgroup name that we will add to the unicast subnet as a 'non-local'
* workgroup.
*/
struct nmb_name nmbname;
struct in_addr send_ip;
int i;
struct nmb_name nmbname;
struct in_addr send_ip;
int i;
if( DEBUGLVL( 5 ) )
{
dbgtext( "find_all_domain_master_names_query_succes:\n" );
dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
dbgtext( "IP addresses for Domain Master Browsers.\n" );
}
if( DEBUGLVL( 5 ) ) {
dbgtext( "find_all_domain_master_names_query_succes:\n" );
dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
dbgtext( "IP addresses for Domain Master Browsers.\n" );
}
for(i = 0; i < rrec->rdlength / 6; i++)
{
/* Initiate the node status requests. */
make_nmb_name(&nmbname, "*", 0);
for(i = 0; i < rrec->rdlength / 6; i++) {
/* Initiate the node status requests. */
make_nmb_name(&nmbname, "*", 0);
putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
/*
* Don't send node status requests to ourself.
*/
/*
* Don't send node status requests to ourself.
*/
if(ismyip( send_ip ))
{
if( DEBUGLVL( 5 ) )
{
dbgtext( "find_all_domain_master_names_query_succes:\n" );
dbgtext( "Not sending node status to our own IP " );
dbgtext( "%s.\n", inet_ntoa(send_ip) );
}
continue;
}
if(ismyip( send_ip )) {
if( DEBUGLVL( 5 ) ) {
dbgtext( "find_all_domain_master_names_query_succes:\n" );
dbgtext( "Not sending node status to our own IP " );
dbgtext( "%s.\n", inet_ntoa(send_ip) );
}
continue;
}
if( DEBUGLVL( 5 ) )
{
dbgtext( "find_all_domain_master_names_query_success:\n" );
dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
}
if( DEBUGLVL( 5 ) ) {
dbgtext( "find_all_domain_master_names_query_success:\n" );
dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
}
node_status( subrec, &nmbname, send_ip,
get_domain_master_name_node_status_success,
get_domain_master_name_node_status_fail,
NULL);
}
node_status( subrec, &nmbname, send_ip,
get_domain_master_name_node_status_success,
get_domain_master_name_node_status_fail,
NULL);
}
}
/****************************************************************************
@ -591,13 +554,12 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec
struct response_record *rrec,
struct nmb_name *question_name, int fail_code)
{
if( DEBUGLVL( 10 ) )
{
dbgtext( "find_domain_master_name_query_fail:\n" );
dbgtext( "WINS server did not reply to a query for name " );
dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
}
if( DEBUGLVL( 10 ) ) {
dbgtext( "find_domain_master_name_query_fail:\n" );
dbgtext( "WINS server did not reply to a query for name " );
dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
}
}
/****************************************************************************
@ -608,43 +570,39 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec
<1b> name in the reply - this is the workgroup name. Add this to the unicast
subnet. This is expensive, so we only do this every 15 minutes.
**************************************************************************/
void collect_all_workgroup_names_from_wins_server(time_t t)
{
static time_t lastrun = 0;
struct work_record *work;
struct nmb_name nmbname;
static time_t lastrun = 0;
struct work_record *work;
/* Only do this if we are using a WINS server. */
if(we_are_a_wins_client() == False)
return;
/* Only do this if we are using a WINS server. */
if(we_are_a_wins_client() == False)
return;
/* Check to see if we are a domain master browser on the unicast subnet. */
if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL)
{
if( DEBUGLVL( 0 ) )
{
dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
}
return;
}
/* Check to see if we are a domain master browser on the unicast subnet. */
if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
}
return;
}
if(!AM_DOMAIN_MASTER_BROWSER(work))
return;
if(!AM_DOMAIN_MASTER_BROWSER(work))
return;
if ((lastrun != 0) && (t < lastrun + (15 * 60)))
return;
if ((lastrun != 0) && (t < lastrun + (15 * 60)))
return;
lastrun = t;
lastrun = t;
make_nmb_name(&nmbname,"*",0x1b);
/* First, query for the *<1b> name from the WINS server. */
query_name(unicast_subnet, nmbname.name, nmbname.name_type,
find_all_domain_master_names_query_success,
find_all_domain_master_names_query_fail,
NULL);
/* First, query for the *<1b> name from the WINS server. */
query_name(unicast_subnet, "*", 0x1b,
find_all_domain_master_names_query_success,
find_all_domain_master_names_query_fail,
NULL);
}
@ -656,6 +614,7 @@ To prevent exponential network traffic with large numbers of workgroups
we use a randomised system where sync probability is inversely proportional
to the number of known workgroups
**************************************************************************/
void sync_all_dmbs(time_t t)
{
static time_t lastrun = 0;
@ -669,7 +628,8 @@ void sync_all_dmbs(time_t t)
/* Check to see if we are a domain master browser on the
unicast subnet. */
work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
if (!work) return;
if (!work)
return;
if (!AM_DOMAIN_MASTER_BROWSER(work))
return;
@ -687,7 +647,10 @@ void sync_all_dmbs(time_t t)
/* sync with a probability of 1/count */
for (work=unicast_subnet->workgrouplist; work; work = work->next) {
if (strcmp(lp_workgroup(), work->work_group)) {
if (((unsigned)sys_random()) % count != 0) continue;
nstring dmb_name;
if (((unsigned)sys_random()) % count != 0)
continue;
lastrun = t;
@ -699,13 +662,15 @@ void sync_all_dmbs(time_t t)
0x20);
}
pull_ascii_nstring(dmb_name, work->dmb_name.name);
DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
work->dmb_name.name,
inet_ntoa(work->dmb_addr)));
dmb_name, inet_ntoa(work->dmb_addr)));
sync_browse_lists(work,
work->dmb_name.name,
dmb_name,
work->dmb_name.name_type,
work->dmb_addr, False, False);
}
}
}
}

View File

@ -3,7 +3,7 @@
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
Copyright (C) Jeremy Allison 1994-1998
Copyright (C) Jeremy Allison 1994-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -29,32 +29,35 @@ extern time_t StartupTime;
/****************************************************************************
Send an election datagram packet.
**************************************************************************/
static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
uint32 criterion, int timeup,const char *server_name)
{
pstring outbuf;
char *p;
pstring outbuf;
fstring srv_name;
char *p;
DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
workgroup_name, subrec->subnet_name ));
DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
workgroup_name, subrec->subnet_name ));
memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
SCVAL(p,0,ANN_Election); /* Election opcode. */
p++;
memset(outbuf,'\0',sizeof(outbuf));
p = outbuf;
SCVAL(p,0,ANN_Election); /* Election opcode. */
p++;
SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
SIVAL(p,1,criterion);
SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
p += 13;
pstrcpy_base(p, server_name, outbuf);
strupper_m(p);
p = skip_string(p,1);
SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
SIVAL(p,1,criterion);
SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
p += 13;
fstrcpy(srv_name, server_name);
strupper_m(srv_name);
pstrcpy_base(p, srv_name, outbuf);
p = skip_string(p,1);
send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
global_myname(), 0,
workgroup_name, 0x1e,
subrec->bcast_ip, subrec->myip, DGRAM_PORT);
send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
global_myname(), 0,
workgroup_name, 0x1e,
subrec->bcast_ip, subrec->myip, DGRAM_PORT);
}
/*******************************************************************
@ -66,8 +69,10 @@ static void check_for_master_browser_success(struct subnet_record *subrec,
struct nmb_name *answer_name,
struct in_addr answer_ip, struct res_rec *rrec)
{
DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) ));
nstring aname;
pull_ascii_nstring(aname, answer_name->name);
DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
IP %s (just checking).\n", aname, inet_ntoa(answer_ip) ));
}
/*******************************************************************
@ -79,41 +84,39 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
struct nmb_name *question_name,
int fail_code)
{
char *workgroup_name = question_name->name;
struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
nstring workgroup_name;
struct work_record *work;
if(work == NULL)
{
DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
workgroup_name, subrec->subnet_name ));
return;
}
pull_ascii_nstring(workgroup_name,question_name->name);
if (strequal(work->work_group, lp_workgroup()))
{
work = find_workgroup_on_subnet(subrec, workgroup_name);
if(work == NULL) {
DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
workgroup_name, subrec->subnet_name ));
return;
}
if (lp_local_master())
{
/* We have discovered that there is no local master
browser, and we are configured to initiate
an election that we will participate in.
*/
DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
work->work_group, subrec->subnet_name ));
if (strequal(work->work_group, lp_workgroup())) {
/* Setting this means we will participate when the
election is run in run_elections(). */
work->needelection = True;
}
else
{
/* We need to force an election, because we are configured
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, "");
}
}
if (lp_local_master()) {
/* We have discovered that there is no local master
browser, and we are configured to initiate
an election that we will participate in.
*/
DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
work->work_group, subrec->subnet_name ));
/* Setting this means we will participate when the
election is run in run_elections(). */
work->needelection = True;
} else {
/* We need to force an election, because we are configured
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, "");
}
}
}
/*******************************************************************
@ -123,36 +126,33 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
void check_master_browser_exists(time_t t)
{
static time_t lastrun=0;
struct subnet_record *subrec;
const char *workgroup_name = lp_workgroup();
static time_t lastrun=0;
struct subnet_record *subrec;
const char *workgroup_name = lp_workgroup();
if (!lastrun)
lastrun = t;
if (!lastrun)
lastrun = t;
if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
return;
if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
return;
lastrun = t;
lastrun = t;
dump_workgroups(False);
dump_workgroups(False);
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
{
struct work_record *work;
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next)
{
if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work))
{
/* Do a name query for the local master browser on this net. */
query_name( subrec, work->work_group, 0x1d,
check_for_master_browser_success,
check_for_master_browser_fail,
NULL);
}
}
}
for (work = subrec->workgrouplist; work; work = work->next) {
if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
/* Do a name query for the local master browser on this net. */
query_name( subrec, work->work_group, 0x1d,
check_for_master_browser_success,
check_for_master_browser_fail,
NULL);
}
}
}
}
/*******************************************************************
@ -161,56 +161,52 @@ void check_master_browser_exists(time_t t)
void run_elections(time_t t)
{
static time_t lastime = 0;
static time_t lastime = 0;
struct subnet_record *subrec;
struct subnet_record *subrec;
/* Send election packets once every 2 seconds - note */
if (lastime && (t - lastime < 2))
return;
/* Send election packets once every 2 seconds - note */
if (lastime && (t - lastime < 2))
return;
lastime = t;
lastime = t;
START_PROFILE(run_elections);
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
{
struct work_record *work;
START_PROFILE(run_elections);
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next)
{
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;
for (work = subrec->workgrouplist; work; work = work->next) {
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);
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
make_nmb_name(&nmbname, work->work_group, 0x1e);
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", nmb_namestr(&nmbname), subrec->subnet_name ));
continue;
}
continue;
}
send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
t - StartupTime, global_myname());
send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
t - StartupTime, global_myname());
if (work->ElectionCount++ >= 4)
{
/* Won election (4 packets were sent out uncontested. */
DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
work->work_group, subrec->subnet_name ));
if (work->ElectionCount++ >= 4) {
/* Won election (4 packets were sent out uncontested. */
DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
work->work_group, subrec->subnet_name ));
work->RunningElection = False;
work->RunningElection = False;
become_local_master_browser(subrec, work);
}
}
}
}
END_PROFILE(run_elections);
become_local_master_browser(subrec, work);
}
}
}
}
END_PROFILE(run_elections);
}
/*******************************************************************
@ -218,44 +214,42 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
******************************************************************/
static BOOL win_election(struct work_record *work, int version,
uint32 criterion, int timeup, char *server_name)
uint32 criterion, int timeup, const char *server_name)
{
int mytimeup = time(NULL) - StartupTime;
uint32 mycriterion = work->ElectionCriterion;
int mytimeup = time(NULL) - StartupTime;
uint32 mycriterion = work->ElectionCriterion;
/* If local master is false then never win
in election broadcasts. */
if(!lp_local_master())
{
DEBUG(3,("win_election: Losing election as local master == False\n"));
return False;
}
/* If local master is false then never win in election broadcasts. */
if(!lp_local_master()) {
DEBUG(3,("win_election: Losing election as local master == False\n"));
return False;
}
DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
version, ELECTION_VERSION,
criterion, mycriterion,
timeup, mytimeup,
server_name, global_myname()));
DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
version, ELECTION_VERSION,
criterion, mycriterion,
timeup, mytimeup,
server_name, global_myname()));
if (version > ELECTION_VERSION)
return(False);
if (version < ELECTION_VERSION)
return(True);
if (version > ELECTION_VERSION)
return(False);
if (version < ELECTION_VERSION)
return(True);
if (criterion > mycriterion)
return(False);
if (criterion < mycriterion)
return(True);
if (criterion > mycriterion)
return(False);
if (criterion < mycriterion)
return(True);
if (timeup > mytimeup)
return(False);
if (timeup < mytimeup)
return(True);
if (timeup > mytimeup)
return(False);
if (timeup < mytimeup)
return(True);
if (strcasecmp(global_myname(), server_name) > 0)
return(False);
if (strcasecmp(global_myname(), server_name) > 0)
return(False);
return(True);
return(True);
}
/*******************************************************************
@ -264,66 +258,63 @@ static BOOL win_election(struct work_record *work, int version,
void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
int version = CVAL(buf,0);
uint32 criterion = IVAL(buf,1);
int timeup = IVAL(buf,5)/1000;
char *server_name = buf+13;
struct work_record *work;
char *workgroup_name = dgram->dest_name.name;
struct dgram_packet *dgram = &p->packet.dgram;
int version = CVAL(buf,0);
uint32 criterion = IVAL(buf,1);
int timeup = IVAL(buf,5)/1000;
nstring server_name;
struct work_record *work;
nstring workgroup_name;
START_PROFILE(election);
server_name[15] = 0;
pull_ascii_nstring(server_name, buf+13);
pull_ascii_nstring(workgroup_name, dgram->dest_name.name);
DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
START_PROFILE(election);
server_name[15] = 0;
DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
{
DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
workgroup_name, subrec->subnet_name ));
goto done;
}
DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
if (!strequal(work->work_group, lp_workgroup()))
{
DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
workgroup_name, subrec->subnet_name ));
goto done;
}
if (!strequal(work->work_group, lp_workgroup())) {
DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
is not my workgroup.\n", work->work_group, subrec->subnet_name ));
goto done;
}
goto done;
}
if (win_election(work, version,criterion,timeup,server_name))
{
/* We take precedence over the requesting server. */
if (!work->RunningElection)
{
/* We weren't running an election - start running one. */
if (win_election(work, version,criterion,timeup,server_name)) {
/* We take precedence over the requesting server. */
if (!work->RunningElection) {
/* We weren't running an election - start running one. */
work->needelection = True;
work->ElectionCount=0;
}
work->needelection = True;
work->ElectionCount=0;
}
/* Note that if we were running an election for this workgroup on this
subnet already, we just ignore the server we take precedence over. */
}
else
{
/* We lost. Stop participating. */
work->needelection = False;
/* Note that if we were running an election for this workgroup on this
subnet already, we just ignore the server we take precedence over. */
} else {
/* We lost. Stop participating. */
work->needelection = False;
if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
{
work->RunningElection = False;
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, False);
}
}
if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) {
work->RunningElection = False;
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, False);
}
}
done:
END_PROFILE(election);
END_PROFILE(election);
}
/****************************************************************************
@ -335,57 +326,53 @@ done:
BOOL check_elections(void)
{
struct subnet_record *subrec;
BOOL run_any_election = False;
struct subnet_record *subrec;
BOOL run_any_election = False;
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
{
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next)
{
run_any_election |= work->RunningElection;
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next) {
run_any_election |= work->RunningElection;
/*
* Start an election if we have any chance of winning.
* Note this is a change to the previous code, that would
* only run an election if nmbd was in the potential browser
* state. We need to run elections in any state if we're told
* to. JRA.
*/
/*
* Start an election if we have any chance of winning.
* Note this is a change to the previous code, that would
* only run an election if nmbd was in the potential browser
* state. We need to run elections in any state if we're told
* to. JRA.
*/
if (work->needelection && !work->RunningElection && lp_local_master())
{
/*
* 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;
if (work->needelection && !work->RunningElection && lp_local_master()) {
/*
* 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);
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
make_nmb_name(&nmbname, work->work_group, 0x1e);
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", nmb_namestr(&nmbname), subrec->subnet_name ));
continue;
}
continue;
}
DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
work->work_group, subrec->subnet_name ));
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;
}
}
}
return run_any_election;
work->ElectionCount = 0;
work->RunningElection = True;
work->needelection = False;
}
}
}
return run_any_election;
}
/****************************************************************************
process a internal Samba message forcing an election
Process a internal Samba message forcing an election.
***************************************************************************/
void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len)
{
struct subnet_record *subrec;

File diff suppressed because it is too large Load Diff

View File

@ -201,7 +201,7 @@ static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name
Try and query for a name.
****************************************************************************/
BOOL query_name(struct subnet_record *subrec, char *name, int type,
BOOL query_name(struct subnet_record *subrec, const char *name, int type,
query_name_success_function success_fn,
query_name_fail_function fail_fn,
struct userdata_struct *userdata)
@ -276,7 +276,7 @@ BOOL query_name(struct subnet_record *subrec, char *name, int type,
****************************************************************************/
BOOL query_name_from_wins_server(struct in_addr ip_to,
char *name, int type,
const char *name, int type,
query_name_success_function success_fn,
query_name_fail_function fail_fn,
struct userdata_struct *userdata)