mirror of
https://github.com/samba-team/samba.git
synced 2025-09-24 05:44:20 +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:
@@ -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 node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
|
||||||
enum packet_type {NMB_PACKET, DGRAM_PACKET};
|
enum packet_type {NMB_PACKET, DGRAM_PACKET};
|
||||||
|
|
||||||
enum master_state
|
enum master_state {
|
||||||
{
|
MST_NONE,
|
||||||
MST_NONE,
|
MST_POTENTIAL,
|
||||||
MST_POTENTIAL,
|
MST_BACKUP,
|
||||||
MST_BACKUP,
|
MST_MSB,
|
||||||
MST_MSB,
|
MST_BROWSER,
|
||||||
MST_BROWSER,
|
MST_UNBECOMING_MASTER
|
||||||
MST_UNBECOMING_MASTER
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum domain_state
|
enum domain_state {
|
||||||
{
|
DOMAIN_NONE,
|
||||||
DOMAIN_NONE,
|
DOMAIN_WAIT,
|
||||||
DOMAIN_WAIT,
|
DOMAIN_MST
|
||||||
DOMAIN_MST
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum logon_state
|
enum logon_state {
|
||||||
{
|
LOGON_NONE,
|
||||||
LOGON_NONE,
|
LOGON_WAIT,
|
||||||
LOGON_WAIT,
|
LOGON_SRV
|
||||||
LOGON_SRV
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct subnet_record;
|
struct subnet_record;
|
||||||
|
|
||||||
struct nmb_data
|
struct nmb_data {
|
||||||
{
|
uint16 nb_flags; /* Netbios flags. */
|
||||||
uint16 nb_flags; /* Netbios flags. */
|
int num_ips; /* Number of ip entries. */
|
||||||
int num_ips; /* Number of ip entries. */
|
struct in_addr *ip; /* The ip list for this name. */
|
||||||
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 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 refresh_time; /* The time the record should be refreshed. */
|
||||||
|
|
||||||
SMB_BIG_UINT id; /* unique id */
|
SMB_BIG_UINT id; /* unique id */
|
||||||
struct in_addr wins_ip; /* the adress of the wins server this record comes from */
|
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. */
|
/* This structure represents an entry in a local netbios name list. */
|
||||||
struct name_record
|
struct name_record {
|
||||||
{
|
ubi_trNode node[1];
|
||||||
ubi_trNode node[1];
|
struct subnet_record *subnet;
|
||||||
struct subnet_record *subnet;
|
struct nmb_name name; /* The netbios name. */
|
||||||
struct nmb_name name; /* The netbios name. */
|
struct nmb_data data; /* The netbios data. */
|
||||||
struct nmb_data data; /* The netbios data. */
|
};
|
||||||
};
|
|
||||||
|
|
||||||
/* Browser cache for synchronising browse lists. */
|
/* Browser cache for synchronising browse lists. */
|
||||||
struct browse_cache_record
|
struct browse_cache_record {
|
||||||
{
|
ubi_dlNode node[1];
|
||||||
ubi_dlNode node[1];
|
pstring lmb_name;
|
||||||
pstring lmb_name;
|
pstring work_group;
|
||||||
pstring work_group;
|
struct in_addr ip;
|
||||||
struct in_addr ip;
|
time_t sync_time;
|
||||||
time_t sync_time;
|
time_t death_time; /* The time the record must be removed. */
|
||||||
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
|
/* This is used to hold the list of servers in my domain, and is
|
||||||
contained within lists of domains. */
|
contained within lists of domains. */
|
||||||
|
|
||||||
struct server_record
|
struct server_record {
|
||||||
{
|
struct server_record *next;
|
||||||
struct server_record *next;
|
struct server_record *prev;
|
||||||
struct server_record *prev;
|
|
||||||
|
|
||||||
struct subnet_record *subnet;
|
struct subnet_record *subnet;
|
||||||
|
|
||||||
struct server_info_struct serv;
|
struct server_info_struct serv;
|
||||||
time_t death_time;
|
time_t death_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A workgroup structure. It contains a list of servers. */
|
/* A workgroup structure. It contains a list of servers. */
|
||||||
struct work_record
|
struct work_record {
|
||||||
{
|
struct work_record *next;
|
||||||
struct work_record *next;
|
struct work_record *prev;
|
||||||
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. */
|
/* Stage of development from non-local-master up to local-master browser. */
|
||||||
enum master_state mst_state;
|
enum master_state mst_state;
|
||||||
|
|
||||||
/* Stage of development from non-domain-master to domain-master browser. */
|
/* Stage of development from non-domain-master to domain-master browser. */
|
||||||
enum domain_state dom_state;
|
enum domain_state dom_state;
|
||||||
|
|
||||||
/* Stage of development from non-logon-server to logon server. */
|
/* Stage of development from non-logon-server to logon server. */
|
||||||
enum logon_state log_state;
|
enum logon_state log_state;
|
||||||
|
|
||||||
/* Work group info. */
|
/* Work group info. */
|
||||||
fstring work_group;
|
fstring work_group;
|
||||||
int token; /* Used when communicating with backup browsers. */
|
int token; /* Used when communicating with backup browsers. */
|
||||||
fstring local_master_browser_name; /* Current local master browser. */
|
fstring local_master_browser_name; /* Current local master browser. */
|
||||||
|
|
||||||
/* Announce info. */
|
/* Announce info. */
|
||||||
time_t lastannounce_time;
|
time_t lastannounce_time;
|
||||||
int announce_interval;
|
int announce_interval;
|
||||||
BOOL needannounce;
|
BOOL needannounce;
|
||||||
|
|
||||||
/* Timeout time for this workgroup. 0 means permanent. */
|
/* Timeout time for this workgroup. 0 means permanent. */
|
||||||
time_t death_time;
|
time_t death_time;
|
||||||
|
|
||||||
/* Election info */
|
/* Election info */
|
||||||
BOOL RunningElection;
|
BOOL RunningElection;
|
||||||
BOOL needelection;
|
BOOL needelection;
|
||||||
int ElectionCount;
|
int ElectionCount;
|
||||||
uint32 ElectionCriterion;
|
uint32 ElectionCriterion;
|
||||||
|
|
||||||
/* Domain master browser info. Used for efficient syncs. */
|
/* Domain master browser info. Used for efficient syncs. */
|
||||||
struct nmb_name dmb_name;
|
struct nmb_name dmb_name;
|
||||||
struct in_addr dmb_addr;
|
struct in_addr dmb_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* typedefs needed to define copy & free functions for userdata. */
|
/* 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. */
|
/* Structure to define any userdata passed around. */
|
||||||
|
|
||||||
struct userdata_struct {
|
struct userdata_struct {
|
||||||
userdata_copy_fn copy_fn;
|
userdata_copy_fn copy_fn;
|
||||||
userdata_free_fn free_fn;
|
userdata_free_fn free_fn;
|
||||||
unsigned int userdata_len;
|
unsigned int userdata_len;
|
||||||
char data[16]; /* 16 is to ensure alignment/padding on all systems */
|
char data[16]; /* 16 is to ensure alignment/padding on all systems */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct response_record;
|
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. */
|
/* Initiated name queries are recorded in this list to track any responses. */
|
||||||
|
|
||||||
struct response_record
|
struct response_record {
|
||||||
{
|
struct response_record *next;
|
||||||
struct response_record *next;
|
struct response_record *prev;
|
||||||
struct response_record *prev;
|
|
||||||
|
|
||||||
uint16 response_id;
|
uint16 response_id;
|
||||||
|
|
||||||
/* Callbacks for packets received or not. */
|
/* Callbacks for packets received or not. */
|
||||||
response_function resp_fn;
|
response_function resp_fn;
|
||||||
timeout_response_function timeout_fn;
|
timeout_response_function timeout_fn;
|
||||||
|
|
||||||
/* Callbacks for the request succeeding or not. */
|
/* Callbacks for the request succeeding or not. */
|
||||||
success_function success_fn;
|
success_function success_fn;
|
||||||
fail_function fail_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_time;
|
||||||
time_t repeat_interval;
|
time_t repeat_interval;
|
||||||
int repeat_count;
|
int repeat_count;
|
||||||
|
|
||||||
/* Recursion protection. */
|
/* Recursion protection. */
|
||||||
BOOL in_expiration_processing;
|
BOOL in_expiration_processing;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A subnet structure. It contains a list of workgroups and netbios names. */
|
/* A subnet structure. It contains a list of workgroups and netbios names. */
|
||||||
@@ -420,42 +411,41 @@ struct response_record
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum subnet_type {
|
enum subnet_type {
|
||||||
NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
|
NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
|
||||||
UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
|
UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
|
||||||
REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
|
REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
|
||||||
WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
|
WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct subnet_record
|
struct subnet_record {
|
||||||
{
|
struct subnet_record *next;
|
||||||
struct subnet_record *next;
|
struct subnet_record *prev;
|
||||||
struct subnet_record *prev;
|
|
||||||
|
|
||||||
char *subnet_name; /* For Debug identification. */
|
char *subnet_name; /* For Debug identification. */
|
||||||
enum subnet_type type; /* To catagorize the subnet. */
|
enum subnet_type type; /* To catagorize the subnet. */
|
||||||
|
|
||||||
struct work_record *workgrouplist; /* List of workgroups. */
|
struct work_record *workgrouplist; /* List of workgroups. */
|
||||||
ubi_trRoot namelist[1]; /* List of netbios names. */
|
ubi_trRoot namelist[1]; /* List of netbios names. */
|
||||||
struct response_record *responselist; /* List of responses expected. */
|
struct response_record *responselist; /* List of responses expected. */
|
||||||
|
|
||||||
BOOL namelist_changed;
|
BOOL namelist_changed;
|
||||||
BOOL work_changed;
|
BOOL work_changed;
|
||||||
|
|
||||||
struct in_addr bcast_ip;
|
struct in_addr bcast_ip;
|
||||||
struct in_addr mask_ip;
|
struct in_addr mask_ip;
|
||||||
struct in_addr myip;
|
struct in_addr myip;
|
||||||
int nmb_sock; /* socket to listen for unicast 137. */
|
int nmb_sock; /* socket to listen for unicast 137. */
|
||||||
int dgram_sock; /* socket to listen for unicast 138. */
|
int dgram_sock; /* socket to listen for unicast 138. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A resource record. */
|
/* A resource record. */
|
||||||
struct res_rec {
|
struct res_rec {
|
||||||
struct nmb_name rr_name;
|
struct nmb_name rr_name;
|
||||||
int rr_type;
|
int rr_type;
|
||||||
int rr_class;
|
int rr_class;
|
||||||
int ttl;
|
int ttl;
|
||||||
int rdlength;
|
int rdlength;
|
||||||
char rdata[MAX_DGRAM_SIZE];
|
char rdata[MAX_DGRAM_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Define these so we can pass info back to caller of name_query */
|
/* 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 */
|
#define NM_FLAGS_B 0x01 /* Broadcast */
|
||||||
|
|
||||||
/* An nmb packet. */
|
/* An nmb packet. */
|
||||||
struct nmb_packet
|
struct nmb_packet {
|
||||||
{
|
struct {
|
||||||
struct {
|
int name_trn_id;
|
||||||
int name_trn_id;
|
int opcode;
|
||||||
int opcode;
|
BOOL response;
|
||||||
BOOL response;
|
struct {
|
||||||
struct {
|
BOOL bcast;
|
||||||
BOOL bcast;
|
BOOL recursion_available;
|
||||||
BOOL recursion_available;
|
BOOL recursion_desired;
|
||||||
BOOL recursion_desired;
|
BOOL trunc;
|
||||||
BOOL trunc;
|
BOOL authoritative;
|
||||||
BOOL authoritative;
|
} nm_flags;
|
||||||
} nm_flags;
|
int rcode;
|
||||||
int rcode;
|
int qdcount;
|
||||||
int qdcount;
|
int ancount;
|
||||||
int ancount;
|
int nscount;
|
||||||
int nscount;
|
int arcount;
|
||||||
int arcount;
|
} header;
|
||||||
} header;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct nmb_name question_name;
|
struct nmb_name question_name;
|
||||||
int question_type;
|
int question_type;
|
||||||
int question_class;
|
int question_class;
|
||||||
} question;
|
} question;
|
||||||
|
|
||||||
struct res_rec *answers;
|
struct res_rec *answers;
|
||||||
struct res_rec *nsrecs;
|
struct res_rec *nsrecs;
|
||||||
struct res_rec *additional;
|
struct res_rec *additional;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* msg_type field options - from rfc1002. */
|
/* msg_type field options - from rfc1002. */
|
||||||
@@ -511,23 +500,23 @@ struct nmb_packet
|
|||||||
/* A datagram - this normally contains SMB data in the data[] array. */
|
/* A datagram - this normally contains SMB data in the data[] array. */
|
||||||
|
|
||||||
struct dgram_packet {
|
struct dgram_packet {
|
||||||
struct {
|
struct {
|
||||||
int msg_type;
|
int msg_type;
|
||||||
struct {
|
struct {
|
||||||
enum node_type node_type;
|
enum node_type node_type;
|
||||||
BOOL first;
|
BOOL first;
|
||||||
BOOL more;
|
BOOL more;
|
||||||
} flags;
|
} flags;
|
||||||
int dgm_id;
|
int dgm_id;
|
||||||
struct in_addr source_ip;
|
struct in_addr source_ip;
|
||||||
int source_port;
|
int source_port;
|
||||||
int dgm_length;
|
int dgm_length;
|
||||||
int packet_offset;
|
int packet_offset;
|
||||||
} header;
|
} header;
|
||||||
struct nmb_name source_name;
|
struct nmb_name source_name;
|
||||||
struct nmb_name dest_name;
|
struct nmb_name dest_name;
|
||||||
int datasize;
|
int datasize;
|
||||||
char data[MAX_DGRAM_SIZE];
|
char data[MAX_DGRAM_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Define a structure used to queue packets. This will be a linked
|
/* 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
|
||||||
{
|
{
|
||||||
struct packet_struct *next;
|
struct packet_struct *next;
|
||||||
struct packet_struct *prev;
|
struct packet_struct *prev;
|
||||||
BOOL locked;
|
BOOL locked;
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
int port;
|
int port;
|
||||||
int fd;
|
int fd;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
enum packet_type packet_type;
|
enum packet_type packet_type;
|
||||||
union {
|
union {
|
||||||
struct nmb_packet nmb;
|
struct nmb_packet nmb;
|
||||||
struct dgram_packet dgram;
|
struct dgram_packet dgram;
|
||||||
} packet;
|
} packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NETLOGON opcodes */
|
/* NETLOGON opcodes */
|
||||||
|
@@ -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 pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1)
|
||||||
#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
|
#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
|
||||||
#define fstrcat(d,s) safe_strcat((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
|
/* 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
|
* update a lot of code. To make this a little easier here are some
|
||||||
|
@@ -1484,9 +1484,11 @@ struct cnotify_fns {
|
|||||||
|
|
||||||
#include "smb_macros.h"
|
#include "smb_macros.h"
|
||||||
|
|
||||||
|
typedef char nstring[16];
|
||||||
|
|
||||||
/* A netbios name structure. */
|
/* A netbios name structure. */
|
||||||
struct nmb_name {
|
struct nmb_name {
|
||||||
char name[16];
|
nstring name;
|
||||||
char scope[64];
|
char scope[64];
|
||||||
unsigned int name_type;
|
unsigned int name_type;
|
||||||
};
|
};
|
||||||
@@ -1494,7 +1496,7 @@ struct nmb_name {
|
|||||||
|
|
||||||
/* A netbios node status array element. */
|
/* A netbios node status array element. */
|
||||||
struct node_status {
|
struct node_status {
|
||||||
char name[16];
|
nstring name;
|
||||||
unsigned char type;
|
unsigned char type;
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
};
|
};
|
||||||
|
@@ -529,6 +529,11 @@ size_t push_ascii_pstring(void *dest, const char *src)
|
|||||||
return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
|
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.
|
* 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);
|
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.
|
* Copy a string from a char* src to a unicode destination.
|
||||||
*
|
*
|
||||||
|
@@ -303,6 +303,7 @@ static BOOL reload_nmbd_services(BOOL test)
|
|||||||
* We use buf here to return BOOL result to process() when reload_interfaces()
|
* We use buf here to return BOOL result to process() when reload_interfaces()
|
||||||
* detects that there are no subnets.
|
* detects that there are no subnets.
|
||||||
**************************************************************************** */
|
**************************************************************************** */
|
||||||
|
|
||||||
static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len)
|
static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
write_browse_list( 0, True );
|
write_browse_list( 0, True );
|
||||||
@@ -650,126 +651,120 @@ static BOOL open_sockets(BOOL isdaemon, int port)
|
|||||||
log_stdout = True;
|
log_stdout = True;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( log_stdout && Fork ) {
|
if ( log_stdout && Fork ) {
|
||||||
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
|
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
|
||||||
exit(1);
|
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) );
|
DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
|
||||||
DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
|
DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
|
||||||
|
|
||||||
if ( !reload_nmbd_services(False) )
|
if ( !reload_nmbd_services(False) )
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
if(!init_names())
|
if(!init_names())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
reload_nmbd_services( True );
|
reload_nmbd_services( True );
|
||||||
|
|
||||||
if (strequal(lp_workgroup(),"*"))
|
if (strequal(lp_workgroup(),"*")) {
|
||||||
{
|
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
|
||||||
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
|
exit(1);
|
||||||
exit(1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
set_samba_nb_type();
|
set_samba_nb_type();
|
||||||
|
|
||||||
if (!is_daemon && !is_a_socket(0))
|
if (!is_daemon && !is_a_socket(0)) {
|
||||||
{
|
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
|
||||||
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
|
is_daemon = True;
|
||||||
is_daemon = True;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (is_daemon && !opt_interactive)
|
if (is_daemon && !opt_interactive) {
|
||||||
{
|
DEBUG( 2, ( "Becoming a daemon.\n" ) );
|
||||||
DEBUG( 2, ( "Becoming a daemon.\n" ) );
|
become_daemon(Fork);
|
||||||
become_daemon(Fork);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if HAVE_SETPGID
|
#if HAVE_SETPGID
|
||||||
/*
|
/*
|
||||||
* If we're interactive we want to set our own process group for
|
* If we're interactive we want to set our own process group for
|
||||||
* signal management.
|
* signal management.
|
||||||
*/
|
*/
|
||||||
if (opt_interactive)
|
if (opt_interactive)
|
||||||
setpgid( (pid_t)0, (pid_t)0 );
|
setpgid( (pid_t)0, (pid_t)0 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SYNC_DNS
|
#ifndef SYNC_DNS
|
||||||
/* Setup the async dns. We do it here so it doesn't have all the other
|
/* Setup the async dns. We do it here so it doesn't have all the other
|
||||||
stuff initialised and thus chewing memory and sockets */
|
stuff initialised and thus chewing memory and sockets */
|
||||||
if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
|
if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
|
||||||
start_async_dns();
|
start_async_dns();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!directory_exist(lp_lockdir(), NULL)) {
|
if (!directory_exist(lp_lockdir(), NULL)) {
|
||||||
mkdir(lp_lockdir(), 0755);
|
mkdir(lp_lockdir(), 0755);
|
||||||
}
|
}
|
||||||
|
|
||||||
pidfile_create("nmbd");
|
pidfile_create("nmbd");
|
||||||
message_init();
|
message_init();
|
||||||
message_register(MSG_FORCE_ELECTION, nmbd_message_election);
|
message_register(MSG_FORCE_ELECTION, nmbd_message_election);
|
||||||
message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
|
message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
|
||||||
message_register(MSG_SHUTDOWN, nmbd_terminate);
|
message_register(MSG_SHUTDOWN, nmbd_terminate);
|
||||||
message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
|
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 ) ) {
|
if ( !open_sockets( is_daemon, global_nmb_port ) ) {
|
||||||
kill_async_dns_child();
|
kill_async_dns_child();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine all the IP addresses we have. */
|
/* Determine all the IP addresses we have. */
|
||||||
load_interfaces();
|
load_interfaces();
|
||||||
|
|
||||||
/* Create an nmbd subnet record for each of the above. */
|
/* Create an nmbd subnet record for each of the above. */
|
||||||
if( False == create_subnets() )
|
if( False == create_subnets() ) {
|
||||||
{
|
DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
|
||||||
DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
|
kill_async_dns_child();
|
||||||
kill_async_dns_child();
|
exit(1);
|
||||||
exit(1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Load in any static local names. */
|
/* Load in any static local names. */
|
||||||
load_lmhosts_file(dyn_LMHOSTSFILE);
|
load_lmhosts_file(dyn_LMHOSTSFILE);
|
||||||
DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
|
DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
|
||||||
|
|
||||||
/* If we are acting as a WINS server, initialise data structures. */
|
/* If we are acting as a WINS server, initialise data structures. */
|
||||||
if( !initialise_wins() )
|
if( !initialise_wins() ) {
|
||||||
{
|
DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
|
||||||
DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
|
kill_async_dns_child();
|
||||||
kill_async_dns_child();
|
exit(1);
|
||||||
exit(1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register nmbd primary workgroup and nmbd names on all
|
* Register nmbd primary workgroup and nmbd names on all
|
||||||
* the broadcast subnets, and on the WINS server (if specified).
|
* the broadcast subnets, and on the WINS server (if specified).
|
||||||
* Also initiate the startup of our primary workgroup (start
|
* Also initiate the startup of our primary workgroup (start
|
||||||
* elections if we are setup as being able to be a local
|
* elections if we are setup as being able to be a local
|
||||||
* master browser.
|
* master browser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( False == register_my_workgroup_and_names() )
|
if( False == register_my_workgroup_and_names() ) {
|
||||||
{
|
DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
|
||||||
DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
|
kill_async_dns_child();
|
||||||
kill_async_dns_child();
|
exit(1);
|
||||||
exit(1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* We can only take signals in the select. */
|
/* We can only take signals in the select. */
|
||||||
BlockSignals( True, SIGTERM );
|
BlockSignals( True, SIGTERM );
|
||||||
|
|
||||||
process();
|
process();
|
||||||
|
|
||||||
if (dbf)
|
if (dbf)
|
||||||
x_fclose(dbf);
|
x_fclose(dbf);
|
||||||
kill_async_dns_child();
|
kill_async_dns_child();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
NBT netbios routines and daemon - version 2
|
NBT netbios routines and daemon - version 2
|
||||||
Copyright (C) Andrew Tridgell 1994-1998
|
Copyright (C) Andrew Tridgell 1994-1998
|
||||||
Copyright (C) Luke Kenneth Casson Leighton 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
|
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
|
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 response_record *rrec,
|
||||||
struct nmb_name *fail_name)
|
struct nmb_name *fail_name)
|
||||||
{
|
{
|
||||||
struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
|
nstring failname;
|
||||||
struct server_record *servrec;
|
struct work_record *work;
|
||||||
|
struct server_record *servrec;
|
||||||
|
|
||||||
if(!work)
|
pull_ascii_nstring(failname, fail_name->name);
|
||||||
{
|
work = find_workgroup_on_subnet(subrec, failname);
|
||||||
DEBUG(0,("become_domain_master_fail: Error - cannot find \
|
if(!work) {
|
||||||
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
|
DEBUG(0,("become_domain_master_fail: Error - cannot find \
|
||||||
return;
|
workgroup %s on subnet %s\n", failname, subrec->subnet_name));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the state back to DOMAIN_NONE. */
|
/* Set the state back to DOMAIN_NONE. */
|
||||||
work->dom_state = DOMAIN_NONE;
|
work->dom_state = DOMAIN_NONE;
|
||||||
|
|
||||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
|
||||||
{
|
DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
|
||||||
DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
|
|
||||||
in workgroup %s on subnet %s\n",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), work->work_group, subrec->subnet_name));
|
global_myname(), work->work_group, subrec->subnet_name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update our server status. */
|
/* Update our server status. */
|
||||||
servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
|
servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
|
||||||
|
|
||||||
/* Tell the namelist writer to write out a change. */
|
/* Tell the namelist writer to write out a change. */
|
||||||
subrec->work_changed = True;
|
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",
|
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,
|
uint16 nb_flags,
|
||||||
int ttl, struct in_addr registered_ip)
|
int ttl, struct in_addr registered_ip)
|
||||||
{
|
{
|
||||||
struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
|
nstring regname;
|
||||||
struct server_record *servrec;
|
struct work_record *work;
|
||||||
|
struct server_record *servrec;
|
||||||
|
|
||||||
if(!work)
|
pull_ascii_nstring(regname, registered_name->name);
|
||||||
{
|
work = find_workgroup_on_subnet( subrec, regname);
|
||||||
DEBUG(0,("become_domain_master_stage2: Error - cannot find \
|
|
||||||
workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
if(!work) {
|
||||||
{
|
DEBUG(0,("become_domain_master_stage2: Error - cannot find \
|
||||||
DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
|
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",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), registered_name->name, subrec->subnet_name));
|
global_myname(), regname, subrec->subnet_name));
|
||||||
work->dom_state = DOMAIN_NONE;
|
work->dom_state = DOMAIN_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the state in the workgroup structure. */
|
/* Set the state in the workgroup structure. */
|
||||||
work->dom_state = DOMAIN_MST; /* Become domain master. */
|
work->dom_state = DOMAIN_MST; /* Become domain master. */
|
||||||
|
|
||||||
/* Update our server status. */
|
/* Update our server status. */
|
||||||
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
|
servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
|
||||||
|
|
||||||
/* Tell the namelist writer to write out a change. */
|
/* Tell the namelist writer to write out a change. */
|
||||||
subrec->work_changed = True;
|
subrec->work_changed = True;
|
||||||
|
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "*****\n\nSamba server %s ", global_myname() );
|
||||||
dbgtext( "*****\n\nSamba server %s ", global_myname() );
|
dbgtext( "is now a domain master browser for " );
|
||||||
dbgtext( "is now a domain master browser for " );
|
dbgtext( "workgroup %s ", work->work_group );
|
||||||
dbgtext( "workgroup %s ", work->work_group );
|
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
|
||||||
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( subrec == unicast_subnet )
|
if( subrec == unicast_subnet ) {
|
||||||
{
|
struct nmb_name nmbname;
|
||||||
struct nmb_name nmbname;
|
struct in_addr my_first_ip;
|
||||||
struct in_addr my_first_ip;
|
|
||||||
|
|
||||||
/* Put our name and first IP address into the
|
/* Put our name and first IP address into the
|
||||||
workgroup struct as domain master browser. This
|
workgroup struct as domain master browser. This
|
||||||
will stop us syncing with ourself if we are also
|
will stop us syncing with ourself if we are also
|
||||||
a local master browser. */
|
a local master browser. */
|
||||||
|
|
||||||
make_nmb_name(&nmbname, global_myname(), 0x20);
|
make_nmb_name(&nmbname, global_myname(), 0x20);
|
||||||
|
|
||||||
work->dmb_name = nmbname;
|
work->dmb_name = nmbname;
|
||||||
/* Pick the first interface ip address as the domain master browser ip. */
|
/* Pick the first interface ip address as the domain master browser ip. */
|
||||||
my_first_ip = *iface_n_ip(0);
|
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
|
/* We successfully registered by unicast with the
|
||||||
WINS server. We now expect to become the domain
|
WINS server. We now expect to become the domain
|
||||||
master on the local subnets. If this fails, it's
|
master on the local subnets. If this fails, it's
|
||||||
probably a 1.9.16p2 to 1.9.16p11 server's fault.
|
probably a 1.9.16p2 to 1.9.16p11 server's fault.
|
||||||
|
|
||||||
This is a configuration issue that should be addressed
|
This is a configuration issue that should be addressed
|
||||||
by the network administrator - you shouldn't have
|
by the network administrator - you shouldn't have
|
||||||
several machines configured as a domain master browser
|
several machines configured as a domain master browser
|
||||||
for the same WINS scope (except if they are 1.9.17 or
|
for the same WINS scope (except if they are 1.9.17 or
|
||||||
greater, and you know what you're doing.
|
greater, and you know what you're doing.
|
||||||
|
|
||||||
see docs/DOMAIN.txt.
|
see docs/DOMAIN.txt.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
become_domain_master_browser_bcast(work->work_group);
|
become_domain_master_browser_bcast(work->work_group);
|
||||||
}
|
} else {
|
||||||
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
|
||||||
* Now we are a domain master on a broadcast subnet, we need to add
|
* unicast requests sent to this name. This bug wasn't found for a while
|
||||||
* the WORKGROUP<1b> name to the unicast subnet so that we can answer
|
* as it is strange to have a DMB without using WINS. JRA.
|
||||||
* 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);
|
||||||
*/
|
}
|
||||||
insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Start the name registration process when becoming a Domain Master Browser
|
Start the name registration process when becoming a Domain Master Browser
|
||||||
on a subnet.
|
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));
|
workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
|
||||||
|
|
||||||
/* First, find the workgroup on the subnet. */
|
/* First, find the workgroup on the subnet. */
|
||||||
if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
|
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",
|
||||||
DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
|
wg_name, subrec->subnet_name));
|
||||||
wg_name, subrec->subnet_name));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
|
DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
|
||||||
work->dom_state = DOMAIN_WAIT;
|
work->dom_state = DOMAIN_WAIT;
|
||||||
|
|
||||||
/* WORKGROUP<1b> is the domain master browser name. */
|
/* WORKGROUP<1b> is the domain master browser name. */
|
||||||
register_name(subrec, work->work_group,0x1b,samba_nb_type,
|
register_name(subrec, work->work_group,0x1b,samba_nb_type,
|
||||||
become_domain_master_stage2,
|
become_domain_master_stage2,
|
||||||
become_domain_master_fail, NULL);
|
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 nmb_name *nmbname, struct in_addr ip,
|
||||||
struct res_rec *rrec)
|
struct res_rec *rrec)
|
||||||
{
|
{
|
||||||
/* If the given ip is not ours, then we can't become a domain
|
nstring name;
|
||||||
controler as the name is already registered.
|
pull_ascii_nstring(name, nmbname->name);
|
||||||
*/
|
|
||||||
|
|
||||||
/* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
|
/* If the given ip is not ours, then we can't become a domain
|
||||||
address or zero ip for this query. Pretend this is ok. */
|
controler as the name is already registered.
|
||||||
|
*/
|
||||||
|
|
||||||
if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
|
/* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
|
||||||
{
|
address or zero ip for this query. Pretend this is ok. */
|
||||||
if( DEBUGLVL( 3 ) )
|
|
||||||
{
|
|
||||||
dbgtext( "become_domain_master_query_success():\n" );
|
|
||||||
dbgtext( "Our address (%s) ", inet_ntoa(ip) );
|
|
||||||
dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
|
|
||||||
dbgtext( "(domain master browser name) " );
|
|
||||||
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
|
||||||
dbgtext( "Continuing with domain master code.\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
become_domain_master_stage1(subrec, nmbname->name);
|
if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) {
|
||||||
}
|
if( DEBUGLVL( 3 ) ) {
|
||||||
else
|
dbgtext( "become_domain_master_query_success():\n" );
|
||||||
{
|
dbgtext( "Our address (%s) ", inet_ntoa(ip) );
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
|
||||||
{
|
dbgtext( "(domain master browser name) " );
|
||||||
dbgtext( "become_domain_master_query_success:\n" );
|
dbgtext( "on subnet %s.\n", subrec->subnet_name );
|
||||||
dbgtext( "There is already a domain master browser at " );
|
dbgtext( "Continuing with domain master code.\n" );
|
||||||
dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
|
}
|
||||||
dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
|
|
||||||
}
|
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 response_record *rrec,
|
||||||
struct nmb_name *question_name, int fail_code)
|
struct nmb_name *question_name, int fail_code)
|
||||||
{
|
{
|
||||||
/* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
|
nstring name;
|
||||||
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. */
|
/* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
|
||||||
become_domain_master_stage1(subrec, question_name->name);
|
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)
|
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))
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||||
{
|
struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
|
||||||
struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
|
|
||||||
|
|
||||||
if (work && (work->dom_state == DOMAIN_NONE))
|
if (work && (work->dom_state == DOMAIN_NONE)) {
|
||||||
{
|
struct nmb_name nmbname;
|
||||||
struct nmb_name nmbname;
|
make_nmb_name(&nmbname,workgroup_name,0x1b);
|
||||||
make_nmb_name(&nmbname,workgroup_name,0x1b);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for our name on the given broadcast subnet first, only initiate
|
* Check for our name on the given broadcast subnet first, only initiate
|
||||||
* further processing if we cannot find it.
|
* further processing if we cannot find it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
|
if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "become_domain_master_browser_bcast:\n" );
|
||||||
{
|
dbgtext( "Attempting to become domain master browser on " );
|
||||||
dbgtext( "become_domain_master_browser_bcast:\n" );
|
dbgtext( "workgroup %s on subnet %s\n",
|
||||||
dbgtext( "Attempting to become domain master browser on " );
|
workgroup_name, subrec->subnet_name );
|
||||||
dbgtext( "workgroup %s on subnet %s\n",
|
}
|
||||||
workgroup_name, subrec->subnet_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send out a query to establish whether there's a
|
/* Send out a query to establish whether there's a
|
||||||
domain controller on the local subnet. If not,
|
domain controller on the local subnet. If not,
|
||||||
we can become a domain controller.
|
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));
|
for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
|
||||||
|
|
||||||
query_name(subrec, nmbname.name, nmbname.name_type,
|
query_name(subrec, workgroup_name, nmbname.name_type,
|
||||||
become_domain_master_query_success,
|
become_domain_master_query_success,
|
||||||
become_domain_master_query_fail,
|
become_domain_master_query_fail,
|
||||||
NULL);
|
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)
|
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))
|
if (work && (work->dom_state == DOMAIN_NONE)) {
|
||||||
{
|
struct nmb_name nmbname;
|
||||||
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
|
* Check for our name on the unicast subnet first, only initiate
|
||||||
* further processing if we cannot find it.
|
* further processing if we cannot find it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
|
if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "become_domain_master_browser_wins:\n" );
|
||||||
{
|
dbgtext( "Attempting to become domain master browser " );
|
||||||
dbgtext( "become_domain_master_browser_wins:\n" );
|
dbgtext( "on workgroup %s, subnet %s.\n",
|
||||||
dbgtext( "Attempting to become domain master browser " );
|
workgroup_name, unicast_subnet->subnet_name );
|
||||||
dbgtext( "on workgroup %s, subnet %s.\n",
|
}
|
||||||
workgroup_name, unicast_subnet->subnet_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send out a query to establish whether there's a
|
/* Send out a query to establish whether there's a
|
||||||
domain master broswer registered with WINS. If not,
|
domain master broswer registered with WINS. If not,
|
||||||
we can become a domain master browser.
|
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",
|
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,
|
query_name(unicast_subnet, workgroup_name, nmbname.name_type,
|
||||||
become_domain_master_query_success,
|
become_domain_master_query_success,
|
||||||
become_domain_master_query_fail,
|
become_domain_master_query_fail,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -363,34 +355,32 @@ for domain master browser name %s on workgroup %s\n",
|
|||||||
|
|
||||||
void add_domain_names(time_t t)
|
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)))
|
if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastrun = t;
|
lastrun = t;
|
||||||
|
|
||||||
/* Do the "internet group" - <1c> names. */
|
/* Do the "internet group" - <1c> names. */
|
||||||
if (lp_domain_logons())
|
if (lp_domain_logons())
|
||||||
add_logon_names();
|
add_logon_names();
|
||||||
|
|
||||||
/* Do the domain master names. */
|
/* Do the domain master names. */
|
||||||
if(lp_domain_master())
|
if(lp_domain_master()) {
|
||||||
{
|
if(we_are_a_wins_client()) {
|
||||||
if(we_are_a_wins_client())
|
/* We register the WORKGROUP<1b> name with the WINS
|
||||||
{
|
server first, and call add_domain_master_bcast()
|
||||||
/* We register the WORKGROUP<1b> name with the WINS
|
only if this is successful.
|
||||||
server first, and call add_domain_master_bcast()
|
|
||||||
only if this is successful.
|
|
||||||
|
|
||||||
This results in domain logon services being gracefully provided,
|
This results in domain logon services being gracefully provided,
|
||||||
as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
|
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,
|
1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
|
||||||
cannot provide domain master / domain logon services.
|
cannot provide domain master / domain logon services.
|
||||||
*/
|
*/
|
||||||
become_domain_master_browser_wins(lp_workgroup());
|
become_domain_master_browser_wins(lp_workgroup());
|
||||||
}
|
} else {
|
||||||
else
|
become_domain_master_browser_bcast(lp_workgroup());
|
||||||
become_domain_master_browser_bcast(lp_workgroup());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
NBT netbios routines and daemon - version 2
|
NBT netbios routines and daemon - version 2
|
||||||
Copyright (C) Andrew Tridgell 1994-1998
|
Copyright (C) Andrew Tridgell 1994-1998
|
||||||
Copyright (C) Luke Kenneth Casson Leighton 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
|
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
|
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,
|
void insert_permanent_name_into_unicast( struct subnet_record *subrec,
|
||||||
struct nmb_name *nmbname, uint16 nb_type )
|
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)
|
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. */
|
/* The name needs to be created on the unicast subnet. */
|
||||||
(void)add_name_to_subnet( unicast_subnet, nmbname->name,
|
(void)add_name_to_subnet( unicast_subnet, name,
|
||||||
nmbname->name_type, nb_type,
|
nmbname->name_type, nb_type,
|
||||||
PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
|
PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
|
||||||
}
|
} else {
|
||||||
else
|
/* The name already exists on the unicast subnet. Add our local
|
||||||
{
|
IP for the given broadcast subnet to the name. */
|
||||||
/* The name already exists on the unicast subnet. Add our local
|
add_ip_to_name_record( namerec, subrec->myip);
|
||||||
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,
|
static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
|
||||||
struct nmb_name *nmbname )
|
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)
|
if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
|
||||||
{
|
/* Remove this broadcast subnet IP address from the name. */
|
||||||
/* Remove this broadcast subnet IP address from the name. */
|
remove_ip_from_name_record( namerec, subrec->myip);
|
||||||
remove_ip_from_name_record( namerec, subrec->myip);
|
if(namerec->data.num_ips == 0)
|
||||||
if(namerec->data.num_ips == 0)
|
remove_name_from_namelist( unicast_subnet, namerec);
|
||||||
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.
|
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 )
|
BOOL force_new_election )
|
||||||
{
|
{
|
||||||
struct work_record *work;
|
struct work_record *work;
|
||||||
struct server_record *servrec;
|
struct server_record *servrec;
|
||||||
struct nmb_name nmbname;
|
struct nmb_name nmbname;
|
||||||
|
|
||||||
if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
|
if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
|
||||||
{
|
DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
|
||||||
DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
|
|
||||||
subnet %s.\n", workgroup_name, subrec->subnet_name ));
|
subnet %s.\n", workgroup_name, subrec->subnet_name ));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
|
||||||
{
|
DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
|
||||||
DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
|
|
||||||
in workgroup %s on subnet %s\n",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), work->work_group, subrec->subnet_name));
|
global_myname(), work->work_group, subrec->subnet_name));
|
||||||
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update our server status - remove any master flag and replace
|
/* Update our server status - remove any master flag and replace
|
||||||
it with the potential browser flag. */
|
it with the potential browser flag. */
|
||||||
servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
|
servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
|
||||||
servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
|
servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
|
||||||
|
|
||||||
/* Tell the namelist writer to write out a change. */
|
/* Tell the namelist writer to write out a change. */
|
||||||
subrec->work_changed = True;
|
subrec->work_changed = True;
|
||||||
|
|
||||||
/* Reset our election flags. */
|
/* Reset our election flags. */
|
||||||
work->ElectionCriterion &= ~0x4;
|
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
|
/* Forget who the local master browser was for
|
||||||
this workgroup. */
|
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
|
* Ensure the IP address of this subnet is not registered as one
|
||||||
* of the IP addresses of the WORKGROUP<1d> name on the unicast
|
* of the IP addresses of the WORKGROUP<1d> name on the unicast
|
||||||
* subnet. This undoes what we did below when we became a local
|
* subnet. This undoes what we did below when we became a local
|
||||||
* master browser.
|
* 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)
|
if(force_new_election)
|
||||||
work->needelection = True;
|
work->needelection = True;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@@ -138,24 +134,25 @@ static void unbecome_local_master_success(struct subnet_record *subrec,
|
|||||||
struct nmb_name *released_name,
|
struct nmb_name *released_name,
|
||||||
struct in_addr released_ip)
|
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",
|
DEBUG(3,("unbecome_local_master_success: released name %s.\n",
|
||||||
nmb_namestr(released_name)));
|
nmb_namestr(released_name)));
|
||||||
|
|
||||||
/* Now reset the workgroup and server state. */
|
/* Now reset the workgroup and server state. */
|
||||||
reset_workgroup_state( subrec, released_name->name, force_new_election );
|
pull_ascii_nstring(relname, released_name->name);
|
||||||
|
reset_workgroup_state( subrec, relname, force_new_election );
|
||||||
|
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "*****\n\n" );
|
||||||
dbgtext( "*****\n\n" );
|
dbgtext( "Samba name server %s ", global_myname() );
|
||||||
dbgtext( "Samba name server %s ", global_myname() );
|
dbgtext( "has stopped being a local master browser " );
|
||||||
dbgtext( "has stopped being a local master browser " );
|
dbgtext( "for workgroup %s ", relname );
|
||||||
dbgtext( "for workgroup %s ", released_name->name );
|
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
|
||||||
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,
|
static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
|
||||||
struct nmb_name *fail_name)
|
struct nmb_name *fail_name)
|
||||||
{
|
{
|
||||||
struct name_record *namerec;
|
struct name_record *namerec;
|
||||||
struct userdata_struct *userdata = rrec->userdata;
|
struct userdata_struct *userdata = rrec->userdata;
|
||||||
BOOL force_new_election = False;
|
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)));
|
Removing from namelist anyway.\n", nmb_namestr(fail_name)));
|
||||||
|
|
||||||
/* Do it anyway. */
|
/* Do it anyway. */
|
||||||
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
|
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
|
||||||
if(namerec)
|
if(namerec)
|
||||||
remove_name_from_namelist(subrec, namerec);
|
remove_name_from_namelist(subrec, namerec);
|
||||||
|
|
||||||
/* Now reset the workgroup and server state. */
|
/* Now reset the workgroup and server state. */
|
||||||
reset_workgroup_state( subrec, fail_name->name, force_new_election );
|
pull_ascii_nstring(failname, fail_name->name);
|
||||||
|
reset_workgroup_state( subrec, failname, force_new_election );
|
||||||
|
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "*****\n\n" );
|
||||||
dbgtext( "*****\n\n" );
|
dbgtext( "Samba name server %s ", global_myname() );
|
||||||
dbgtext( "Samba name server %s ", global_myname() );
|
dbgtext( "has stopped being a local master browser " );
|
||||||
dbgtext( "has stopped being a local master browser " );
|
dbgtext( "for workgroup %s ", failname );
|
||||||
dbgtext( "for workgroup %s ", fail_name->name );
|
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
|
||||||
dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Utility function to remove the WORKGROUP<1d> 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)
|
BOOL force_new_election)
|
||||||
{
|
{
|
||||||
struct nmb_name nmbname;
|
struct nmb_name nmbname;
|
||||||
struct name_record *namerec;
|
struct name_record *namerec;
|
||||||
|
|
||||||
make_nmb_name(&nmbname, workgroup_name, 0x1d);
|
make_nmb_name(&nmbname, workgroup_name, 0x1d);
|
||||||
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
|
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
|
||||||
{
|
struct userdata_struct *userdata;
|
||||||
struct userdata_struct *userdata;
|
size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
|
||||||
size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
|
|
||||||
|
|
||||||
if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
|
if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
|
||||||
{
|
DEBUG(0,("release_1d_name: malloc fail.\n"));
|
||||||
DEBUG(0,("release_1d_name: malloc fail.\n"));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
userdata->copy_fn = NULL;
|
userdata->copy_fn = NULL;
|
||||||
userdata->free_fn = NULL;
|
userdata->free_fn = NULL;
|
||||||
userdata->userdata_len = sizeof(BOOL);
|
userdata->userdata_len = sizeof(BOOL);
|
||||||
memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
|
memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
|
||||||
|
|
||||||
release_name(subrec, namerec,
|
release_name(subrec, namerec,
|
||||||
unbecome_local_master_success,
|
unbecome_local_master_success,
|
||||||
unbecome_local_master_fail,
|
unbecome_local_master_fail,
|
||||||
userdata);
|
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 nmb_name *released_name,
|
||||||
struct in_addr released_ip)
|
struct in_addr released_ip)
|
||||||
{
|
{
|
||||||
DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
|
DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
|
||||||
nmb_namestr(released_name), subrec->subnet_name ));
|
nmb_namestr(released_name), subrec->subnet_name ));
|
||||||
|
|
||||||
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
||||||
remove_permanent_name_from_unicast( subrec, released_name);
|
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 response_record *rrec,
|
||||||
struct nmb_name *fail_name)
|
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.",
|
DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
|
||||||
nmb_namestr(fail_name), subrec->subnet_name ));
|
nmb_namestr(fail_name), subrec->subnet_name ));
|
||||||
|
|
||||||
/* Release the name anyway. */
|
/* Release the name anyway. */
|
||||||
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
|
namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
|
||||||
if(namerec)
|
if(namerec)
|
||||||
remove_name_from_namelist(subrec, namerec);
|
remove_name_from_namelist(subrec, namerec);
|
||||||
|
|
||||||
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
/* Remove the permanent MSBROWSE name added into the unicast subnet. */
|
||||||
remove_permanent_name_from_unicast( subrec, fail_name);
|
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,
|
void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
|
||||||
BOOL force_new_election)
|
BOOL force_new_election)
|
||||||
{
|
{
|
||||||
struct name_record *namerec;
|
struct name_record *namerec;
|
||||||
struct nmb_name nmbname;
|
struct nmb_name nmbname;
|
||||||
|
|
||||||
/* Sanity check. */
|
/* 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));
|
on subnet %s\n",work->work_group, subrec->subnet_name));
|
||||||
|
|
||||||
if(find_server_in_workgroup( work, global_myname()) == NULL)
|
if(find_server_in_workgroup( work, global_myname()) == NULL) {
|
||||||
{
|
DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
|
||||||
DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
|
|
||||||
in workgroup %s on subnet %s\n",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), work->work_group, subrec->subnet_name));
|
global_myname(), work->work_group, subrec->subnet_name));
|
||||||
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the state to unbecoming. */
|
/* Set the state to unbecoming. */
|
||||||
work->mst_state = MST_UNBECOMING_MASTER;
|
work->mst_state = MST_UNBECOMING_MASTER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release the WORKGROUP<1d> name asap to allow another machine to
|
* Release the WORKGROUP<1d> name asap to allow another machine to
|
||||||
* claim it.
|
* 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. */
|
/* Deregister any browser names we may have. */
|
||||||
make_nmb_name(&nmbname, MSBROWSE, 0x1);
|
make_nmb_name(&nmbname, MSBROWSE, 0x1);
|
||||||
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
|
if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
|
||||||
{
|
release_name(subrec, namerec,
|
||||||
release_name(subrec, namerec,
|
release_msbrowse_name_success,
|
||||||
release_msbrowse_name_success,
|
release_msbrowse_name_fail,
|
||||||
release_msbrowse_name_fail,
|
NULL);
|
||||||
NULL);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure we have sent and processed these release packets
|
* Ensure we have sent and processed these release packets
|
||||||
* before returning - we don't want to process any election
|
* before returning - we don't want to process any election
|
||||||
* packets before dealing with the 1d release.
|
* 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,
|
uint16 nb_flags,
|
||||||
int ttl, struct in_addr registered_ip)
|
int ttl, struct in_addr registered_ip)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct server_record *sl;
|
struct server_record *sl;
|
||||||
struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
|
struct work_record *work;
|
||||||
struct server_record *servrec;
|
struct server_record *servrec;
|
||||||
|
nstring regname;
|
||||||
|
|
||||||
if(!work)
|
pull_ascii_nstring(regname, registered_name->name);
|
||||||
{
|
work = find_workgroup_on_subnet( subrec, regname);
|
||||||
DEBUG(0,("become_local_master_stage2: Error - cannot find \
|
|
||||||
workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
|
if(!work) {
|
||||||
{
|
DEBUG(0,("become_local_master_stage2: Error - cannot find \
|
||||||
DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
|
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",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), registered_name->name, subrec->subnet_name));
|
global_myname(), regname, subrec->subnet_name));
|
||||||
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
|
||||||
return;
|
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));
|
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 */
|
/* update our server status */
|
||||||
servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
|
servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
|
||||||
servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
|
servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
|
||||||
|
|
||||||
/* Tell the namelist writer to write out a change. */
|
/* Tell the namelist writer to write out a change. */
|
||||||
subrec->work_changed = True;
|
subrec->work_changed = True;
|
||||||
|
|
||||||
/* Add this name to the workgroup as local master browser. */
|
/* Add this name to the workgroup as local master browser. */
|
||||||
set_workgroup_local_master_browser_name( work, global_myname());
|
set_workgroup_local_master_browser_name( work, global_myname());
|
||||||
|
|
||||||
/* Count the number of servers we have on our list. If it's
|
/* Count the number of servers we have on our list. If it's
|
||||||
less than 10 (just a heuristic) request the servers
|
less than 10 (just a heuristic) request the servers
|
||||||
to announce themselves.
|
to announce themselves.
|
||||||
*/
|
*/
|
||||||
for( sl = work->serverlist; sl != NULL; sl = sl->next)
|
for( sl = work->serverlist; sl != NULL; sl = sl->next)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i < 10)
|
if (i < 10) {
|
||||||
{
|
/* Ask all servers on our local net to announce to us. */
|
||||||
/* Ask all servers on our local net to announce to us. */
|
broadcast_announce_request(subrec, work);
|
||||||
broadcast_announce_request(subrec, work);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we are a local master on a broadcast subnet, we need to add
|
* 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
|
* 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
|
* 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
|
* the unicast subnet as a WINS server always returns true when registering
|
||||||
* this name, and discards the registration. We use the number of IP
|
* this name, and discards the registration. We use the number of IP
|
||||||
* addresses registered to this name as a reference count, as we
|
* 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
|
* remove this broadcast subnet IP address from it when we stop becoming a local
|
||||||
* master browser for this broadcast subnet.
|
* 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
|
/* 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. */
|
master browser as soon as possible that we are a local master browser. */
|
||||||
reset_announce_timer();
|
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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.
|
Failed to register the WORKGROUP<1d> name.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void become_local_master_fail2(struct subnet_record *subrec,
|
static void become_local_master_fail2(struct subnet_record *subrec,
|
||||||
struct response_record *rrec,
|
struct response_record *rrec,
|
||||||
struct nmb_name *fail_name)
|
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));
|
Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
|
||||||
|
|
||||||
if(!work)
|
pull_ascii_nstring(failname, fail_name->name);
|
||||||
{
|
work = find_workgroup_on_subnet( subrec, failname);
|
||||||
DEBUG(0,("become_local_master_fail2: Error - cannot find \
|
|
||||||
workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Roll back all the way by calling unbecome_local_master_browser(). */
|
if(!work) {
|
||||||
unbecome_local_master_browser(subrec, work, False);
|
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,
|
uint16 nb_flags,
|
||||||
int ttl, struct in_addr registered_ip)
|
int ttl, struct in_addr registered_ip)
|
||||||
{
|
{
|
||||||
char *work_name = userdata->data;
|
char *work_name = userdata->data;
|
||||||
struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
|
struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
|
||||||
|
|
||||||
if(!work)
|
if(!work) {
|
||||||
{
|
DEBUG(0,("become_local_master_stage1: Error - cannot find \
|
||||||
DEBUG(0,("become_local_master_stage1: Error - cannot find \
|
%s on subnet %s\n", work_name, subrec->subnet_name));
|
||||||
workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
|
DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
|
||||||
work->work_group));
|
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
|
* 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
|
* the MSBROWSE name to the unicast subnet so that we can answer
|
||||||
* unicast requests sent to this name. We create this name directly on
|
* unicast requests sent to this name. We create this name directly on
|
||||||
* the unicast subnet.
|
* 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. */
|
/* Attempt to register the WORKGROUP<1d> name. */
|
||||||
register_name(subrec, work->work_group,0x1d,samba_nb_type,
|
register_name(subrec, work->work_group,0x1d,samba_nb_type,
|
||||||
become_local_master_stage2,
|
become_local_master_stage2,
|
||||||
become_local_master_fail2,
|
become_local_master_fail2,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -481,29 +477,27 @@ static void become_local_master_fail1(struct subnet_record *subrec,
|
|||||||
struct response_record *rrec,
|
struct response_record *rrec,
|
||||||
struct nmb_name *fail_name)
|
struct nmb_name *fail_name)
|
||||||
{
|
{
|
||||||
char *work_name = rrec->userdata->data;
|
char *work_name = rrec->userdata->data;
|
||||||
struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
|
struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
|
||||||
|
|
||||||
if(!work)
|
if(!work) {
|
||||||
{
|
DEBUG(0,("become_local_master_fail1: Error - cannot find \
|
||||||
DEBUG(0,("become_local_master_fail1: Error - cannot find \
|
|
||||||
workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
|
workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(find_server_in_workgroup(work, global_myname()) == NULL)
|
if(find_server_in_workgroup(work, global_myname()) == NULL) {
|
||||||
{
|
DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
|
||||||
DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
|
|
||||||
in workgroup %s on subnet %s\n",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), work->work_group, subrec->subnet_name));
|
global_myname(), work->work_group, subrec->subnet_name));
|
||||||
return;
|
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",
|
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)
|
void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
|
||||||
{
|
{
|
||||||
struct userdata_struct *userdata;
|
struct userdata_struct *userdata;
|
||||||
size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
|
size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
|
||||||
|
|
||||||
/* Sanity check. */
|
/* Sanity check. */
|
||||||
if (!lp_local_master())
|
if (!lp_local_master()) {
|
||||||
{
|
DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
|
||||||
DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!AM_POTENTIAL_MASTER_BROWSER(work))
|
if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
|
||||||
{
|
DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
|
||||||
DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
|
work->mst_state ));
|
||||||
work->mst_state ));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(find_server_in_workgroup( work, global_myname()) == NULL)
|
if(find_server_in_workgroup( work, global_myname()) == NULL) {
|
||||||
{
|
DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
|
||||||
DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
|
|
||||||
in workgroup %s on subnet %s\n",
|
in workgroup %s on subnet %s\n",
|
||||||
global_myname(), work->work_group, subrec->subnet_name));
|
global_myname(), work->work_group, subrec->subnet_name));
|
||||||
return;
|
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));
|
%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"));
|
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->mst_state = MST_BACKUP; /* an election win was successful */
|
||||||
|
|
||||||
work->ElectionCriterion |= 0x5;
|
work->ElectionCriterion |= 0x5;
|
||||||
|
|
||||||
/* Tell the namelist writer to write out a change. */
|
/* Tell the namelist writer to write out a change. */
|
||||||
subrec->work_changed = True;
|
subrec->work_changed = True;
|
||||||
|
|
||||||
/* Setup the userdata_struct. */
|
/* Setup the userdata_struct. */
|
||||||
if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
|
if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
|
||||||
{
|
DEBUG(0,("become_local_master_browser: malloc fail.\n"));
|
||||||
DEBUG(0,("become_local_master_browser: malloc fail.\n"));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
userdata->copy_fn = NULL;
|
userdata->copy_fn = NULL;
|
||||||
userdata->free_fn = NULL;
|
userdata->free_fn = NULL;
|
||||||
userdata->userdata_len = strlen(work->work_group)+1;
|
userdata->userdata_len = strlen(work->work_group)+1;
|
||||||
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
|
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
|
||||||
|
|
||||||
/* Register the special browser group name. */
|
/* Register the special browser group name. */
|
||||||
register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
|
register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
|
||||||
become_local_master_stage1,
|
become_local_master_stage1,
|
||||||
become_local_master_fail1,
|
become_local_master_fail1,
|
||||||
userdata);
|
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)
|
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 ));
|
for workgroup %s.\n", newname, work->work_group ));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -600,5 +590,5 @@ local_master_browser_name for workgroup %s to workgroup name.\n",
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fstrcpy(work->local_master_browser_name, newname);
|
fstrcpy(work->local_master_browser_name, newname);
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
|
||||||
char *browser_name,
|
const char *browser_name,
|
||||||
struct in_addr ip )
|
struct in_addr ip )
|
||||||
{
|
{
|
||||||
struct browse_cache_record *browc;
|
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;
|
struct browse_cache_record *browc;
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
NBT netbios routines and daemon - version 2
|
NBT netbios routines and daemon - version 2
|
||||||
Copyright (C) Andrew Tridgell 1994-1998
|
Copyright (C) Andrew Tridgell 1994-1998
|
||||||
Copyright (C) Luke Kenneth Casson Leighton 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
|
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
|
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.
|
As a domain master browser, do a sync with a local master browser.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static void sync_with_lmb(struct browse_cache_record *browc)
|
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( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "sync_with_lmb:\n" );
|
||||||
{
|
dbgtext( "Failed to get a workgroup for a local master browser " );
|
||||||
dbgtext( "sync_with_lmb:\n" );
|
dbgtext( "cache entry workgroup " );
|
||||||
dbgtext( "Failed to get a workgroup for a local master browser " );
|
dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
|
||||||
dbgtext( "cache entry workgroup " );
|
}
|
||||||
dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should only be doing this if we are a domain master browser for
|
/* We should only be doing this if we are a domain master browser for
|
||||||
the given workgroup. Ensure this is so. */
|
the given workgroup. Ensure this is so. */
|
||||||
|
|
||||||
if(!AM_DOMAIN_MASTER_BROWSER(work))
|
if(!AM_DOMAIN_MASTER_BROWSER(work)) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "sync_with_lmb:\n" );
|
||||||
{
|
dbgtext( "We are trying to sync with a local master browser " );
|
||||||
dbgtext( "sync_with_lmb:\n" );
|
dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
|
||||||
dbgtext( "We are trying to sync with a local master browser " );
|
dbgtext( "and we are not a domain master browser on this workgroup.\n" );
|
||||||
dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
|
dbgtext( "Error!\n" );
|
||||||
dbgtext( "and we are not a domain master browser on this workgroup.\n" );
|
}
|
||||||
dbgtext( "Error!\n" );
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( DEBUGLVL( 2 ) )
|
if( DEBUGLVL( 2 ) ) {
|
||||||
{
|
dbgtext( "sync_with_lmb:\n" );
|
||||||
dbgtext( "sync_with_lmb:\n" );
|
dbgtext( "Initiating sync with local master browser " );
|
||||||
dbgtext( "Initiating sync with local master browser " );
|
dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
|
||||||
dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
|
dbgtext( "for workgroup %s\n", browc->work_group );
|
||||||
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.
|
Sync or expire any local master browsers.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void dmb_expire_and_sync_browser_lists(time_t t)
|
void dmb_expire_and_sync_browser_lists(time_t t)
|
||||||
{
|
{
|
||||||
static time_t last_run = 0;
|
static time_t last_run = 0;
|
||||||
struct browse_cache_record *browc;
|
struct browse_cache_record *browc;
|
||||||
|
|
||||||
/* Only do this every 20 seconds. */
|
/* Only do this every 20 seconds. */
|
||||||
if (t - last_run < 20)
|
if (t - last_run < 20)
|
||||||
return;
|
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 );
|
for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
|
||||||
browc;
|
browc;
|
||||||
browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
|
browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
|
||||||
{
|
if (browc->sync_time < t)
|
||||||
if (browc->sync_time < t)
|
sync_with_lmb(browc);
|
||||||
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)
|
static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
|
||||||
{
|
{
|
||||||
pstring outbuf;
|
pstring outbuf;
|
||||||
fstring myname;
|
fstring myname;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if(ismyip(work->dmb_addr))
|
if(ismyip(work->dmb_addr)) {
|
||||||
{
|
if( DEBUGLVL( 2 ) ) {
|
||||||
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( "announce_local_master_browser_to_domain_master_browser:\n" );
|
dbgtext( "workgroup %s. ", work->work_group );
|
||||||
dbgtext( "We are both a domain and a local master browser for " );
|
dbgtext( "Do not announce to ourselves.\n" );
|
||||||
dbgtext( "workgroup %s. ", work->work_group );
|
}
|
||||||
dbgtext( "Do not announce to ourselves.\n" );
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(outbuf,'\0',sizeof(outbuf));
|
memset(outbuf,'\0',sizeof(outbuf));
|
||||||
p = outbuf;
|
p = outbuf;
|
||||||
SCVAL(p,0,ANN_MasterAnnouncement);
|
SCVAL(p,0,ANN_MasterAnnouncement);
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
fstrcpy(myname, global_myname());
|
fstrcpy(myname, global_myname());
|
||||||
strupper_m(myname);
|
strupper_m(myname);
|
||||||
myname[15]='\0';
|
myname[15]='\0';
|
||||||
push_pstring_base(p, myname, outbuf);
|
/* 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 ) )
|
if( DEBUGLVL( 4 ) ) {
|
||||||
{
|
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
|
||||||
dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
|
dbgtext( "Sending local master announce to " );
|
||||||
dbgtext( "Sending local master announce to " );
|
dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
|
||||||
dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
|
work->work_group );
|
||||||
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,
|
global_myname(), 0x0, work->dmb_name.name, 0x0,
|
||||||
work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
|
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)
|
static void sync_with_dmb(struct work_record *work)
|
||||||
{
|
{
|
||||||
if( DEBUGLVL( 2 ) )
|
nstring dmb_name;
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type,
|
if( DEBUGLVL( 2 ) ) {
|
||||||
work->dmb_addr, False, True);
|
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 res_rec *answers,
|
||||||
struct in_addr from_ip)
|
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( work == NULL ) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "domain_master_node_status_success:\n" );
|
||||||
{
|
dbgtext( "Unable to find workgroup " );
|
||||||
dbgtext( "domain_master_node_status_success:\n" );
|
dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
|
||||||
dbgtext( "Unable to find workgroup " );
|
}
|
||||||
dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( DEBUGLVL( 3 ) )
|
if( DEBUGLVL( 3 ) ) {
|
||||||
{
|
dbgtext( "domain_master_node_status_success:\n" );
|
||||||
dbgtext( "domain_master_node_status_success:\n" );
|
dbgtext( "Success in node status for workgroup " );
|
||||||
dbgtext( "Success in node status for workgroup " );
|
dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
|
||||||
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
|
/* Go through the list of names found at answers->rdata and look for
|
||||||
the first SERVER<0x20> name. */
|
the first SERVER<0x20> name. */
|
||||||
|
|
||||||
if(answers->rdata != NULL)
|
if(answers->rdata != NULL) {
|
||||||
{
|
char *p = answers->rdata;
|
||||||
char *p = answers->rdata;
|
int numnames = CVAL(p, 0);
|
||||||
int numnames = CVAL(p, 0);
|
|
||||||
|
|
||||||
p += 1;
|
p += 1;
|
||||||
|
|
||||||
while (numnames--)
|
while (numnames--) {
|
||||||
{
|
nstring qname;
|
||||||
char qname[17];
|
uint16 nb_flags;
|
||||||
uint16 nb_flags;
|
int name_type;
|
||||||
int name_type;
|
|
||||||
|
|
||||||
StrnCpy(qname,p,15);
|
pull_ascii_nstring(qname, p);
|
||||||
name_type = CVAL(p,15);
|
name_type = CVAL(p,15);
|
||||||
nb_flags = get_nb_flags(&p[16]);
|
nb_flags = get_nb_flags(&p[16]);
|
||||||
trim_string(qname,NULL," ");
|
trim_string(qname,NULL," ");
|
||||||
|
|
||||||
p += 18;
|
p += 18;
|
||||||
|
|
||||||
if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
|
if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
|
||||||
{
|
struct nmb_name nmbname;
|
||||||
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
|
/* Copy the dmb name and IP address
|
||||||
into the workgroup struct. */
|
into the workgroup struct. */
|
||||||
|
|
||||||
work->dmb_name = nmbname;
|
work->dmb_name = nmbname;
|
||||||
putip((char *)&work->dmb_addr, &from_ip);
|
putip((char *)&work->dmb_addr, &from_ip);
|
||||||
|
|
||||||
/* Do the local master browser announcement to the domain
|
/* Do the local master browser announcement to the domain
|
||||||
master browser name and IP. */
|
master browser name and IP. */
|
||||||
announce_local_master_browser_to_domain_master_browser( work );
|
announce_local_master_browser_to_domain_master_browser( work );
|
||||||
|
|
||||||
/* Now synchronise lists with the domain master browser. */
|
/* Now synchronise lists with the domain master browser. */
|
||||||
sync_with_dmb(work);
|
sync_with_dmb(work);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if( DEBUGLVL( 0 ) ) {
|
||||||
else
|
dbgtext( "domain_master_node_status_success:\n" );
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
|
||||||
{
|
dbgtext( "%s.\n", inet_ntoa(from_ip) );
|
||||||
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,
|
static void domain_master_node_status_fail(struct subnet_record *subrec,
|
||||||
struct response_record *rrec)
|
struct response_record *rrec)
|
||||||
{
|
{
|
||||||
struct userdata_struct *userdata = rrec->userdata;
|
struct userdata_struct *userdata = rrec->userdata;
|
||||||
|
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "domain_master_node_status_fail:\n" );
|
||||||
dbgtext( "domain_master_node_status_fail:\n" );
|
dbgtext( "Doing a node status request to the domain master browser\n" );
|
||||||
dbgtext( "Doing a node status request to the domain master browser\n" );
|
dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
|
||||||
dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
|
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
|
||||||
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
|
dbgtext( "Cannot sync browser lists.\n" );
|
||||||
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 userdata_struct *userdata_in,
|
||||||
struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
|
struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Unfortunately, finding the IP address of the Domain Master Browser,
|
* 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
|
* 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
|
* SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
|
||||||
* respond to the SMBSERVER name. To get this name from IP
|
* respond to the SMBSERVER name. To get this name from IP
|
||||||
* address we do a Node status request, and look for the first
|
* address we do a Node status request, and look for the first
|
||||||
* NAME<0x20> in the response, and take that as the server name.
|
* 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
|
* 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
|
* 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
|
* is returned every time, we don't need to do the node status
|
||||||
* request.
|
* request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct work_record *work;
|
struct work_record *work;
|
||||||
struct nmb_name nmbname;
|
struct nmb_name nmbname;
|
||||||
struct userdata_struct *userdata;
|
struct userdata_struct *userdata;
|
||||||
size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
|
size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
|
||||||
|
nstring qname;
|
||||||
|
|
||||||
if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
|
pull_ascii_nstring(qname, q_name->name);
|
||||||
{
|
if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "find_domain_master_name_query_success:\n" );
|
||||||
dbgtext( "find_domain_master_name_query_success:\n" );
|
dbgtext( "Failed to find workgroup %s\n", qname);
|
||||||
dbgtext( "Failed to find workgroup %s\n", q_name->name );
|
}
|
||||||
}
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First check if we already have a dmb for this workgroup. */
|
/* 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))
|
if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) {
|
||||||
{
|
/* Do the local master browser announcement to the domain
|
||||||
/* Do the local master browser announcement to the domain
|
master browser name and IP. */
|
||||||
master browser name and IP. */
|
announce_local_master_browser_to_domain_master_browser( work );
|
||||||
announce_local_master_browser_to_domain_master_browser( work );
|
|
||||||
|
|
||||||
/* Now synchronise lists with the domain master browser. */
|
/* Now synchronise lists with the domain master browser. */
|
||||||
sync_with_dmb(work);
|
sync_with_dmb(work);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
zero_ip(&work->dmb_addr);
|
||||||
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
|
/* We used to use the name "*",0x0 here, but some Windows
|
||||||
* servers don't answer that name. However we *know* they
|
* servers don't answer that name. However we *know* they
|
||||||
* have the name workgroup#1b (as we just looked it up).
|
* have the name workgroup#1b (as we just looked it up).
|
||||||
* So do the node status request on this name instead.
|
* So do the node status request on this name instead.
|
||||||
* Found at LBL labs. JRA.
|
* 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
|
/* Put the workgroup name into the userdata so we know
|
||||||
what workgroup we're talking to when the reply comes
|
what workgroup we're talking to when the reply comes
|
||||||
back. */
|
back. */
|
||||||
|
|
||||||
/* Setup the userdata_struct - this is copied so we can use
|
/* Setup the userdata_struct - this is copied so we can use
|
||||||
a stack variable for this. */
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
userdata->copy_fn = NULL;
|
if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
|
||||||
userdata->free_fn = NULL;
|
DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
|
||||||
userdata->userdata_len = strlen(work->work_group)+1;
|
return;
|
||||||
overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
|
}
|
||||||
|
|
||||||
node_status( subrec, &nmbname, answer_ip,
|
userdata->copy_fn = NULL;
|
||||||
domain_master_node_status_success,
|
userdata->free_fn = NULL;
|
||||||
domain_master_node_status_fail,
|
userdata->userdata_len = strlen(work->work_group)+1;
|
||||||
userdata);
|
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.
|
Function called when a query for a WORKGROUP<1b> name fails.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void find_domain_master_name_query_fail(struct subnet_record *subrec,
|
static void find_domain_master_name_query_fail(struct subnet_record *subrec,
|
||||||
struct response_record *rrec,
|
struct response_record *rrec,
|
||||||
struct nmb_name *question_name, int fail_code)
|
struct nmb_name *question_name, int fail_code)
|
||||||
{
|
{
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "find_domain_master_name_query_fail:\n" );
|
||||||
dbgtext( "find_domain_master_name_query_fail:\n" );
|
dbgtext( "Unable to find the Domain Master Browser name " );
|
||||||
dbgtext( "Unable to find the Domain Master Browser name " );
|
dbgtext( "%s for the workgroup %s.\n",
|
||||||
dbgtext( "%s for the workgroup %s.\n",
|
nmb_namestr(question_name), question_name->name );
|
||||||
nmb_namestr(question_name), question_name->name );
|
dbgtext( "Unable to sync browse lists in this workgroup.\n" );
|
||||||
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,
|
void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
|
||||||
struct work_record *work)
|
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. */
|
/* First, query for the WORKGROUP<1b> name from the WINS server. */
|
||||||
if(we_are_a_wins_client() == False)
|
query_name(unicast_subnet, work->work_group, 0x1b,
|
||||||
{
|
|
||||||
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,
|
|
||||||
find_domain_master_name_query_success,
|
find_domain_master_name_query_success,
|
||||||
find_domain_master_name_query_fail,
|
find_domain_master_name_query_fail,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -421,89 +398,81 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub
|
|||||||
struct res_rec *answers,
|
struct res_rec *answers,
|
||||||
struct in_addr from_ip)
|
struct in_addr from_ip)
|
||||||
{
|
{
|
||||||
struct work_record *work;
|
struct work_record *work;
|
||||||
fstring server_name;
|
fstring server_name;
|
||||||
|
|
||||||
server_name[0] = 0;
|
server_name[0] = 0;
|
||||||
|
|
||||||
if( DEBUGLVL( 3 ) )
|
if( DEBUGLVL( 3 ) ) {
|
||||||
{
|
dbgtext( "get_domain_master_name_node_status_success:\n" );
|
||||||
dbgtext( "get_domain_master_name_node_status_success:\n" );
|
dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
|
||||||
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
|
* Go through the list of names found at answers->rdata and look for
|
||||||
* the first WORKGROUP<0x1b> name.
|
* the first WORKGROUP<0x1b> name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(answers->rdata != NULL)
|
if(answers->rdata != NULL) {
|
||||||
{
|
char *p = answers->rdata;
|
||||||
char *p = answers->rdata;
|
int numnames = CVAL(p, 0);
|
||||||
int numnames = CVAL(p, 0);
|
|
||||||
|
|
||||||
p += 1;
|
p += 1;
|
||||||
|
|
||||||
while (numnames--)
|
while (numnames--) {
|
||||||
{
|
nstring qname;
|
||||||
char qname[17];
|
uint16 nb_flags;
|
||||||
uint16 nb_flags;
|
int name_type;
|
||||||
int name_type;
|
|
||||||
|
|
||||||
StrnCpy(qname,p,15);
|
pull_ascii_nstring(qname, p);
|
||||||
name_type = CVAL(p,15);
|
name_type = CVAL(p,15);
|
||||||
nb_flags = get_nb_flags(&p[16]);
|
nb_flags = get_nb_flags(&p[16]);
|
||||||
trim_string(qname,NULL," ");
|
trim_string(qname,NULL," ");
|
||||||
|
|
||||||
p += 18;
|
p += 18;
|
||||||
|
|
||||||
if(!(nb_flags & NB_GROUP) && (name_type == 0x00) &&
|
if(!(nb_flags & NB_GROUP) && (name_type == 0x00) &&
|
||||||
server_name[0] == 0) {
|
server_name[0] == 0) {
|
||||||
/* this is almost certainly the server netbios name */
|
/* this is almost certainly the server netbios name */
|
||||||
fstrcpy(server_name, qname);
|
fstrcpy(server_name, qname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
|
if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
|
||||||
{
|
if( DEBUGLVL( 5 ) ) {
|
||||||
if( DEBUGLVL( 5 ) )
|
dbgtext( "get_domain_master_name_node_status_success:\n" );
|
||||||
{
|
dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
|
||||||
dbgtext( "get_domain_master_name_node_status_success:\n" );
|
dbgtext( "is a domain master browser for workgroup " );
|
||||||
dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
|
dbgtext( "%s. Adding this name.\n", qname );
|
||||||
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
|
* If we don't already know about this workgroup, add it
|
||||||
* to the workgroup list on the unicast_subnet.
|
* 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;
|
|
||||||
|
|
||||||
/* remember who the master is */
|
if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
|
||||||
fstrcpy(work->local_master_browser_name, server_name);
|
struct nmb_name nmbname;
|
||||||
make_nmb_name(&nmbname, server_name, 0x20);
|
/*
|
||||||
work->dmb_name = nmbname;
|
* Add it - with an hour in the cache.
|
||||||
work->dmb_addr = from_ip;
|
*/
|
||||||
}
|
if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
}
|
/* remember who the master is */
|
||||||
}
|
fstrcpy(work->local_master_browser_name, server_name);
|
||||||
else
|
make_nmb_name(&nmbname, server_name, 0x20);
|
||||||
if( DEBUGLVL( 0 ) )
|
work->dmb_name = nmbname;
|
||||||
{
|
work->dmb_addr = from_ip;
|
||||||
dbgtext( "get_domain_master_name_node_status_success:\n" );
|
}
|
||||||
dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
|
break;
|
||||||
dbgtext( "%s.\n", inet_ntoa(from_ip) );
|
}
|
||||||
}
|
}
|
||||||
|
} 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,
|
static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
|
||||||
struct response_record *rrec)
|
struct response_record *rrec)
|
||||||
{
|
{
|
||||||
if( DEBUGLVL( 0 ) )
|
if( DEBUGLVL( 0 ) ) {
|
||||||
{
|
dbgtext( "get_domain_master_name_node_status_fail:\n" );
|
||||||
dbgtext( "get_domain_master_name_node_status_fail:\n" );
|
dbgtext( "Doing a node status request to the domain master browser " );
|
||||||
dbgtext( "Doing a node status request to the domain master browser " );
|
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
|
||||||
dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
|
dbgtext( "Cannot get workgroup name.\n" );
|
||||||
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 userdata_struct *userdata_in,
|
||||||
struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
|
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
|
* 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
|
* 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
|
* 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'
|
* the workgroup name that we will add to the unicast subnet as a 'non-local'
|
||||||
* workgroup.
|
* workgroup.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct nmb_name nmbname;
|
struct nmb_name nmbname;
|
||||||
struct in_addr send_ip;
|
struct in_addr send_ip;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( DEBUGLVL( 5 ) )
|
if( DEBUGLVL( 5 ) ) {
|
||||||
{
|
dbgtext( "find_all_domain_master_names_query_succes:\n" );
|
||||||
dbgtext( "find_all_domain_master_names_query_succes:\n" );
|
dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
|
||||||
dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
|
dbgtext( "IP addresses for Domain Master Browsers.\n" );
|
||||||
dbgtext( "IP addresses for Domain Master Browsers.\n" );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < rrec->rdlength / 6; i++)
|
for(i = 0; i < rrec->rdlength / 6; i++) {
|
||||||
{
|
/* Initiate the node status requests. */
|
||||||
/* Initiate the node status requests. */
|
make_nmb_name(&nmbname, "*", 0);
|
||||||
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(ismyip( send_ip )) {
|
||||||
{
|
if( DEBUGLVL( 5 ) ) {
|
||||||
if( DEBUGLVL( 5 ) )
|
dbgtext( "find_all_domain_master_names_query_succes:\n" );
|
||||||
{
|
dbgtext( "Not sending node status to our own IP " );
|
||||||
dbgtext( "find_all_domain_master_names_query_succes:\n" );
|
dbgtext( "%s.\n", inet_ntoa(send_ip) );
|
||||||
dbgtext( "Not sending node status to our own IP " );
|
}
|
||||||
dbgtext( "%s.\n", inet_ntoa(send_ip) );
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( DEBUGLVL( 5 ) )
|
if( DEBUGLVL( 5 ) ) {
|
||||||
{
|
dbgtext( "find_all_domain_master_names_query_success:\n" );
|
||||||
dbgtext( "find_all_domain_master_names_query_success:\n" );
|
dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
|
||||||
dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
node_status( subrec, &nmbname, send_ip,
|
node_status( subrec, &nmbname, send_ip,
|
||||||
get_domain_master_name_node_status_success,
|
get_domain_master_name_node_status_success,
|
||||||
get_domain_master_name_node_status_fail,
|
get_domain_master_name_node_status_fail,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -591,13 +554,12 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec
|
|||||||
struct response_record *rrec,
|
struct response_record *rrec,
|
||||||
struct nmb_name *question_name, int fail_code)
|
struct nmb_name *question_name, int fail_code)
|
||||||
{
|
{
|
||||||
if( DEBUGLVL( 10 ) )
|
if( DEBUGLVL( 10 ) ) {
|
||||||
{
|
dbgtext( "find_domain_master_name_query_fail:\n" );
|
||||||
dbgtext( "find_domain_master_name_query_fail:\n" );
|
dbgtext( "WINS server did not reply to a query for name " );
|
||||||
dbgtext( "WINS server did not reply to a query for name " );
|
dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
|
||||||
dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
|
dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
|
||||||
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
|
<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.
|
subnet. This is expensive, so we only do this every 15 minutes.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void collect_all_workgroup_names_from_wins_server(time_t t)
|
void collect_all_workgroup_names_from_wins_server(time_t t)
|
||||||
{
|
{
|
||||||
static time_t lastrun = 0;
|
static time_t lastrun = 0;
|
||||||
struct work_record *work;
|
struct work_record *work;
|
||||||
struct nmb_name nmbname;
|
|
||||||
|
|
||||||
/* Only do this if we are using a WINS server. */
|
/* Only do this if we are using a WINS server. */
|
||||||
if(we_are_a_wins_client() == False)
|
if(we_are_a_wins_client() == False)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Check to see if we are a domain master browser on the unicast subnet. */
|
/* 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((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
|
||||||
{
|
if( DEBUGLVL( 0 ) ) {
|
||||||
if( DEBUGLVL( 0 ) )
|
dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
|
||||||
{
|
dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
|
||||||
dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
|
dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
|
||||||
dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
|
}
|
||||||
dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!AM_DOMAIN_MASTER_BROWSER(work))
|
if(!AM_DOMAIN_MASTER_BROWSER(work))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((lastrun != 0) && (t < lastrun + (15 * 60)))
|
if ((lastrun != 0) && (t < lastrun + (15 * 60)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastrun = t;
|
lastrun = t;
|
||||||
|
|
||||||
make_nmb_name(&nmbname,"*",0x1b);
|
/* First, query for the *<1b> name from the WINS server. */
|
||||||
|
query_name(unicast_subnet, "*", 0x1b,
|
||||||
/* First, query for the *<1b> name from the WINS server. */
|
find_all_domain_master_names_query_success,
|
||||||
query_name(unicast_subnet, nmbname.name, nmbname.name_type,
|
find_all_domain_master_names_query_fail,
|
||||||
find_all_domain_master_names_query_success,
|
NULL);
|
||||||
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
|
we use a randomised system where sync probability is inversely proportional
|
||||||
to the number of known workgroups
|
to the number of known workgroups
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void sync_all_dmbs(time_t t)
|
void sync_all_dmbs(time_t t)
|
||||||
{
|
{
|
||||||
static time_t lastrun = 0;
|
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
|
/* Check to see if we are a domain master browser on the
|
||||||
unicast subnet. */
|
unicast subnet. */
|
||||||
work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
|
work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
|
||||||
if (!work) return;
|
if (!work)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!AM_DOMAIN_MASTER_BROWSER(work))
|
if (!AM_DOMAIN_MASTER_BROWSER(work))
|
||||||
return;
|
return;
|
||||||
@@ -687,7 +647,10 @@ void sync_all_dmbs(time_t t)
|
|||||||
/* sync with a probability of 1/count */
|
/* sync with a probability of 1/count */
|
||||||
for (work=unicast_subnet->workgrouplist; work; work = work->next) {
|
for (work=unicast_subnet->workgrouplist; work; work = work->next) {
|
||||||
if (strcmp(lp_workgroup(), work->work_group)) {
|
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;
|
lastrun = t;
|
||||||
|
|
||||||
@@ -699,13 +662,15 @@ void sync_all_dmbs(time_t t)
|
|||||||
0x20);
|
0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pull_ascii_nstring(dmb_name, work->dmb_name.name);
|
||||||
|
|
||||||
DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
|
DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
|
||||||
work->dmb_name.name,
|
dmb_name, inet_ntoa(work->dmb_addr)));
|
||||||
inet_ntoa(work->dmb_addr)));
|
|
||||||
sync_browse_lists(work,
|
sync_browse_lists(work,
|
||||||
work->dmb_name.name,
|
dmb_name,
|
||||||
work->dmb_name.name_type,
|
work->dmb_name.name_type,
|
||||||
work->dmb_addr, False, False);
|
work->dmb_addr, False, False);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
NBT netbios routines and daemon - version 2
|
NBT netbios routines and daemon - version 2
|
||||||
Copyright (C) Andrew Tridgell 1994-1998
|
Copyright (C) Andrew Tridgell 1994-1998
|
||||||
Copyright (C) Luke Kenneth Casson Leighton 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
|
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
|
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.
|
Send an election datagram packet.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
|
static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
|
||||||
uint32 criterion, int timeup,const char *server_name)
|
uint32 criterion, int timeup,const char *server_name)
|
||||||
{
|
{
|
||||||
pstring outbuf;
|
pstring outbuf;
|
||||||
char *p;
|
fstring srv_name;
|
||||||
|
char *p;
|
||||||
|
|
||||||
DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
|
DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
|
||||||
workgroup_name, subrec->subnet_name ));
|
workgroup_name, subrec->subnet_name ));
|
||||||
|
|
||||||
memset(outbuf,'\0',sizeof(outbuf));
|
memset(outbuf,'\0',sizeof(outbuf));
|
||||||
p = outbuf;
|
p = outbuf;
|
||||||
SCVAL(p,0,ANN_Election); /* Election opcode. */
|
SCVAL(p,0,ANN_Election); /* Election opcode. */
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
|
SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
|
||||||
SIVAL(p,1,criterion);
|
SIVAL(p,1,criterion);
|
||||||
SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
|
SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
|
||||||
p += 13;
|
p += 13;
|
||||||
pstrcpy_base(p, server_name, outbuf);
|
fstrcpy(srv_name, server_name);
|
||||||
strupper_m(p);
|
strupper_m(srv_name);
|
||||||
p = skip_string(p,1);
|
pstrcpy_base(p, srv_name, outbuf);
|
||||||
|
p = skip_string(p,1);
|
||||||
|
|
||||||
send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
|
||||||
global_myname(), 0,
|
global_myname(), 0,
|
||||||
workgroup_name, 0x1e,
|
workgroup_name, 0x1e,
|
||||||
subrec->bcast_ip, subrec->myip, DGRAM_PORT);
|
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 nmb_name *answer_name,
|
||||||
struct in_addr answer_ip, struct res_rec *rrec)
|
struct in_addr answer_ip, struct res_rec *rrec)
|
||||||
{
|
{
|
||||||
DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
|
nstring aname;
|
||||||
IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) ));
|
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,
|
struct nmb_name *question_name,
|
||||||
int fail_code)
|
int fail_code)
|
||||||
{
|
{
|
||||||
char *workgroup_name = question_name->name;
|
nstring workgroup_name;
|
||||||
struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
|
struct work_record *work;
|
||||||
|
|
||||||
if(work == NULL)
|
pull_ascii_nstring(workgroup_name,question_name->name);
|
||||||
{
|
|
||||||
DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
|
|
||||||
workgroup_name, subrec->subnet_name ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
if (strequal(work->work_group, lp_workgroup())) {
|
||||||
{
|
|
||||||
/* 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
|
if (lp_local_master()) {
|
||||||
election is run in run_elections(). */
|
/* We have discovered that there is no local master
|
||||||
work->needelection = True;
|
browser, and we are configured to initiate
|
||||||
}
|
an election that we will participate in.
|
||||||
else
|
*/
|
||||||
{
|
DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
|
||||||
/* We need to force an election, because we are configured
|
work->work_group, subrec->subnet_name ));
|
||||||
not to become the local master, but we still need one,
|
|
||||||
having detected that one doesn't exist.
|
/* Setting this means we will participate when the
|
||||||
*/
|
election is run in run_elections(). */
|
||||||
send_election_dgram(subrec, work->work_group, 0, 0, "");
|
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)
|
void check_master_browser_exists(time_t t)
|
||||||
{
|
{
|
||||||
static time_t lastrun=0;
|
static time_t lastrun=0;
|
||||||
struct subnet_record *subrec;
|
struct subnet_record *subrec;
|
||||||
const char *workgroup_name = lp_workgroup();
|
const char *workgroup_name = lp_workgroup();
|
||||||
|
|
||||||
if (!lastrun)
|
if (!lastrun)
|
||||||
lastrun = t;
|
lastrun = t;
|
||||||
|
|
||||||
if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
|
if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastrun = t;
|
lastrun = t;
|
||||||
|
|
||||||
dump_workgroups(False);
|
dump_workgroups(False);
|
||||||
|
|
||||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||||
{
|
struct work_record *work;
|
||||||
struct work_record *work;
|
|
||||||
|
|
||||||
for (work = subrec->workgrouplist; work; work = work->next)
|
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||||
{
|
if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
|
||||||
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,
|
||||||
/* Do a name query for the local master browser on this net. */
|
check_for_master_browser_success,
|
||||||
query_name( subrec, work->work_group, 0x1d,
|
check_for_master_browser_fail,
|
||||||
check_for_master_browser_success,
|
NULL);
|
||||||
check_for_master_browser_fail,
|
}
|
||||||
NULL);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@@ -161,56 +161,52 @@ void check_master_browser_exists(time_t t)
|
|||||||
|
|
||||||
void run_elections(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 */
|
/* Send election packets once every 2 seconds - note */
|
||||||
if (lastime && (t - lastime < 2))
|
if (lastime && (t - lastime < 2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastime = t;
|
lastime = t;
|
||||||
|
|
||||||
START_PROFILE(run_elections);
|
START_PROFILE(run_elections);
|
||||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||||
{
|
struct work_record *work;
|
||||||
struct work_record *work;
|
|
||||||
|
|
||||||
for (work = subrec->workgrouplist; work; work = work->next)
|
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||||
{
|
if (work->RunningElection) {
|
||||||
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 can only run an election for a workgroup if we have
|
* we must listen to.
|
||||||
* registered the WORKGROUP<1e> name, as that's the name
|
*/
|
||||||
* we must listen to.
|
struct nmb_name nmbname;
|
||||||
*/
|
|
||||||
struct nmb_name nmbname;
|
|
||||||
|
|
||||||
make_nmb_name(&nmbname, work->work_group, 0x1e);
|
make_nmb_name(&nmbname, work->work_group, 0x1e);
|
||||||
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
||||||
DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
|
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 ));
|
yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
|
send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
|
||||||
t - StartupTime, global_myname());
|
t - StartupTime, global_myname());
|
||||||
|
|
||||||
if (work->ElectionCount++ >= 4)
|
if (work->ElectionCount++ >= 4) {
|
||||||
{
|
/* Won election (4 packets were sent out uncontested. */
|
||||||
/* Won election (4 packets were sent out uncontested. */
|
DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
|
||||||
DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
|
work->work_group, subrec->subnet_name ));
|
||||||
work->work_group, subrec->subnet_name ));
|
|
||||||
|
|
||||||
work->RunningElection = False;
|
work->RunningElection = False;
|
||||||
|
|
||||||
become_local_master_browser(subrec, work);
|
become_local_master_browser(subrec, work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_PROFILE(run_elections);
|
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,
|
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;
|
int mytimeup = time(NULL) - StartupTime;
|
||||||
uint32 mycriterion = work->ElectionCriterion;
|
uint32 mycriterion = work->ElectionCriterion;
|
||||||
|
|
||||||
/* If local master is false then never win
|
/* If local master is false then never win in election broadcasts. */
|
||||||
in election broadcasts. */
|
if(!lp_local_master()) {
|
||||||
if(!lp_local_master())
|
DEBUG(3,("win_election: Losing election as local master == False\n"));
|
||||||
{
|
return False;
|
||||||
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",
|
DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
|
||||||
version, ELECTION_VERSION,
|
version, ELECTION_VERSION,
|
||||||
criterion, mycriterion,
|
criterion, mycriterion,
|
||||||
timeup, mytimeup,
|
timeup, mytimeup,
|
||||||
server_name, global_myname()));
|
server_name, global_myname()));
|
||||||
|
|
||||||
if (version > ELECTION_VERSION)
|
if (version > ELECTION_VERSION)
|
||||||
return(False);
|
return(False);
|
||||||
if (version < ELECTION_VERSION)
|
if (version < ELECTION_VERSION)
|
||||||
return(True);
|
return(True);
|
||||||
|
|
||||||
if (criterion > mycriterion)
|
if (criterion > mycriterion)
|
||||||
return(False);
|
return(False);
|
||||||
if (criterion < mycriterion)
|
if (criterion < mycriterion)
|
||||||
return(True);
|
return(True);
|
||||||
|
|
||||||
if (timeup > mytimeup)
|
if (timeup > mytimeup)
|
||||||
return(False);
|
return(False);
|
||||||
if (timeup < mytimeup)
|
if (timeup < mytimeup)
|
||||||
return(True);
|
return(True);
|
||||||
|
|
||||||
if (strcasecmp(global_myname(), server_name) > 0)
|
if (strcasecmp(global_myname(), server_name) > 0)
|
||||||
return(False);
|
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)
|
void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
|
||||||
{
|
{
|
||||||
struct dgram_packet *dgram = &p->packet.dgram;
|
struct dgram_packet *dgram = &p->packet.dgram;
|
||||||
int version = CVAL(buf,0);
|
int version = CVAL(buf,0);
|
||||||
uint32 criterion = IVAL(buf,1);
|
uint32 criterion = IVAL(buf,1);
|
||||||
int timeup = IVAL(buf,5)/1000;
|
int timeup = IVAL(buf,5)/1000;
|
||||||
char *server_name = buf+13;
|
nstring server_name;
|
||||||
struct work_record *work;
|
struct work_record *work;
|
||||||
char *workgroup_name = dgram->dest_name.name;
|
nstring workgroup_name;
|
||||||
|
|
||||||
START_PROFILE(election);
|
pull_ascii_nstring(server_name, buf+13);
|
||||||
server_name[15] = 0;
|
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",
|
START_PROFILE(election);
|
||||||
server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
|
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(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
|
||||||
{
|
|
||||||
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()))
|
if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
|
||||||
{
|
DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
|
||||||
DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
|
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 ));
|
is not my workgroup.\n", work->work_group, subrec->subnet_name ));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (win_election(work, version,criterion,timeup,server_name))
|
if (win_election(work, version,criterion,timeup,server_name)) {
|
||||||
{
|
/* We take precedence over the requesting server. */
|
||||||
/* We take precedence over the requesting server. */
|
if (!work->RunningElection) {
|
||||||
if (!work->RunningElection)
|
/* We weren't running an election - start running one. */
|
||||||
{
|
|
||||||
/* We weren't running an election - start running one. */
|
|
||||||
|
|
||||||
work->needelection = True;
|
work->needelection = True;
|
||||||
work->ElectionCount=0;
|
work->ElectionCount=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that if we were running an election for this workgroup on this
|
/* Note that if we were running an election for this workgroup on this
|
||||||
subnet already, we just ignore the server we take precedence over. */
|
subnet already, we just ignore the server we take precedence over. */
|
||||||
}
|
} else {
|
||||||
else
|
/* We lost. Stop participating. */
|
||||||
{
|
work->needelection = False;
|
||||||
/* We lost. Stop participating. */
|
|
||||||
work->needelection = False;
|
|
||||||
|
|
||||||
if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
|
if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) {
|
||||||
{
|
work->RunningElection = False;
|
||||||
work->RunningElection = False;
|
DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
|
||||||
DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
|
work->work_group, subrec->subnet_name ));
|
||||||
work->work_group, subrec->subnet_name ));
|
if (AM_LOCAL_MASTER_BROWSER(work))
|
||||||
if (AM_LOCAL_MASTER_BROWSER(work))
|
unbecome_local_master_browser(subrec, work, False);
|
||||||
unbecome_local_master_browser(subrec, work, False);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
done:
|
done:
|
||||||
END_PROFILE(election);
|
|
||||||
|
END_PROFILE(election);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -335,57 +326,53 @@ done:
|
|||||||
|
|
||||||
BOOL check_elections(void)
|
BOOL check_elections(void)
|
||||||
{
|
{
|
||||||
struct subnet_record *subrec;
|
struct subnet_record *subrec;
|
||||||
BOOL run_any_election = False;
|
BOOL run_any_election = False;
|
||||||
|
|
||||||
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
||||||
{
|
struct work_record *work;
|
||||||
struct work_record *work;
|
for (work = subrec->workgrouplist; work; work = work->next) {
|
||||||
for (work = subrec->workgrouplist; work; work = work->next)
|
run_any_election |= work->RunningElection;
|
||||||
{
|
|
||||||
run_any_election |= work->RunningElection;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start an election if we have any chance of winning.
|
* Start an election if we have any chance of winning.
|
||||||
* Note this is a change to the previous code, that would
|
* Note this is a change to the previous code, that would
|
||||||
* only run an election if nmbd was in the potential browser
|
* only run an election if nmbd was in the potential browser
|
||||||
* state. We need to run elections in any state if we're told
|
* state. We need to run elections in any state if we're told
|
||||||
* to. JRA.
|
* to. JRA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (work->needelection && !work->RunningElection && lp_local_master())
|
if (work->needelection && !work->RunningElection && lp_local_master()) {
|
||||||
{
|
/*
|
||||||
/*
|
* We can only run an election for a workgroup if we have
|
||||||
* We can only run an election for a workgroup if we have
|
* registered the WORKGROUP<1e> name, as that's the name
|
||||||
* registered the WORKGROUP<1e> name, as that's the name
|
* we must listen to.
|
||||||
* we must listen to.
|
*/
|
||||||
*/
|
struct nmb_name nmbname;
|
||||||
struct nmb_name nmbname;
|
|
||||||
|
|
||||||
make_nmb_name(&nmbname, work->work_group, 0x1e);
|
make_nmb_name(&nmbname, work->work_group, 0x1e);
|
||||||
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
|
||||||
DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
|
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 ));
|
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",
|
DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
|
||||||
work->work_group, subrec->subnet_name ));
|
work->work_group, subrec->subnet_name ));
|
||||||
|
|
||||||
work->ElectionCount = 0;
|
work->ElectionCount = 0;
|
||||||
work->RunningElection = True;
|
work->RunningElection = True;
|
||||||
work->needelection = False;
|
work->needelection = False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return run_any_election;
|
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)
|
void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct subnet_record *subrec;
|
struct subnet_record *subrec;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -201,7 +201,7 @@ static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name
|
|||||||
Try and query for a 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_success_function success_fn,
|
||||||
query_name_fail_function fail_fn,
|
query_name_fail_function fail_fn,
|
||||||
struct userdata_struct *userdata)
|
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,
|
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_success_function success_fn,
|
||||||
query_name_fail_function fail_fn,
|
query_name_fail_function fail_fn,
|
||||||
struct userdata_struct *userdata)
|
struct userdata_struct *userdata)
|
||||||
|
Reference in New Issue
Block a user