1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

backout all the changes to nmbd.

The 1.9.16 tree is now back to 1.9.16p2 as far as nmbd is concerned
apart from a small change that fixes the announce type in two places.
(This used to be commit 45e66a69d3)
This commit is contained in:
Andrew Tridgell 1996-10-02 15:41:30 +00:00
parent 5a2f52b79e
commit afd08462ad
29 changed files with 2008 additions and 2440 deletions

View File

@ -3787,12 +3787,10 @@ static BOOL list_servers(char *wk_grp)
for (i=0;i<count;i++) { for (i=0;i<count;i++) {
char *sname = p2; char *sname = p2;
uint32 stype = IVAL(p2,18);
int comment_offset = IVAL(p2,22) & 0xFFFF; int comment_offset = IVAL(p2,22) & 0xFFFF;
printf("\t%-16.16s %s (%8x)\n", printf("\t%-16.16s %s\n",
sname, sname,
comment_offset?rdata+comment_offset-converter:"", comment_offset?rdata+comment_offset-converter:"");
stype);
ok=True; ok=True;
p2 += 26; p2 += 26;
@ -3828,12 +3826,10 @@ static BOOL list_servers(char *wk_grp)
for (i=0;i<count;i++) { for (i=0;i<count;i++) {
char *sname = p2; char *sname = p2;
uint32 stype = IVAL(p2,18);
int comment_offset = IVAL(p2,22) & 0xFFFF; int comment_offset = IVAL(p2,22) & 0xFFFF;
printf("\t%-16.16s %s (%8x)\n", printf("\t%-16.16s %s\n",
sname, sname,
comment_offset?rdata+comment_offset-converter:"", comment_offset?rdata+comment_offset-converter:"");
stype);
ok=True; ok=True;
p2 += 26; p2 += 26;

View File

@ -54,19 +54,6 @@
#define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */ #define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */
#define NB_FLGMSK 0x60 #define NB_FLGMSK 0x60
#define WG_BROWSE_SIGNATURE 0x017e
#define WG_BROWSE_VERSION 0xff08
#define HOST_BROWSE_SIGNATURE 0xaa55
#define HOST_BROWSE_VERSION 0x010f
#define WG_MAJOR_VERSION 0x03
#define WG_MINOR_VERSION 0x0a
#define HOST_MAJOR_VERSION 0x04 /* nt/as host version */
#define HOST_MINOR_VERSION 0x01 /* one better than current nt/as version */
#define REFRESH_TIME (15*60) #define REFRESH_TIME (15*60)
#define NAME_POLL_REFRESH_TIME (5*60) #define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15 #define NAME_POLL_INTERVAL 15
@ -86,7 +73,7 @@
/* server type identifiers */ /* server type identifiers */
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER) #define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER) #define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
#define AM_DMBRSE(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER) #define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL)
/* microsoft browser NetBIOS name */ /* microsoft browser NetBIOS name */
#define MSBROWSE "\001\002__MSBROWSE__\002" #define MSBROWSE "\001\002__MSBROWSE__\002"
@ -112,19 +99,19 @@ enum master_state
enum state_type enum state_type
{ {
NAME_STATUS_DOM_SRV_CHK, NAME_STATUS_DOM_SRV_CHK,
NAME_STATUS_SRV_CHK, NAME_STATUS_SRV_CHK,
NAME_REGISTER_CHALLENGE, NAME_REGISTER_CHALLENGE,
NAME_REGISTER, NAME_REGISTER,
NAME_RELEASE, NAME_RELEASE,
NAME_QUERY_CONFIRM, NAME_QUERY_CONFIRM,
NAME_QUERY_ANNOUNCE_HOST, NAME_QUERY_ANNOUNCE_HOST,
NAME_QUERY_SYNC_LOCAL, NAME_QUERY_SYNC_LOCAL,
NAME_QUERY_SYNC_REMOTE, NAME_QUERY_SYNC_REMOTE,
NAME_QUERY_DOM_SRV_CHK, NAME_QUERY_DOM_SRV_CHK,
NAME_QUERY_SRV_CHK, NAME_QUERY_SRV_CHK,
NAME_QUERY_FIND_MST, NAME_QUERY_FIND_MST,
NAME_QUERY_MST_CHK NAME_QUERY_MST_CHK
}; };
/* a netbios name structure */ /* a netbios name structure */
@ -134,14 +121,6 @@ struct nmb_name {
int name_type; int name_type;
}; };
/* A server name and comment. */
struct server_identity
{
char *name;
char *comment;
struct server_identity *next;
};
/* a netbios flags + ip address structure */ /* a netbios flags + ip address structure */
/* this is used for multi-homed systems and for internet group names */ /* this is used for multi-homed systems and for internet group names */
struct nmb_ip struct nmb_ip
@ -169,16 +148,16 @@ struct name_record
/* browse and backup server cache for synchronising browse list */ /* browse and backup server cache for synchronising browse list */
struct browse_cache_record struct browse_cache_record
{ {
struct browse_cache_record *next; struct browse_cache_record *next;
struct browse_cache_record *prev; struct browse_cache_record *prev;
char name[17]; pstring name;
int type; int type;
char group[17]; pstring group;
struct in_addr ip; struct in_addr ip;
time_t sync_time; time_t sync_time;
BOOL synced; BOOL synced;
BOOL local; BOOL local;
}; };
/* 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 */
@ -204,7 +183,7 @@ struct work_record
enum master_state state; enum master_state state;
/* work group info */ /* work group info */
char work_group[17]; fstring work_group;
int token; /* used when communicating with backup browsers */ int token; /* used when communicating with backup browsers */
int ServerType; int ServerType;
@ -235,18 +214,17 @@ struct response_record
int fd; int fd;
int quest_type; int quest_type;
struct nmb_name name; struct nmb_name name;
struct nmb_ip reply; int nb_flags;
time_t ttl; time_t ttl;
enum name_source source;
int token; /* unique workgroup token id */
int server_type; int server_type;
char my_name[17]; fstring my_name;
char my_comment[50]; fstring my_comment;
BOOL bcast; BOOL bcast;
BOOL recurse; BOOL recurse;
struct in_addr send_ip; struct in_addr send_ip;
struct in_addr reply_to_ip;
int num_msgs; int num_msgs;

View File

@ -124,7 +124,6 @@ char *lp_smbrun(void);
char *lp_configfile(void); char *lp_configfile(void);
char *lp_smb_passwd_file(void); char *lp_smb_passwd_file(void);
char *lp_serverstring(void); char *lp_serverstring(void);
char *lp_server_comment(void);
char *lp_printcapname(void); char *lp_printcapname(void);
char *lp_lockdir(void); char *lp_lockdir(void);
char *lp_rootdir(void); char *lp_rootdir(void);
@ -147,7 +146,6 @@ char *lp_interfaces(void);
char *lp_socket_address(void); char *lp_socket_address(void);
BOOL lp_wins_support(void); BOOL lp_wins_support(void);
BOOL lp_wins_proxy(void); BOOL lp_wins_proxy(void);
BOOL lp_local_master(void);
BOOL lp_domain_master(void); BOOL lp_domain_master(void);
BOOL lp_domain_logons(void); BOOL lp_domain_logons(void);
BOOL lp_preferred_master(void); BOOL lp_preferred_master(void);
@ -294,22 +292,20 @@ int reply_sendend(char *inbuf,char *outbuf);
/*The following definitions come from nameannounce.c */ /*The following definitions come from nameannounce.c */
void announce_request(struct work_record *work, struct in_addr ip); void announce_request(struct work_record *work, struct in_addr ip);
void do_announce_request(char *info, char *from_name, char *to_name, void do_announce_request(char *info, char *to_name, int announce_type,
int announce_type, int from, int to, struct in_addr dest_ip); int from,
int to, struct in_addr dest_ip);
void sync_server(enum state_type state, char *serv_name, char *work_name, void sync_server(enum state_type state, char *serv_name, char *work_name,
int name_type, int name_type,
struct in_addr ip); struct in_addr ip);
void do_announce_host(int command, void do_announce_host(int command,
char *from_name, int from_type, struct in_addr from_ip, char *from_name, int from_type, struct in_addr from_ip,
char *to_name , int to_type , struct in_addr to_ip, char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval, time_t announce_interval,
char *server_name, int server_type, char *server_name, int server_type, char *server_comment);
char major_version, char minor_version,
uint16 browse_version, uint16 browse_sig,
char *server_comment);
void remove_my_servers(void); void remove_my_servers(void);
void announce_server(struct subnet_record *d, struct work_record *work, void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type); char *name, char *comment, time_t ttl, int server_type);
void announce_host(void); void announce_host(void);
void announce_master(void); void announce_master(void);
void announce_remote(void); void announce_remote(void);
@ -318,7 +314,7 @@ void announce_remote(void);
void expire_browse_cache(time_t t); void expire_browse_cache(time_t t);
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
time_t ttl, struct in_addr ip, BOOL local); time_t ttl, struct in_addr ip, BOOL local);
void do_browser_lists(void); void do_browser_lists(void);
/*The following definitions come from nameconf.c */ /*The following definitions come from nameconf.c */
@ -326,10 +322,8 @@ void do_browser_lists(void);
int get_num_workgroups(void); int get_num_workgroups(void);
int conf_workgroup_name_to_token(char *workgroup_name,char *default_name); int conf_workgroup_name_to_token(char *workgroup_name,char *default_name);
char *conf_workgroup_name(int token); char *conf_workgroup_name(int token);
int conf_should_preferred_master(int token);
int conf_should_workgroup_member(int token); int conf_should_workgroup_member(int token);
int conf_should_local_master(int token); int conf_should_local_master(int token);
int conf_should_domain_logon(int token);
int conf_should_domain_master(int token); int conf_should_domain_master(int token);
char *conf_browsing_alias(int token); char *conf_browsing_alias(int token);
char *conf_browsing_alias_comment(int token); char *conf_browsing_alias_comment(int token);
@ -344,24 +338,24 @@ BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2);
BOOL ms_browser_name(char *name, int type); BOOL ms_browser_name(char *name, int type);
void remove_name(struct subnet_record *d, struct name_record *n); void remove_name(struct subnet_record *d, struct name_record *n);
struct name_record *find_name(struct name_record *n, struct name_record *find_name(struct name_record *n,
struct nmb_name *name, struct nmb_name *name,
int search); int search);
struct name_record *find_name_search(struct subnet_record **d, struct name_record *find_name_search(struct subnet_record **d,
struct nmb_name *name, struct nmb_name *name,
int search, struct in_addr ip); int search, struct in_addr ip);
void dump_names(void); void dump_names(void);
void load_netbios_names(void); void load_netbios_names(void);
void remove_netbios_name(struct subnet_record *d, void remove_netbios_name(struct subnet_record *d,
char *name,int type, enum name_source source, char *name,int type, enum name_source source,
struct in_addr ip); struct in_addr ip);
struct name_record *add_netbios_entry(struct subnet_record *d, struct name_record *add_netbios_entry(struct subnet_record *d,
char *name, int type, int nb_flags, char *name, int type, int nb_flags,
int ttl, enum name_source source, struct in_addr ip, int ttl, enum name_source source, struct in_addr ip,
BOOL new_only,BOOL wins); BOOL new_only,BOOL wins);
void check_expire_names(time_t t); void expire_names(time_t t);
struct name_record *search_for_name(struct subnet_record **d, struct name_record *search_for_name(struct subnet_record **d,
struct nmb_name *question, struct nmb_name *question,
struct in_addr ip, int Time, int search); struct in_addr ip, int Time, int search);
/*The following definitions come from namedbresp.c */ /*The following definitions come from namedbresp.c */
@ -370,9 +364,8 @@ void add_response_record(struct subnet_record *d,
void remove_response_record(struct subnet_record *d, void remove_response_record(struct subnet_record *d,
struct response_record *n); struct response_record *n);
struct response_record *make_response_queue_record(enum state_type state, struct response_record *make_response_queue_record(enum state_type state,
int id,uint16 fd, int quest_type, int id,uint16 fd,
int token, char *name,int type, int quest_type, char *name,int type, int nb_flags, time_t ttl,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment, int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse, BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip); struct in_addr send_ip, struct in_addr reply_to_ip);
@ -382,13 +375,13 @@ struct response_record *find_response_record(struct subnet_record **d,
/*The following definitions come from namedbserver.c */ /*The following definitions come from namedbserver.c */
void remove_old_servers(struct work_record *work, time_t t, void remove_old_servers(struct work_record *work, time_t t,
BOOL remove_all); BOOL remove_all);
struct server_record *find_server(struct work_record *work, char *name); struct server_record *find_server(struct work_record *work, char *name);
struct server_record *add_server_entry(struct subnet_record *d, struct server_record *add_server_entry(struct subnet_record *d,
struct work_record *work, struct work_record *work,
char *name,int servertype, char *name,int servertype,
int ttl,char *comment, int ttl,char *comment,
BOOL replace); BOOL replace);
void expire_servers(time_t t); void expire_servers(time_t t);
/*The following definitions come from namedbsubnet.c */ /*The following definitions come from namedbsubnet.c */
@ -396,21 +389,19 @@ void expire_servers(time_t t);
struct subnet_record *find_subnet(struct in_addr bcast_ip); struct subnet_record *find_subnet(struct in_addr bcast_ip);
struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast); struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast);
void add_subnet_interfaces(void); void add_subnet_interfaces(void);
void add_workgroup_to_subnet(char *group, struct in_addr bcast_ip, void add_my_subnets(char *group);
struct in_addr mask_ip);
void add_workgroups_to_subnets();
struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
struct in_addr mask_ip, struct in_addr mask_ip,
char *name, BOOL add, BOOL lmhosts); char *name, BOOL add, BOOL lmhosts);
void write_browse_list(void); void write_browse_list(void);
/*The following definitions come from namedbwork.c */ /*The following definitions come from namedbwork.c */
struct work_record *remove_workgroup(struct subnet_record *d, struct work_record *remove_workgroup(struct subnet_record *d,
struct work_record *work, struct work_record *work,
BOOL remove_all_servers); BOOL remove_all_servers);
struct work_record *find_workgroupstruct(struct subnet_record *d, struct work_record *find_workgroupstruct(struct subnet_record *d,
fstring name, BOOL add); fstring name, BOOL add);
void dump_workgroups(void); void dump_workgroups(void);
/*The following definitions come from nameelect.c */ /*The following definitions come from nameelect.c */
@ -418,14 +409,13 @@ void dump_workgroups(void);
void check_master_browser(void); void check_master_browser(void);
void browser_gone(char *work_name, struct in_addr ip); void browser_gone(char *work_name, struct in_addr ip);
void send_election(struct subnet_record *d, char *group,uint32 criterion, void send_election(struct subnet_record *d, char *group,uint32 criterion,
int timeup,char *name); int timeup,char *name);
void name_unregister_work(struct subnet_record *d, char *name, int name_type); void name_unregister_work(struct subnet_record *d, char *name, int name_type);
void name_register_work(struct subnet_record *d, int token, void name_register_work(struct subnet_record *d, char *name, int name_type,
char *name, int name_type, enum name_source source, int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast);
struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast);
void become_master(struct subnet_record *d, struct work_record *work); void become_master(struct subnet_record *d, struct work_record *work);
void become_nonmaster(struct subnet_record *d, struct work_record *work, void become_nonmaster(struct subnet_record *d, struct work_record *work,
int remove_type); int remove_type);
void run_elections(void); void run_elections(void);
void process_election(struct packet_struct *p,char *buf); void process_election(struct packet_struct *p,char *buf);
BOOL check_elections(void); BOOL check_elections(void);
@ -437,20 +427,20 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len);
/*The following definitions come from namepacket.c */ /*The following definitions come from namepacket.c */
void debug_browse_data(char *outbuf, int len); void debug_browse_data(char *outbuf, int len);
BOOL initiate_netbios_packet(uint16 id, void initiate_netbios_packet(uint16 *id,
int fd,int quest_type,char *name,int name_type, int fd,int quest_type,char *name,int name_type,
int nb_flags,BOOL bcast,BOOL recurse, int nb_flags,BOOL bcast,BOOL recurse,
struct in_addr to_ip); struct in_addr to_ip);
void reply_netbios_packet(struct packet_struct *p1,int trn_id, void reply_netbios_packet(struct packet_struct *p1,int trn_id,
int rcode, int rcv_code, int opcode, BOOL recurse, int rcode, int rcv_code, int opcode, BOOL recurse,
struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
char *data,int len); char *data,int len);
void queue_packet(struct packet_struct *packet); void queue_packet(struct packet_struct *packet);
void run_packet_queue(); void run_packet_queue();
void listen_for_packets(BOOL run_election); void listen_for_packets(BOOL run_election);
BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
char *dstname,int src_type,int dest_type, char *dstname,int src_type,int dest_type,
struct in_addr dest_ip,struct in_addr src_ip); struct in_addr dest_ip,struct in_addr src_ip);
/*The following definitions come from namequery.c */ /*The following definitions come from namequery.c */
@ -463,30 +453,27 @@ BOOL name_query(int fd,char *name,int name_type,
/*The following definitions come from nameresp.c */ /*The following definitions come from nameresp.c */
void update_name_trn_id(void);
void expire_netbios_response_entries(); void expire_netbios_response_entries();
void queue_netbios_pkt_wins(struct subnet_record *d, struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum state_type state, int fd,int quest_type,enum state_type state,
int token, char *name,int name_type, char *name,int name_type,int nb_flags, time_t ttl,
enum name_source source, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment,
int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse,
BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip);
struct in_addr send_ip, struct in_addr reply_to_ip); struct response_record *queue_netbios_packet(struct subnet_record *d,
void queue_netbios_packet(struct subnet_record *d, int fd,int quest_type,enum state_type state,char *name,
int fd,int quest_type,enum state_type state, int name_type,int nb_flags, time_t ttl,
int token, char *name, int name_type, int server_type, char *my_name, char *my_comment,
enum name_source source, int nb_flags, time_t ttl, BOOL bcast,BOOL recurse,
int server_type, char *my_name, char *my_comment, struct in_addr send_ip, struct in_addr reply_to_ip);
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip);
/*The following definitions come from nameserv.c */ /*The following definitions come from nameserv.c */
void remove_name_entry(struct subnet_record *d, int token, char *name,int type); void remove_name_entry(struct subnet_record *d, char *name,int type);
void add_my_name_entry(struct subnet_record *d, int token, void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags);
char *name,int type,int nb_flags);
void add_my_names(void); void add_my_names(void);
void remove_my_names(); void remove_my_names();
void refresh_my_names(time_t t);
void query_refresh_names(void); void query_refresh_names(void);
/*The following definitions come from nameservreply.c */ /*The following definitions come from nameservreply.c */
@ -508,18 +495,13 @@ void reply_name_query(struct packet_struct *p);
/*The following definitions come from nameservresp.c */ /*The following definitions come from nameservresp.c */
void debug_state_type(int state); void debug_state_type(int state);
void response_process(struct in_addr ip, struct subnet_record *d,
struct response_record *n,
int rcode, char *nmb_data, struct nmb_name *q_name,
time_t ttl, BOOL bcast, struct nmb_name *ans_name);
void response_netbios_packet(struct packet_struct *p); void response_netbios_packet(struct packet_struct *p);
/*The following definitions come from namework.c */ /*The following definitions come from namework.c */
void reset_server(struct work_record *work, char *name, int state, struct in_addr ip); void reset_server(char *name, int state, struct in_addr ip);
void tell_become_backup(void); void tell_become_backup(void);
BOOL same_context(struct dgram_packet *dgram); BOOL same_context(struct dgram_packet *dgram);
BOOL listening_name(struct work_record *work, struct nmb_name *n);
void process_browse_packet(struct packet_struct *p,char *buf,int len); void process_browse_packet(struct packet_struct *p,char *buf,int len);
/*The following definitions come from nmbd.c */ /*The following definitions come from nmbd.c */
@ -545,7 +527,7 @@ int main(int argc,char *argv[]);
char *getsmbpass(char *pass); char *getsmbpass(char *pass);
void sync_browse_lists(struct subnet_record *d, struct work_record *work, void sync_browse_lists(struct subnet_record *d, struct work_record *work,
char *name, int nm_type, struct in_addr ip, BOOL local); char *name, int nm_type, struct in_addr ip, BOOL local);
/*The following definitions come from params.c */ /*The following definitions come from params.c */
@ -769,7 +751,6 @@ unsigned int Ucrit_checkPid(int pid);
int sys_select(fd_set *fds,struct timeval *tval); int sys_select(fd_set *fds,struct timeval *tval);
int sys_select(fd_set *fds,struct timeval *tval); int sys_select(fd_set *fds,struct timeval *tval);
int sys_unlink(char *fname); int sys_unlink(char *fname);
unsigned int sys_random(int max_range);
int sys_open(char *fname,int flags,int mode); int sys_open(char *fname,int flags,int mode);
DIR *sys_opendir(char *dname); DIR *sys_opendir(char *dname);
int sys_stat(char *fname,struct stat *sbuf); int sys_stat(char *fname,struct stat *sbuf);

View File

@ -380,10 +380,10 @@ typedef struct
/* used for server information: client, nameserv and ipc */ /* used for server information: client, nameserv and ipc */
struct server_info_struct struct server_info_struct
{ {
char name[17]; fstring name;
uint32 type; uint32 type;
char comment[50]; fstring comment;
char domain[17]; /* used ONLY in ipc.c NOT namework.c */ fstring domain; /* used ONLY in ipc.c NOT namework.c */
BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
}; };

View File

@ -115,15 +115,6 @@ int sys_unlink(char *fname)
} }
/*******************************************************************
random number generator
********************************************************************/
unsigned int sys_random(int max_range)
{
return(((unsigned int)random()) % max_range);
}
/******************************************************************* /*******************************************************************
a simple open() wrapper a simple open() wrapper
********************************************************************/ ********************************************************************/

View File

@ -65,7 +65,7 @@ static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
for (j = 0; j < 16; j++) for (j = 0; j < 16; j++)
{ {
if (i+j >= res->rdlength) break; if (i+j >= res->rdlength) break;
DEBUG(4, ("%02x", (unsigned char)res->rdata[i+j])); DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j]));
} }
DEBUG(4, ("\n")); DEBUG(4, ("\n"));

View File

@ -23,18 +23,19 @@
14 jan 96: lkcl@pires.co.uk 14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
#define TEST_CODE
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
extern BOOL CanRecurse; extern BOOL CanRecurse;
extern struct in_addr ipzero; extern struct in_addr ipzero;
extern pstring myname;
extern int ClientDGRAM; extern int ClientDGRAM;
extern int ClientNMB; extern int ClientNMB;
@ -42,17 +43,14 @@ extern int ClientNMB;
extern struct subnet_record *subnetlist; extern struct subnet_record *subnetlist;
extern int updatecount; extern int updatecount;
extern int workgroup_count;
extern struct in_addr ipgrp; extern struct in_addr ipgrp;
extern pstring myname;
/**************************************************************************** /****************************************************************************
Send a announce request to the local net. send a announce request to the local net
This is called by become_master(). This purpose of this action is to
encourage servers to send us host announcements right away.
**************************************************************************/ **************************************************************************/
void announce_request(struct work_record *work, struct in_addr ip) void announce_request(struct work_record *work, struct in_addr ip)
{ {
@ -64,7 +62,7 @@ void announce_request(struct work_record *work, struct in_addr ip)
work->needannounce = True; work->needannounce = True;
DEBUG(2,("sending announce request to %s for workgroup %s\n", DEBUG(2,("sending announce request to %s for workgroup %s\n",
inet_ntoa(ip),work->work_group)); inet_ntoa(ip),work->work_group));
bzero(outbuf,sizeof(outbuf)); bzero(outbuf,sizeof(outbuf));
p = outbuf; p = outbuf;
@ -73,7 +71,8 @@ void announce_request(struct work_record *work, struct in_addr ip)
CVAL(p,0) = work->token; /* (local) unique workgroup token id */ CVAL(p,0) = work->token; /* (local) unique workgroup token id */
p++; p++;
StrnCpy(p,conf_browsing_alias(work->token),16); StrnCpy(p,myname,16);
strupper(p);
p = skip_string(p,1); p = skip_string(p,1);
/* XXXX note: if we sent the announcement request to 0x1d instead /* XXXX note: if we sent the announcement request to 0x1d instead
@ -81,17 +80,16 @@ void announce_request(struct work_record *work, struct in_addr ip)
us instead of the members of the workgroup. wha-hey! */ us instead of the members of the workgroup. wha-hey! */
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
conf_browsing_alias(work->token),work->work_group, myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
0x20, 0x1e,
ip,*iface_ip(ip));
} }
/**************************************************************************** /****************************************************************************
request an announcement request an announcement
**************************************************************************/ **************************************************************************/
void do_announce_request(char *info, char *from_name, char *to_name, void do_announce_request(char *info, char *to_name, int announce_type,
int announce_type, int from, int to, struct in_addr dest_ip) int from,
int to, struct in_addr dest_ip)
{ {
pstring outbuf; pstring outbuf;
char *p; char *p;
@ -102,15 +100,14 @@ void do_announce_request(char *info, char *from_name, char *to_name,
p++; p++;
DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n", DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n",
announce_type, info, inet_ntoa(dest_ip),to_name,to)); announce_type, info, inet_ntoa(dest_ip),to_name,to));
StrnCpy(p,info,16); StrnCpy(p,info,16);
strupper(p); strupper(p);
p = skip_string(p,1); p = skip_string(p,1);
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
from_name,to_name,from,to, myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
dest_ip,*iface_ip(dest_ip));
} }
@ -119,23 +116,19 @@ void do_announce_request(char *info, char *from_name, char *to_name,
control ends up back here via response_name_query. control ends up back here via response_name_query.
**************************************************************************/ **************************************************************************/
void sync_server(enum state_type state, char *serv_name, char *work_name, void sync_server(enum state_type state, char *serv_name, char *work_name,
int name_type, int name_type,
struct in_addr ip) struct in_addr ip)
{ {
int token = conf_workgroup_name_to_token(work_name, myname);
/* with a domain master we can get the whole list (not local only list) */ /* with a domain master we can get the whole list (not local only list) */
BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK); BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK);
add_browser_entry(serv_name, name_type, work_name, 0, ip, local_only); add_browser_entry(serv_name, name_type, work_name, 0, ip, local_only);
if (state == NAME_STATUS_DOM_SRV_CHK && conf_should_local_master(token)) if (state == NAME_STATUS_DOM_SRV_CHK)
{ {
/* announce ourselves as a master browser to serv_name */ /* announce ourselves as a master browser to serv_name */
do_announce_request(conf_browsing_alias(token), /* info */ do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
conf_browsing_alias(token), /* from */ 0x20, 0, ip);
serv_name, /* to */
ANN_MasterAnnouncement, 0x20, 0,ip);
} }
} }
@ -144,50 +137,46 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
send a host announcement packet send a host announcement packet
**************************************************************************/ **************************************************************************/
void do_announce_host(int command, void do_announce_host(int command,
char *from_name, int from_type, struct in_addr from_ip, char *from_name, int from_type, struct in_addr from_ip,
char *to_name , int to_type , struct in_addr to_ip, char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval, time_t announce_interval,
char *server_name, int server_type, char *server_name, int server_type, char *server_comment)
char major_version, char minor_version,
uint16 browse_version, uint16 browse_sig,
char *server_comment)
{ {
pstring outbuf; pstring outbuf;
char *p; char *p;
bzero(outbuf,sizeof(outbuf)); bzero(outbuf,sizeof(outbuf));
p = outbuf+1; p = outbuf+1;
/* command type */ /* command type */
CVAL(outbuf,0) = command; CVAL(outbuf,0) = command;
/* announcement parameters */ /* announcement parameters */
CVAL(p,0) = updatecount; CVAL(p,0) = updatecount;
SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
StrnCpy(p+5,server_name,16); StrnCpy(p+5,server_name,16);
strupper(p+5); strupper(p+5);
CVAL(p,21) = major_version; CVAL(p,21) = 0x02; /* major version */
CVAL(p,22) = minor_version; CVAL(p,22) = 0x02; /* minor version */
SIVAL(p,23,server_type); SIVAL(p,23,server_type);
SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */
SSVAL(p,29,0xaa55); /* browse signature */
SSVAL(p,27,browse_version); strcpy(p+31,server_comment);
SSVAL(p,29,browse_sig); p += 31;
p = skip_string(p,1);
strcpy(p+31,server_comment);
p += 31;
p = skip_string(p,1);
debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
/* send the announcement */ /* send the announcement */
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf), PTR_DIFF(p,outbuf),
from_name, to_name, from_name, to_name,
from_type, to_type, from_type, to_type,
to_ip, from_ip); to_ip, from_ip);
} }
@ -196,23 +185,20 @@ void do_announce_host(int command,
****************************************************************************/ ****************************************************************************/
void remove_my_servers(void) void remove_my_servers(void)
{ {
struct subnet_record *d; struct subnet_record *d;
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
struct server_record *s; struct server_record *s;
for (s = work->serverlist; s; s = s->next) for (s = work->serverlist; s; s = s->next)
{ {
if (!strequal(conf_browsing_alias(work->token),s->serv.name)) if (!strequal(myname,s->serv.name)) continue;
{ announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
continue; }
} }
announce_server(d, work, s->serv.name, s->serv.comment, 0, 0); }
}
}
}
} }
@ -220,14 +206,13 @@ void remove_my_servers(void)
announce a server entry announce a server entry
****************************************************************************/ ****************************************************************************/
void announce_server(struct subnet_record *d, struct work_record *work, void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type) char *name, char *comment, time_t ttl, int server_type)
{ {
/* domain type cannot have anything in it that might confuse /* domain type cannot have anything in it that might confuse
a client into thinking that the domain is in fact a server. a client into thinking that the domain is in fact a server.
(SV_TYPE_SERVER_UNIX, for example) (SV_TYPE_SERVER_UNIX, for example)
*/ */
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp); BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
if (wins_iface && server_type != 0) if (wins_iface && server_type != 0)
@ -235,13 +220,14 @@ void announce_server(struct subnet_record *d, struct work_record *work,
/* wins pseudo-ip interface */ /* wins pseudo-ip interface */
if (!AM_MASTER(work)) if (!AM_MASTER(work))
{ {
/* non-master announce by unicast to the domain master */ /* non-master announce by unicast to the domain
master */
if (!lp_wins_support() && *lp_wins_server()) if (!lp_wins_support() && *lp_wins_server())
{ {
/* look up the domain master with the WINS server */ /* look up the domain master with the WINS server */
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
NAME_QUERY_ANNOUNCE_HOST, NAME_QUERY_ANNOUNCE_HOST,
work->token,work->work_group,0x1b,0,0,ttl*1000, work->work_group,0x1b,0,ttl*1000,
server_type,name,comment, server_type,name,comment,
False, False, ipzero, d->bcast_ip); False, False, ipzero, d->bcast_ip);
} }
@ -257,7 +243,9 @@ void announce_server(struct subnet_record *d, struct work_record *work,
/* XXXX any other kinds of announcements we need to consider here? /* XXXX any other kinds of announcements we need to consider here?
e.g local master browsers... no. local master browsers do e.g local master browsers... no. local master browsers do
local master announcements to their domain master. local master announcements to their domain master. they even
use WINS lookup of the domain master if another wins server
is being used!
*/ */
} }
else else
@ -268,13 +256,10 @@ void announce_server(struct subnet_record *d, struct work_record *work,
inet_ntoa(d->bcast_ip),work->work_group)); inet_ntoa(d->bcast_ip),work->work_group));
do_announce_host(ANN_LocalMasterAnnouncement, do_announce_host(ANN_LocalMasterAnnouncement,
name , 0x00, d->myip, name , 0x00, d->myip,
work->work_group, 0x1e, d->bcast_ip, work->work_group, 0x1e, d->bcast_ip,
ttl*1000, ttl*1000,
name, server_type, name, server_type, comment);
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
DEBUG(3,("sending domain announce to %s for %s\n", DEBUG(3,("sending domain announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group)); inet_ntoa(d->bcast_ip),work->work_group));
@ -283,13 +268,11 @@ void announce_server(struct subnet_record *d, struct work_record *work,
if (server_type != 0) if (server_type != 0)
{ {
do_announce_host(ANN_DomainAnnouncement, do_announce_host(ANN_DomainAnnouncement,
name , 0x00, d->myip, name , 0x00, d->myip,
MSBROWSE, 0x01, d->bcast_ip, MSBROWSE, 0x01, d->bcast_ip,
ttl*1000, ttl*1000,
work->work_group, server_type ? domain_type : 0, work->work_group, server_type ? domain_type : 0,
WG_MAJOR_VERSION, WG_MINOR_VERSION, name);
WG_BROWSE_VERSION, WG_BROWSE_SIGNATURE,
name);
} }
} }
else else
@ -298,13 +281,10 @@ void announce_server(struct subnet_record *d, struct work_record *work,
inet_ntoa(d->bcast_ip),work->work_group)); inet_ntoa(d->bcast_ip),work->work_group));
do_announce_host(ANN_HostAnnouncement, do_announce_host(ANN_HostAnnouncement,
name , 0x00, d->myip, name , 0x00, d->myip,
work->work_group, 0x1d, d->bcast_ip, work->work_group, 0x1d, d->bcast_ip,
ttl*1000, ttl*1000,
name, server_type, name, server_type, comment);
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
} }
} }
} }
@ -317,6 +297,11 @@ void announce_host(void)
time_t t = time(NULL); time_t t = time(NULL);
struct subnet_record *d; struct subnet_record *d;
pstring comment; pstring comment;
char *my_name;
StrnCpy(comment, lp_serverstring(), 43);
my_name = *myname ? myname : "NoName";
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
@ -325,63 +310,62 @@ void announce_host(void)
if (ip_equal(d->bcast_ip, ipgrp)) continue; if (ip_equal(d->bcast_ip, ipgrp)) continue;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
uint32 stype = work->ServerType; uint32 stype = work->ServerType;
struct server_record *s; struct server_record *s;
BOOL announce = False;
char *my_name = conf_browsing_alias(work->token);
char *my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
/* must work on the code that does announcements at up to /* must work on the code that does announcements at up to
30 seconds later if a master browser sends us a request 30 seconds later if a master browser sends us a request
announce. announce.
*/ */
if (work->needannounce) { if (work->needannounce) {
/* drop back to a max 3 minute announce - this is to prevent a /* drop back to a max 3 minute announce - this is to prevent a
single lost packet from stuffing things up for too long */ single lost packet from stuffing things up for too long */
work->announce_interval = MIN(work->announce_interval, work->announce_interval = MIN(work->announce_interval,
CHECK_TIME_MIN_HOST_ANNCE*60); CHECK_TIME_MIN_HOST_ANNCE*60);
work->lastannounce_time = t - (work->announce_interval+1); work->lastannounce_time = t - (work->announce_interval+1);
} }
/* announce every minute at first then progress to every 12 mins */ /* announce every minute at first then progress to every 12 mins */
if (work->lastannounce_time && if (work->lastannounce_time &&
(t - work->lastannounce_time) < work->announce_interval) (t - work->lastannounce_time) < work->announce_interval)
continue; continue;
if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60)
work->announce_interval += 60; work->announce_interval += 60;
work->lastannounce_time = t; work->lastannounce_time = t;
for (s = work->serverlist; s; s = s->next) { for (s = work->serverlist; s; s = s->next) {
if (strequal(my_name, s->serv.name)) if (strequal(myname, s->serv.name)) {
{ announce = True;
announce_server(d,work,my_name,comment, break;
work->announce_interval,stype); }
break; }
}
} if (announce) {
announce_server(d,work,my_name,comment,
if (work->needannounce) work->announce_interval,stype);
{ }
work->needannounce = False;
break; if (work->needannounce)
/* sorry: can't do too many announces. do some more later */ {
} work->needannounce = False;
} break;
/* sorry: can't do too many announces. do some more later */
}
}
} }
} }
/**************************************************************************** /****************************************************************************
announce samba as a master to all other primary domain conrollers. announce myself as a master to all other primary domain conrollers.
this actually gets done in search_and_sync_workgroups() via the this actually gets done in search_and_sync_workgroups() via the
NAME_QUERY_DOM_SRV_CHK state, if there is a response from the NAME_QUERY_DOM_SRV_CHK command, if there is a response from the
name query initiated here. see response_name_query() name query initiated here. see response_name_query()
**************************************************************************/ **************************************************************************/
void announce_master(void) void announce_master(void)
@ -393,108 +377,97 @@ void announce_master(void)
if (!last) last = t; if (!last) last = t;
if (t-last < CHECK_TIME_MST_ANNOUNCE * 60) if (t-last < CHECK_TIME_MST_ANNOUNCE * 60)
return; return;
last = t; last = t;
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{ {
if (AM_MASTER(work) || AM_DMBRSE(work)) struct work_record *work;
{ for (work = d->workgrouplist; work; work = work->next)
am_master = True; {
} if (AM_MASTER(work))
{
am_master = True;
}
}
} }
}
if (!am_master) return; /* only proceed if we are a master browser */ if (!am_master) return; /* only proceed if we are a master browser */
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{ {
struct server_record *s; struct work_record *work;
for (s = work->serverlist; s; s = s->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (strequal(s->serv.name, conf_browsing_alias(work->token))) continue; struct server_record *s;
for (s = work->serverlist; s; s = s->next)
/* all master browsers */ {
if (s->serv.type & SV_TYPE_DOMAIN_MASTER) if (strequal(s->serv.name, myname)) continue;
{
/* check the existence of a domain master for this workgroup, /* all DOMs (which should also be master browsers) */
and if one exists at the specified ip, sync with it and if (s->serv.type & SV_TYPE_DOMAIN_CTRL)
announce ourselves as a local master browser to it */ {
/* check the existence of a pdc for this workgroup, and if
/* exclude lp_domain_controller() from this check if it's one exists at the specified ip, sync with it and announce
in our browse lists, because it's dealt with separately ourselves as a master browser to it */
*/
if (!*lp_domain_controller() || if (!*lp_domain_controller() ||
!strequal(lp_domain_controller(), s->serv.name)) !strequal(lp_domain_controller(), s->serv.name))
{ {
if (lp_wins_support() || *lp_wins_server()) if (!lp_wins_support() && *lp_wins_server())
{ {
/* query the WINS server (that may include samba itself) queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
to find the browse master NAME_QUERY_DOM_SRV_CHK,
*/ work->work_group,0x1b,0,0,0,NULL,NULL,
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, False, False, ipzero, ipzero);
NAME_QUERY_DOM_SRV_CHK, }
work->token, else
work->work_group,0x1b,0,0,0,0,NULL,NULL, {
False, False, ipzero, ipzero); struct subnet_record *d2;
} for (d2 = subnetlist; d2; d2 = d2->next)
else {
{ queue_netbios_packet(d,ClientNMB,NMB_QUERY,
struct subnet_record *d2; NAME_QUERY_DOM_SRV_CHK,
for (d2 = subnetlist; d2; d2 = d2->next) work->work_group,0x1b,0,0,0,NULL,NULL,
{ True, False, d2->bcast_ip, d2->bcast_ip);
/* query by broadcast on every local interface }
to find the browse master }
*/ }
queue_netbios_packet(d,ClientNMB,NMB_QUERY, }
NAME_QUERY_DOM_SRV_CHK, }
work->token, work->work_group,0x1b,
0,0,0,0,NULL,NULL, /* now do primary domain controller - the one that's not
True, False, d2->bcast_ip, d2->bcast_ip); necessarily in our browse lists, although it ought to be
} this pdc is the one that we get TOLD about through smb.conf.
} basically, if it's on a subnet that we know about, it may end
} up in our browse lists (which is why it's explicitly excluded
} in the code above) */
}
if (*lp_domain_controller())
/* now do primary domain controller - the one that's not {
necessarily in our browse lists, although it ought to be struct in_addr ip;
this pdc is the one that we get TOLD about through smb.conf. BOOL bcast = False;
basically, if it's on a subnet that we know about, it may end
up in our browse lists (which is why it's explicitly excluded ip = *interpret_addr2(lp_domain_controller());
in the code above) */
if (zero_ip(ip)) {
if (*lp_domain_controller()) ip = d->bcast_ip;
{ bcast = True;
struct in_addr ip; }
ip = *interpret_addr2(lp_domain_controller()); DEBUG(2, ("Searching for DOM %s at %s\n",
lp_domain_controller(), inet_ntoa(ip)));
/* if the ip is zero, then make the query to samba as a WINS server */
/* XXXX later, if this also fails, we could also do a broadcast query on /* check the existence of a pdc for this workgroup, and if
samba's local subnets one exists at the specified ip, sync with it and announce
*/ ourselves as a master browser to it */
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
DEBUG(2, ("Searching for DOM %s at %s\n", work->work_group,0x1b,0,0,0,NULL,NULL,
lp_domain_controller(), inet_ntoa(ip))); bcast, False, ip, ip);
}
/* check the existence of a pdc for this workgroup, and if }
one exists at the specified ip, sync with it and announce
ourselves as a master browser to it */
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
work->token, work->work_group,0x1b,
0,0,0,0,NULL,NULL,
False, False, ip, ip);
}
} }
}
} }
@ -512,7 +485,6 @@ void announce_remote(void)
pstring s2; pstring s2;
struct in_addr addr; struct in_addr addr;
char *comment,*workgroup; char *comment,*workgroup;
int token;
int stype = DFLT_SERVER_TYPE; int stype = DFLT_SERVER_TYPE;
if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL) if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL)
@ -523,16 +495,13 @@ void announce_remote(void)
s = lp_remote_announce(); s = lp_remote_announce();
if (!*s) return; if (!*s) return;
comment = lp_serverstring(); /* default comment */ comment = lp_serverstring();
workgroup = lp_workgroup(); /* default workgroup name */ workgroup = lp_workgroup();
for (ptr=s; next_token(&ptr,s2,NULL); ) for (ptr=s; next_token(&ptr,s2,NULL); ) {
{
/* the entries are of the form a.b.c.d/WORKGROUP with /* the entries are of the form a.b.c.d/WORKGROUP with
WORKGROUP being optional */ WORKGROUP being optional */
char *wgroup; char *wgroup;
char *my_name;
extern pstring myname; /* samba's default NetBIOS name */
wgroup = strchr(s2,'/'); wgroup = strchr(s2,'/');
if (wgroup) *wgroup++ = 0; if (wgroup) *wgroup++ = 0;
@ -541,17 +510,10 @@ void announce_remote(void)
addr = *interpret_addr2(s2); addr = *interpret_addr2(s2);
token = conf_workgroup_name_to_token(wgroup, myname); do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr),
my_name = conf_browsing_alias(token); wgroup,0x1e,addr,
my_name = my_name ? my_name : myname; REMOTE_ANNOUNCE_INTERVAL,
myname,stype,comment);
do_announce_host(ANN_HostAnnouncement,
my_name, 0x20, *iface_ip(addr),
wgroup , 0x1e, addr,
REMOTE_ANNOUNCE_INTERVAL,
my_name,stype,
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
} }
} }

View File

@ -23,9 +23,6 @@
14 jan 96: lkcl@pires.co.uk 14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -74,21 +71,21 @@ void expire_browse_cache(time_t t)
for (b = browserlist; b; b = nextb) for (b = browserlist; b; b = nextb)
{ {
if (b->synced && b->sync_time < t) if (b->synced && b->sync_time < t)
{ {
DEBUG(3,("Removing dead cached browser %s\n",b->name)); DEBUG(3,("Removing dead cached browser %s\n",b->name));
nextb = b->next; nextb = b->next;
if (b->prev) b->prev->next = b->next; if (b->prev) b->prev->next = b->next;
if (b->next) b->next->prev = b->prev; if (b->next) b->next->prev = b->prev;
if (browserlist == b) browserlist = b->next; if (browserlist == b) browserlist = b->next;
free(b); free(b);
} }
else else
{ {
nextb = b->next; nextb = b->next;
} }
} }
} }
@ -97,7 +94,7 @@ void expire_browse_cache(time_t t)
add a browser entry add a browser entry
****************************************************************************/ ****************************************************************************/
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
time_t ttl, struct in_addr ip, BOOL local) time_t ttl, struct in_addr ip, BOOL local)
{ {
BOOL newentry=False; BOOL newentry=False;
@ -112,9 +109,9 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
if (b && b->synced) if (b && b->synced)
{ {
/* entries get left in the cache for a while. this stops sync'ing too /* entries get left in the cache for a while. this stops sync'ing too
often if the network is large */ often if the network is large */
DEBUG(4, ("browser %s %s %s already sync'd at time %d\n", DEBUG(4, ("browser %s %s %s already sync'd at time %d\n",
b->name, b->group, inet_ntoa(b->ip), b->sync_time)); b->name, b->group, inet_ntoa(b->ip), b->sync_time));
return NULL; return NULL;
} }
@ -149,12 +146,12 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
add_browse_cache(b); add_browse_cache(b);
DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n", DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
wg, name, type, inet_ntoa(ip),ttl)); wg, name, type, inet_ntoa(ip),ttl));
} }
else else
{ {
DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n", DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n",
wg, name, type, inet_ntoa(ip),ttl)); wg, name, type, inet_ntoa(ip),ttl));
} }
return(b); return(b);
@ -169,23 +166,23 @@ static void start_sync_browse_entry(struct browse_cache_record *b)
struct subnet_record *d; struct subnet_record *d;
struct work_record *work; struct work_record *work;
if( (d = find_subnet(b->ip)) == (struct subnet_record *)NULL ) return; if (!(d = find_subnet(b->ip))) return;
if (!(work = find_workgroupstruct(d, b->group, False))) return; if (!(work = find_workgroupstruct(d, b->group, False))) return;
/* only sync if we are the master */ /* only sync if we are the master */
if (AM_MASTER(work)) { if (AM_MASTER(work)) {
/* first check whether the group we intend to sync with exists. if it /* first check whether the group we intend to sync with exists. if it
doesn't, the server must have died. o dear. */ doesn't, the server must have died. o dear. */
/* see response_netbios_packet() or expire_netbios_response_entries() */ /* see response_netbios_packet() or expire_netbios_response_entries() */
queue_netbios_packet(d,ClientNMB,NMB_QUERY, queue_netbios_packet(d,ClientNMB,NMB_QUERY,
b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
work->token,b->group,0x20,0,0,0,0,NULL,NULL, b->group,0x20,0,0,0,NULL,NULL,
False,False,b->ip,b->ip); False,False,b->ip,b->ip);
} }
b->synced = True; b->synced = True;
} }

View File

@ -58,12 +58,10 @@ struct smbbrowse
char work_name[16]; /* workgroup name */ char work_name[16]; /* workgroup name */
char browsing_alias[16]; /* alias for our role in this workgroup */ char browsing_alias[16]; /* alias for our role in this workgroup */
struct server_identity *my_names; /* a list of server name we should appear here as */ struct server_identity *my_names; /* a list of server name we should appear here as */
BOOL should_workgroup_member; /* should we be a member of this workgroup? */ BOOL should_workgroup_member; /* should we try to become a member of this workgroup? */
BOOL should_local_master; /* should we be a master browser? */ BOOL should_local_master; /* should we try to become a master browser? */
BOOL should_preferred_master; /* should we initiate attempts to become a master browser? */ BOOL should_domain_master; /* should we try to become the domain master browser? */
BOOL should_domain_master; /* should we be the domain master browser? */ } ;
BOOL should_domain_logon; /* should we be the domain logon? */
};
/* The whole list */ /* The whole list */
static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL; static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL;
@ -89,7 +87,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model,
{ {
struct smbbrowse *new; struct smbbrowse *new;
if ( ! (array_size > nexttoken) ) if( ! (array_size > nexttoken) )
{ {
array_size += 10; array_size += 10;
smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups, smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups,
@ -98,7 +96,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model,
new = &smbbrowse_workgroups[nexttoken]; new = &smbbrowse_workgroups[nexttoken];
if (model != (struct smbbrowse *)NULL ) if(model != (struct smbbrowse *)NULL )
memcpy(new, model, sizeof(struct smbbrowse)); memcpy(new, model, sizeof(struct smbbrowse));
else else
memset(new, 0, sizeof(struct smbbrowse)); memset(new, 0, sizeof(struct smbbrowse));
@ -129,22 +127,22 @@ int conf_workgroup_name_to_token(char *workgroup_name,char *default_name)
int idx; int idx;
/* Look for an existing instance. */ /* Look for an existing instance. */
for (idx=0; idx < nexttoken; idx++) for(idx=0; idx < nexttoken; idx++)
{ {
if (strequal(workgroup_name, smbbrowse_workgroups[idx].work_name)) if(strequal(workgroup_name, smbbrowse_workgroups[idx].work_name))
{ {
return idx; return idx;
} }
} }
/* See if creating new ones in admissable. */ /* See if creating new ones in admissable. */
for (idx=0; idx < nexttoken; idx++) for(idx=0; idx < nexttoken; idx++)
{ {
if (strequal("*", smbbrowse_workgroups[idx].work_name)) if(strequal("*", smbbrowse_workgroups[idx].work_name))
{ {
struct smbbrowse *w = new_workgroup(&smbbrowse_workgroups[idx], struct smbbrowse *w = new_workgroup(&smbbrowse_workgroups[idx],
workgroup_name, default_name); workgroup_name, default_name);
w->should_workgroup_member = True; w->should_workgroup_member = False;
return (nexttoken - 1); return (nexttoken - 1);
} }
@ -160,7 +158,7 @@ int conf_workgroup_name_to_token(char *workgroup_name,char *default_name)
*/ */
static int range_check(int token) static int range_check(int token)
{ {
if (token < 0 || token >= nexttoken) if(token < 0 || token >= nexttoken)
{ {
DEBUG(0, ("range_check(): failed\n")); DEBUG(0, ("range_check(): failed\n"));
return True; return True;
@ -174,25 +172,12 @@ static int range_check(int token)
*/ */
char *conf_workgroup_name(int token) char *conf_workgroup_name(int token)
{ {
if (range_check(token)) if(range_check(token))
return (char*)NULL; return (char*)NULL;
return smbbrowse_workgroups[token].work_name; return smbbrowse_workgroups[token].work_name;
} }
/*
** Given a token, return True if we should try
** to become a master browser.
*/
int conf_should_preferred_master(int token)
{
if (range_check(token))
return False;
return smbbrowse_workgroups[token].should_preferred_master;
}
/* /*
** Given a token, return True if we should try ** Given a token, return True if we should try
** to become a master browser. ** to become a master browser.
@ -200,7 +185,7 @@ int conf_should_preferred_master(int token)
int conf_should_workgroup_member(int token) int conf_should_workgroup_member(int token)
{ {
if (range_check(token)) if(range_check(token))
return False; return False;
return smbbrowse_workgroups[token].should_workgroup_member; return smbbrowse_workgroups[token].should_workgroup_member;
@ -211,22 +196,12 @@ int conf_should_workgroup_member(int token)
** to become a master browser. ** to become a master browser.
*/ */
int conf_should_local_master(int token) int conf_should_local_master(int token)
{ {
if (range_check(token)) return False; if(range_check(token))
return False;
return smbbrowse_workgroups[token].should_local_master; return smbbrowse_workgroups[token].should_local_master;
} }
/*
** Given a token, return True if we should try
** to become a domain master browser.
*/
int conf_should_domain_logon(int token)
{
if (range_check(token)) return False;
return smbbrowse_workgroups[token].should_domain_logon;
}
/* /*
** Given a token, return True if we should try ** Given a token, return True if we should try
@ -234,7 +209,7 @@ int conf_should_domain_logon(int token)
*/ */
int conf_should_domain_master(int token) int conf_should_domain_master(int token)
{ {
if (range_check(token)) if(range_check(token))
return False; return False;
return smbbrowse_workgroups[token].should_domain_master; return smbbrowse_workgroups[token].should_domain_master;
@ -244,12 +219,12 @@ int conf_should_domain_master(int token)
** Given a token, return the name. ** Given a token, return the name.
*/ */
char *conf_browsing_alias(int token) char *conf_browsing_alias(int token)
{ {
if (range_check(token)) if(range_check(token))
return (char*)NULL; return (char*)NULL;
return smbbrowse_workgroups[token].browsing_alias; return smbbrowse_workgroups[token].browsing_alias;
} }
/* /*
** Return the server comment which should be used with the ** Return the server comment which should be used with the
@ -257,11 +232,11 @@ char *conf_browsing_alias(int token)
*/ */
char *conf_browsing_alias_comment(int token) char *conf_browsing_alias_comment(int token)
{ {
if (range_check(token)) if(range_check(token))
return (char*) NULL; return (char*) NULL;
return lp_server_comment(); return "Browser";
} }
/* /*
** Given an alias name for this server, return the name of the workgroup ** Given an alias name for this server, return the name of the workgroup
@ -273,11 +248,11 @@ char *conf_alias_to_workgroup(char *alias)
DEBUG(4,("alias_to_workgroup: %s", alias)); DEBUG(4,("alias_to_workgroup: %s", alias));
for (x=0; x < nexttoken; x++) for(x=0; x < nexttoken; x++)
{ {
DEBUG(4,("%s ", smbbrowse_workgroups[x].browsing_alias)); DEBUG(4,("%s ", smbbrowse_workgroups[x].browsing_alias));
if (strequal(alias, smbbrowse_workgroups[x].browsing_alias)) if(strequal(alias, smbbrowse_workgroups[x].browsing_alias))
{ {
DEBUG(4,("OK\n")); DEBUG(4,("OK\n"));
return smbbrowse_workgroups[x].work_name; return smbbrowse_workgroups[x].work_name;
@ -295,9 +270,9 @@ int conf_alias_to_token(char *alias)
{ {
int x; int x;
for (x=0; x < nexttoken; x++) for(x=0; x < nexttoken; x++)
{ {
if (strequal(alias, smbbrowse_workgroups[x].browsing_alias)) if(strequal(alias, smbbrowse_workgroups[x].browsing_alias))
{ {
return x; return x;
} }
@ -315,19 +290,15 @@ static void default_smbbrowse_conf(char *default_name)
/* The workgroup specified in smb.conf */ /* The workgroup specified in smb.conf */
w = new_workgroup((struct smbbrowse *)NULL, lp_workgroup(), default_name); w = new_workgroup((struct smbbrowse *)NULL, lp_workgroup(), default_name);
w->should_local_master = lp_local_master(); w->should_local_master = lp_preferred_master();
w->should_domain_master = lp_domain_master(); w->should_domain_master = lp_domain_master();
w->should_domain_logon = lp_domain_logons();
w->should_workgroup_member = True; w->should_workgroup_member = True;
/* default action: allow any new workgroup to be added. this is /* default action: allow any new workgroup to be added */
_not_ the same as the old 1.9.14-1.9.15 definition of "*"
*/
w = new_workgroup((struct smbbrowse *)NULL, "*", default_name); w = new_workgroup((struct smbbrowse *)NULL, "*", default_name);
w->should_local_master = False; w->should_local_master = False;
w->should_domain_master = False; w->should_domain_master = False;
w->should_workgroup_member = False; w->should_workgroup_member = False;
w->should_domain_logon = False;
} }
/* /*
@ -360,10 +331,8 @@ void read_smbbrowse_conf(char *default_name)
if (count <= 0) continue; if (count <= 0) continue;
w = new_workgroup((struct smbbrowse *)NULL, work_name, default_name); w = new_workgroup((struct smbbrowse *)NULL, work_name, default_name);
w->should_local_master = lp_local_master(); w->should_local_master = lp_local_master();
w->should_domain_master = lp_domain_master(); w->should_domain_master = lp_domain_master();
w->should_preferred_master = lp_preferred_master();
w->should_domain_logon = lp_domain_logons();
w->should_workgroup_member = True; w->should_workgroup_member = True;
} }

View File

@ -27,10 +27,6 @@
04 jul 96: lkcl@pires.co.uk 04 jul 96: lkcl@pires.co.uk
created module namedbname containing name database functions created module namedbname containing name database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -47,16 +43,6 @@ extern struct subnet_record *subnetlist;
uint16 nb_type = 0; /* samba's NetBIOS name type */ uint16 nb_type = 0; /* samba's NetBIOS name type */
static char *source_description[] =
{
"STATUS_QUERY",
"LMHOSTS",
"REG",
"SELF",
"DNS",
"DNSFAIL"
};
/**************************************************************************** /****************************************************************************
samba's NetBIOS name type samba's NetBIOS name type
@ -66,14 +52,14 @@ static char *source_description[] =
****************************************************************************/ ****************************************************************************/
void set_samba_nb_type(void) void set_samba_nb_type(void)
{ {
if (lp_wins_support() || (*lp_wins_server())) if (lp_wins_support() || (*lp_wins_server()))
{ {
nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
} }
else else
{ {
nb_type = NB_BFLAG; /* samba is broadcast-only node type */ nb_type = NB_BFLAG; /* samba is broadcast-only node type */
} }
} }
@ -83,7 +69,7 @@ void set_samba_nb_type(void)
BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2) BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
{ {
return n1->name_type == n2->name_type && return n1->name_type == n2->name_type &&
strequal(n1->name ,n2->name ) && strequal(n1->name ,n2->name ) &&
strequal(n1->scope,n2->scope); strequal(n1->scope,n2->scope);
} }
@ -154,22 +140,22 @@ void remove_name(struct subnet_record *d, struct name_record *n)
find a name in a namelist. find a name in a namelist.
**************************************************************************/ **************************************************************************/
struct name_record *find_name(struct name_record *n, struct name_record *find_name(struct name_record *n,
struct nmb_name *name, struct nmb_name *name,
int search) int search)
{ {
struct name_record *ret; struct name_record *ret;
for (ret = n; ret; ret = ret->next) for (ret = n; ret; ret = ret->next)
{ {
if (name_equal(&ret->name,name)) if (name_equal(&ret->name,name))
{ {
/* self search: self names only */ /* self search: self names only */
if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
continue; continue;
return ret; return ret;
} }
} }
return NULL; return NULL;
} }
@ -182,31 +168,29 @@ struct name_record *find_name(struct name_record *n,
FIND_WINS - look for names in the WINS record FIND_WINS - look for names in the WINS record
**************************************************************************/ **************************************************************************/
struct name_record *find_name_search(struct subnet_record **d, struct name_record *find_name_search(struct subnet_record **d,
struct nmb_name *name, struct nmb_name *name,
int search, struct in_addr ip) int search, struct in_addr ip)
{ {
if (d == NULL) return NULL; /* bad error! */ if (d == NULL) return NULL; /* bad error! */
if (search & FIND_LOCAL) if (search & FIND_LOCAL) {
{ if (*d != NULL) {
if (*d != NULL) struct name_record *n = find_name((*d)->namelist, name, search);
{ DEBUG(4,("find_name on local: %s %s search %x\n",
struct name_record *n = find_name((*d)->namelist, name, search); namestr(name),inet_ntoa(ip), search));
DEBUG(4,("find_name on local: %s %s search %x\n", if (n) return n;
namestr(name),inet_ntoa(ip), search)); }
if (n) return n;
}
} }
if ((search & FIND_WINS) != FIND_WINS) return NULL; if (!(search & FIND_WINS)) return NULL;
/* find WINS subnet record. */ /* find WINS subnet record. */
*d = find_subnet(ipgrp); *d = find_subnet(ipgrp);
if (*d == NULL) return NULL; if (*d == NULL) return NULL;
DEBUG(4,("find_name on WINS: %s %s search %x\n", DEBUG(4,("find_name on WINS: %s %s search %x\n",
namestr(name),inet_ntoa(ip), search)); namestr(name),inet_ntoa(ip), search));
return find_name((*d)->namelist, name, search); return find_name((*d)->namelist, name, search);
} }
@ -244,18 +228,20 @@ void dump_names(void)
{ {
int i; int i;
DEBUG(3,("%-15s ", inet_ntoa(d->bcast_ip))); DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip)));
DEBUG(3,("%-19s TTL=%7ld %s ", DEBUG(3,("%15s ", inet_ntoa(d->mask_ip)));
namestr(&n->name), DEBUG(3,("%-19s TTL=%ld ",
n->death_time?n->death_time-t:0, source_description[n->source])); namestr(&n->name),
n->death_time?n->death_time-t:0));
for (i = 0; i < n->num_ips; i++) for (i = 0; i < n->num_ips; i++)
{ {
DEBUG(3,("%-15s NB=%2x ", DEBUG(3,("%15s NB=%2x source=%d",
inet_ntoa(n->ip_flgs[i].ip), inet_ntoa(n->ip_flgs[i].ip),
(unsigned char)n->ip_flgs[i].nb_flags)); n->ip_flgs[i].nb_flags,n->source));
} }
DEBUG(3,("\n")); DEBUG(3,("\n"));
if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER) if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER)
{ {
@ -263,16 +249,16 @@ void dump_names(void)
anything other than as a hexadecimal number :-) */ anything other than as a hexadecimal number :-) */
fprintf(f, "%s#%02x %ld ", fprintf(f, "%s#%02x %ld ",
n->name.name,n->name.name_type, /* XXXX ignore scope for now */ n->name.name,n->name.name_type, /* XXXX ignore scope for now */
n->death_time); n->death_time);
for (i = 0; i < n->num_ips; i++) for (i = 0; i < n->num_ips; i++)
{ {
fprintf(f, "%s %2x ", fprintf(f, "%s %2x ",
inet_ntoa(n->ip_flgs[i].ip), inet_ntoa(n->ip_flgs[i].ip),
(unsigned char)n->ip_flgs[i].nb_flags); n->ip_flgs[i].nb_flags);
} }
fprintf(f, "\n"); fprintf(f, "\n");
} }
} }
@ -321,12 +307,12 @@ void load_netbios_names(void)
int type = 0; int type = 0;
unsigned int nb_flags; unsigned int nb_flags;
time_t ttd; time_t ttd;
struct in_addr ipaddr; struct in_addr ipaddr;
enum name_source source; enum name_source source;
char *ptr; char *ptr;
int count = 0; int count = 0;
char *p; char *p;
@ -334,20 +320,20 @@ void load_netbios_names(void)
if (*line == '#') continue; if (*line == '#') continue;
ptr = line; ptr = line;
if (next_token(&ptr,name_str ,NULL)) ++count; if (next_token(&ptr,name_str ,NULL)) ++count;
if (next_token(&ptr,ttd_str ,NULL)) ++count; if (next_token(&ptr,ttd_str ,NULL)) ++count;
if (next_token(&ptr,ip_str ,NULL)) ++count; if (next_token(&ptr,ip_str ,NULL)) ++count;
if (next_token(&ptr,nb_flags_str,NULL)) ++count; if (next_token(&ptr,nb_flags_str,NULL)) ++count;
if (count <= 0) continue; if (count <= 0) continue;
if (count != 4) { if (count != 4) {
DEBUG(0,("Ill formed wins line")); DEBUG(0,("Ill formed wins line"));
DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line));
continue; continue;
} }
/* netbios name. # divides the name from the type (hex): netbios#xx */ /* netbios name. # divides the name from the type (hex): netbios#xx */
strcpy(name,name_str); strcpy(name,name_str);
@ -355,15 +341,15 @@ void load_netbios_names(void)
p = strchr(name,'#'); p = strchr(name,'#');
if (p) { if (p) {
*p = 0; *p = 0;
sscanf(p+1,"%x",&type); sscanf(p+1,"%x",&type);
} }
/* decode the netbios flags (hex) and the time-to-die (seconds) */ /* decode the netbios flags (hex) and the time-to-die (seconds) */
sscanf(nb_flags_str,"%x",&nb_flags); sscanf(nb_flags_str,"%x",&nb_flags);
sscanf(ttd_str,"%ld",&ttd); sscanf(ttd_str,"%ld",&ttd);
ipaddr = *interpret_addr2(ip_str); ipaddr = *interpret_addr2(ip_str);
if (ip_equal(ipaddr,ipzero)) { if (ip_equal(ipaddr,ipzero)) {
source = SELF; source = SELF;
@ -374,7 +360,7 @@ void load_netbios_names(void)
} }
DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n", DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n",
name,type, ttd, inet_ntoa(ipaddr), nb_flags)); name,type, ttd, inet_ntoa(ipaddr), nb_flags));
/* add all entries that have 60 seconds or more to live */ /* add all entries that have 60 seconds or more to live */
if (ttd - 60 > time(NULL) || ttd == 0) if (ttd - 60 > time(NULL) || ttd == 0)
@ -394,8 +380,8 @@ void load_netbios_names(void)
remove an entry from the name list remove an entry from the name list
****************************************************************************/ ****************************************************************************/
void remove_netbios_name(struct subnet_record *d, void remove_netbios_name(struct subnet_record *d,
char *name,int type, enum name_source source, char *name,int type, enum name_source source,
struct in_addr ip) struct in_addr ip)
{ {
struct nmb_name nn; struct nmb_name nn;
struct name_record *n; struct name_record *n;
@ -419,22 +405,14 @@ void remove_netbios_name(struct subnet_record *d,
****************************************************************************/ ****************************************************************************/
struct name_record *add_netbios_entry(struct subnet_record *d, struct name_record *add_netbios_entry(struct subnet_record *d,
char *name, int type, int nb_flags, char *name, int type, int nb_flags,
int ttl, enum name_source source, struct in_addr ip, int ttl, enum name_source source, struct in_addr ip,
BOOL new_only,BOOL wins) BOOL new_only,BOOL wins)
{ {
struct name_record *n; struct name_record *n;
struct name_record *n2=NULL; struct name_record *n2=NULL;
int search = 0; int search = 0;
BOOL self; BOOL self = source == SELF;
if (iface_ip(ip))
{
source = SELF;
putip(&ip, &ipzero);
}
self = source == SELF;
/* add the name to the WINS list if the name comes from a directed query */ /* add the name to the WINS list if the name comes from a directed query */
search |= wins ? FIND_WINS : FIND_LOCAL; search |= wins ? FIND_WINS : FIND_LOCAL;
@ -487,57 +465,46 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
if (!n2) add_name(d,n); if (!n2) add_name(d,n);
DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n", DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n",
namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); namestr(&n->name),inet_ntoa(ip),ttl,nb_flags));
return(n); return(n);
} }
/******************************************************************* /*******************************************************************
expires or refreshes old names in the namelist expires old names in the namelist
if the name is a samba SELF name, it must be refreshed rather than
removed.
******************************************************************/ ******************************************************************/
void check_expire_names(time_t t) void expire_names(time_t t)
{ {
struct name_record *n; struct name_record *n;
struct name_record *next; struct name_record *next;
struct subnet_record *d; struct subnet_record *d;
/* expire old names */ /* expire old names */
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
for (n = d->namelist; n; n = next) for (n = d->namelist; n; n = next)
{ {
next = n->next; next = n->next;
if (n->death_time && n->death_time < t)
if (n->death_time && n->death_time < t) {
{ if (n->source == SELF) {
if (n->source == SELF) DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name)));
{ n->death_time += 300;
/* refresh the samba name. if this refresh fails continue;
for any reason, it will be deleted. }
*/ DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
DEBUG(3,("Refreshing SELF name %s\n", namestr(&n->name)));
add_my_name_entry(d, -1, if (n->prev) n->prev->next = n->next;
n->name.name, n->name.name_type, if (n->next) n->next->prev = n->prev;
n->ip_flgs[0].nb_flags);
continue; if (d->namelist == n) d->namelist = n->next;
}
free(n->ip_flgs);
DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); free(n);
}
if (n->prev) n->prev->next = n->next; }
if (n->next) n->next->prev = n->prev; }
if (d->namelist == n) d->namelist = n->next;
free(n->ip_flgs);
free(n);
}
}
}
} }
@ -545,8 +512,8 @@ void check_expire_names(time_t t)
reply to a name query reply to a name query
****************************************************************************/ ****************************************************************************/
struct name_record *search_for_name(struct subnet_record **d, struct name_record *search_for_name(struct subnet_record **d,
struct nmb_name *question, struct nmb_name *question,
struct in_addr ip, int Time, int search) struct in_addr ip, int Time, int search)
{ {
int name_type = question->name_type; int name_type = question->name_type;
char *qname = question->name; char *qname = question->name;
@ -571,10 +538,10 @@ struct name_record *search_for_name(struct subnet_record **d,
/* only do DNS lookups if the query is for type 0x20 or type 0x0 */ /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
if (!dns_type && name_type != 0x1b) if (!dns_type && name_type != 0x1b)
{ {
DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n"));
return NULL; return NULL;
} }
/* look it up with DNS */ /* look it up with DNS */
a = interpret_addr(qname); a = interpret_addr(qname);
@ -582,18 +549,18 @@ struct name_record *search_for_name(struct subnet_record **d,
putip((char *)&dns_ip,(char *)&a); putip((char *)&dns_ip,(char *)&a);
if (!a) if (!a)
{ {
/* no luck with DNS. We could possibly recurse here XXXX */ /* no luck with DNS. We could possibly recurse here XXXX */
DEBUG(3,("no recursion.\n")); DEBUG(3,("no recursion.\n"));
/* add the fail to our WINS cache of names. give it 1 hour in the cache */ /* add the fail to our WINS cache of names. give it 1 hour in the cache */
add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,
True, True); True, True);
return NULL; return NULL;
} }
/* add it to our WINS cache of names. give it 2 hours in the cache */ /* add it to our WINS cache of names. give it 2 hours in the cache */
n = add_netbios_entry(*d,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip, n = add_netbios_entry(*d,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
True,True); True,True);
/* failed to add it? yikes! */ /* failed to add it? yikes! */
if (!n) return NULL; if (!n) return NULL;

View File

@ -92,9 +92,8 @@ void remove_response_record(struct subnet_record *d,
create a name query response record create a name query response record
**************************************************************************/ **************************************************************************/
struct response_record *make_response_queue_record(enum state_type state, struct response_record *make_response_queue_record(enum state_type state,
int id,uint16 fd, int quest_type, int id,uint16 fd,
int token, char *name,int type, int quest_type, char *name,int type, int nb_flags, time_t ttl,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment, int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse, BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip) struct in_addr send_ip, struct in_addr reply_to_ip)
@ -110,17 +109,14 @@ struct response_record *make_response_queue_record(enum state_type state,
n->state = state; n->state = state;
n->fd = fd; n->fd = fd;
n->quest_type = quest_type; n->quest_type = quest_type;
n->token = token;
make_nmb_name(&n->name, name, type, scope); make_nmb_name(&n->name, name, type, scope);
n->nb_flags = nb_flags;
n->ttl = ttl; n->ttl = ttl;
n->source = source;
n->server_type = server_type; n->server_type = server_type;
n->bcast = bcast; n->bcast = bcast;
n->recurse = recurse; n->recurse = recurse;
n->reply.nb_flags = nb_flags;
n->reply.ip = reply_to_ip;
n->send_ip = send_ip; n->send_ip = send_ip;
n->reply_to_ip = reply_to_ip;
StrnCpy(my_name , n->my_name , sizeof(n->my_name )-1); StrnCpy(my_name , n->my_name , sizeof(n->my_name )-1);
StrnCpy(my_comment, n->my_comment, sizeof(n->my_comment)-1); StrnCpy(my_comment, n->my_comment, sizeof(n->my_comment)-1);

View File

@ -50,7 +50,7 @@ extern BOOL updatedlists;
remove_all_servers indicates everybody dies. remove_all_servers indicates everybody dies.
******************************************************************/ ******************************************************************/
void remove_old_servers(struct work_record *work, time_t t, void remove_old_servers(struct work_record *work, time_t t,
BOOL remove_all) BOOL remove_all)
{ {
struct server_record *s; struct server_record *s;
struct server_record *nexts; struct server_record *nexts;
@ -59,23 +59,23 @@ void remove_old_servers(struct work_record *work, time_t t,
for (s = work->serverlist; s; s = nexts) for (s = work->serverlist; s; s = nexts)
{ {
if (remove_all || (s->death_time && (t == -1 || s->death_time < t))) if (remove_all || (s->death_time && (t == -1 || s->death_time < t)))
{ {
DEBUG(3,("Removing dead server %s\n",s->serv.name)); DEBUG(3,("Removing dead server %s\n",s->serv.name));
updatedlists = True; updatedlists = True;
nexts = s->next; nexts = s->next;
if (s->prev) s->prev->next = s->next; if (s->prev) s->prev->next = s->next;
if (s->next) s->next->prev = s->prev; if (s->next) s->next->prev = s->prev;
if (work->serverlist == s) if (work->serverlist == s)
work->serverlist = s->next; work->serverlist = s->next;
free(s); free(s);
} }
else else
{ {
nexts = s->next; nexts = s->next;
} }
} }
} }
@ -107,17 +107,17 @@ static void add_server(struct work_record *work,struct server_record *s)
**************************************************************************/ **************************************************************************/
struct server_record *find_server(struct work_record *work, char *name) struct server_record *find_server(struct work_record *work, char *name)
{ {
struct server_record *ret; struct server_record *ret;
if (!work) return NULL; if (!work) return NULL;
for (ret = work->serverlist; ret; ret = ret->next) for (ret = work->serverlist; ret; ret = ret->next)
{ {
if (strequal(ret->serv.name,name)) if (strequal(ret->serv.name,name))
{ {
return ret; return ret;
} }
} }
return NULL; return NULL;
} }
@ -126,15 +126,14 @@ struct server_record *find_server(struct work_record *work, char *name)
add a server entry add a server entry
****************************************************************************/ ****************************************************************************/
struct server_record *add_server_entry(struct subnet_record *d, struct server_record *add_server_entry(struct subnet_record *d,
struct work_record *work, struct work_record *work,
char *name,int servertype, char *name,int servertype,
int ttl,char *comment, int ttl,char *comment,
BOOL replace) BOOL replace)
{ {
BOOL newentry=False; BOOL newentry=False;
struct server_record *s; struct server_record *s;
int token = conf_workgroup_name_to_token(work->work_group, myname);
if (name[0] == '*') if (name[0] == '*')
{ {
return (NULL); return (NULL);
@ -161,14 +160,16 @@ struct server_record *add_server_entry(struct subnet_record *d,
bzero((char *)s,sizeof(*s)); bzero((char *)s,sizeof(*s));
} }
if (conf_should_workgroup_member(token))
{ if (strequal(lp_workgroup(),work->work_group))
if (servertype) servertype |= SV_TYPE_LOCAL_LIST_ONLY; {
} if (servertype)
servertype |= SV_TYPE_LOCAL_LIST_ONLY;
}
else else
{ {
servertype &= ~SV_TYPE_LOCAL_LIST_ONLY; servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
} }
/* update the entry */ /* update the entry */
StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1); StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
@ -193,8 +194,8 @@ struct server_record *add_server_entry(struct subnet_record *d,
} }
DEBUG(3,("server entry %s of type %x (%s) to %s %s\n", DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
name,servertype,comment, name,servertype,comment,
work->work_group,inet_ntoa(d->bcast_ip))); work->work_group,inet_ntoa(d->bcast_ip)));
return(s); return(s);
} }
@ -212,9 +213,9 @@ void expire_servers(time_t t)
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
remove_old_servers(work, t, False); remove_old_servers(work, t, False);
} }
} }
} }

View File

@ -26,9 +26,6 @@
04 jul 96: lkcl@pires.co.uk 04 jul 96: lkcl@pires.co.uk
created module namedbsubnet containing subnet database functions created module namedbsubnet containing subnet database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -93,16 +90,16 @@ struct subnet_record *find_subnet(struct in_addr bcast_ip)
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
if (ip_equal(bcast_ip, wins_ip)) if (ip_equal(bcast_ip, wins_ip))
{ {
if (ip_equal(bcast_ip, d->bcast_ip)) if (ip_equal(bcast_ip, d->bcast_ip))
{ {
return d; return d;
} }
} }
else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
{ {
return(d); return(d);
} }
} }
return (NULL); return (NULL);
@ -157,60 +154,47 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr
****************************************************************************/ ****************************************************************************/
void add_subnet_interfaces(void) void add_subnet_interfaces(void)
{ {
struct interface *i; struct interface *i;
/* loop on all local interfaces */ /* loop on all local interfaces */
for (i = local_interfaces; i; i = i->next) for (i = local_interfaces; i; i = i->next)
{ {
/* add the interface into our subnet database */ /* add the interface into our subnet database */
if (!find_subnet(i->bcast)) if (!find_subnet(i->bcast))
{ {
make_subnet(i->bcast,i->nmask); make_subnet(i->bcast,i->nmask);
} }
} }
/* add the pseudo-ip interface for WINS: 255.255.255.255 */ /* add the pseudo-ip interface for WINS: 255.255.255.255 */
if (lp_wins_support() || (*lp_wins_server())) if (lp_wins_support() || (*lp_wins_server()))
{ {
struct in_addr wins_bcast = ipgrp; struct in_addr wins_bcast = ipgrp;
struct in_addr wins_nmask = ipzero; struct in_addr wins_nmask = ipzero;
make_subnet(wins_bcast, wins_nmask); make_subnet(wins_bcast, wins_nmask);
} }
} }
/****************************************************************************
add the default workgroups into my domain
**************************************************************************/
void add_workgroup_to_subnet(char *group, struct in_addr bcast_ip,
struct in_addr mask_ip)
{
if (group && *group != '*')
{
DEBUG(4,("add_wg_to_subnet: %s %s\n", group, inet_ntoa(bcast_ip)));
add_subnet_entry(bcast_ip,mask_ip,group, True, False);
}
}
/**************************************************************************** /****************************************************************************
add the default workgroup into my domain add the default workgroup into my domain
**************************************************************************/ **************************************************************************/
void add_workgroups_to_subnets() void add_my_subnets(char *group)
{ {
struct interface *i; struct interface *i;
/* add or find domain on our local subnet, in the default workgroup */ /* add or find domain on our local subnet, in the default workgroup */
if (*group == '*') return;
for (i = local_interfaces; i; i = i->next) /* the coding choice is up to you, andrew: i can see why you don't want
{ global access to the local_interfaces structure: so it can't get
int token; messed up! */
for (token = 0; token < get_num_workgroups(); token++) for (i = local_interfaces; i; i = i->next)
{ {
add_workgroup_to_subnet(conf_workgroup_name(token),i->bcast,i->nmask); add_subnet_entry(i->bcast,i->nmask,group, True, False);
} }
}
} }
@ -219,49 +203,48 @@ void add_workgroups_to_subnets()
to the named a workgroup. to the named a workgroup.
****************************************************************************/ ****************************************************************************/
struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
struct in_addr mask_ip, struct in_addr mask_ip,
char *name, BOOL add, BOOL lmhosts) char *name, BOOL add, BOOL lmhosts)
{ {
struct subnet_record *d; struct subnet_record *d;
DEBUG(4,("add_subnet_entry: %s %\n", name,inet_ntoa(bcast_ip))); /* XXXX andrew: struct in_addr ip appears not to be referenced at all except
in the DEBUG comment. i assume that the DEBUG comment below actually
intends to refer to bcast_ip? i don't know.
if (zero_ip(bcast_ip)) bcast_ip = *iface_bcast(bcast_ip); struct in_addr ip = ipgrp;
*/
if (zero_ip(bcast_ip))
bcast_ip = *iface_bcast(bcast_ip);
/* add the domain into our domain database */ /* add the domain into our domain database */
if ((d = find_subnet(bcast_ip)) || (d = make_subnet(bcast_ip, mask_ip))) if ((d = find_subnet(bcast_ip)) ||
{ (d = make_subnet(bcast_ip, mask_ip)))
struct work_record *work = find_workgroupstruct(d, name, add);
if (!work) return NULL;
if (conf_should_workgroup_member(work->token))
{ {
/* add samba server name to workgroup list. don't add struct work_record *w = find_workgroupstruct(d, name, add);
lmhosts server entries to local interfaces */
if (!w) return NULL;
pstring comment;
char *my_name = conf_browsing_alias (work->token);
char *my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
add_server_entry(d,work,my_name,
work->ServerType | SV_TYPE_LOCAL_LIST_ONLY,
0,comment,True);
/* add WORKGROUP(1e) and WORKGROUP(00) entries into name database
or register with WINS server, if it's our workgroup */
if (strequal(lp_workgroup(), name))
{
add_my_name_entry(d,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
}
/* add samba server name to workgroup list. don't add
lmhosts server entries to local interfaces */
if (strequal(lp_workgroup(), name))
{
add_server_entry(d,w,myname,w->ServerType,0,lp_serverstring(),True);
DEBUG(3,("Added server name entry %s at %s\n", DEBUG(3,("Added server name entry %s at %s\n",
name,inet_ntoa(bcast_ip))); name,inet_ntoa(bcast_ip)));
}
/* add WORKGROUP(1e) and WORKGROUP(00) entries into name database
or register with WINS server, if it's our workgroup */
add_my_name_entry(d,work->token,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,work->token,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
}
return d; return d;
} }
return NULL; return NULL;
} }
@ -307,31 +290,31 @@ void write_browse_list(void)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work ; work = work->next) for (work = d->workgrouplist; work ; work = work->next)
{ {
struct server_record *s; struct server_record *s;
for (s = work->serverlist; s ; s = s->next) for (s = work->serverlist; s ; s = s->next)
{ {
fstring tmp; fstring tmp;
/* don't list domains I don't have a master for */ /* don't list domains I don't have a master for */
if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0])
{ {
continue; continue;
} }
/* output server details, plus what workgroup/domain /* output server details, plus what workgroup/domain
they're in. without the domain information, the they're in. without the domain information, the
combined list of all servers in all workgroups gets combined list of all servers in all workgroups gets
sent to anyone asking about any workgroup! */ sent to anyone asking about any workgroup! */
sprintf(tmp, "\"%s\"", s->serv.name); sprintf(tmp, "\"%s\"", s->serv.name);
fprintf(f, "%-25s ", tmp); fprintf(f, "%-25s ", tmp);
fprintf(f, "%08x ", s->serv.type); fprintf(f, "%08x ", s->serv.type);
sprintf(tmp, "\"%s\" ", s->serv.comment); sprintf(tmp, "\"%s\" ", s->serv.comment);
fprintf(f, "%-30s", tmp); fprintf(f, "%-30s", tmp);
fprintf(f, "\"%s\"\n", work->work_group); fprintf(f, "\"%s\"\n", work->work_group);
} }
} }
} }
fclose(f); fclose(f);

View File

@ -26,9 +26,6 @@
04 jul 96: lkcl@pires.co.uk 04 jul 96: lkcl@pires.co.uk
created module namedbwork containing workgroup database functions created module namedbwork containing workgroup database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -43,7 +40,9 @@ extern struct subnet_record *subnetlist;
extern struct in_addr ipgrp; extern struct in_addr ipgrp;
extern pstring myname; int workgroup_count = 0; /* unique index key: one for each workgroup */
/**************************************************************************** /****************************************************************************
add a workgroup into the domain list add a workgroup into the domain list
@ -76,17 +75,11 @@ static void add_workgroup(struct work_record *work, struct subnet_record *d)
static struct work_record *make_workgroup(char *name) static struct work_record *make_workgroup(char *name)
{ {
struct work_record *work; struct work_record *work;
struct subnet_record *d;
int t = -1; int t = -1;
if (!name || !name[0]) return NULL; if (!name || !name[0]) return NULL;
/* conf_workgroup_name_to_token() gets or creates a unique index for the workgroup name */
if ((t = conf_workgroup_name_to_token(name, myname)) == -1)
{
DEBUG(3, ("work_record(\"%s\"): conf_workgroup_name_to_token() refuses to allow workgroup\n", name));
return (struct work_record *)NULL;
}
work = (struct work_record *)malloc(sizeof(*work)); work = (struct work_record *)malloc(sizeof(*work));
if (!work) return(NULL); if (!work) return(NULL);
@ -99,16 +92,34 @@ static struct work_record *make_workgroup(char *name)
work->needelection = False; work->needelection = False;
work->needannounce = True; work->needannounce = True;
work->state = MST_NONE; work->state = MST_NONE;
work->token = t;
/* make sure all token representations of workgroups are unique */
for (d = subnetlist; d && t == -1; d = d->next)
{
struct work_record *w;
for (w = d->workgrouplist; w && t == -1; w = w->next)
{
if (strequal(w->work_group, work->work_group)) t = w->token;
}
}
if (t == -1)
{
work->token = ++workgroup_count;
}
else
{
work->token = t;
}
/* WfWg uses 01040b01 */ /* WfWg uses 01040b01 */
/* Win95 uses 01041501 */ /* Win95 uses 01041501 */
/* NTAS uses ???????? */ /* NTAS uses ???????? */
work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8); work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
work->ElectionCriterion |= (lp_os_level() << 24); work->ElectionCriterion |= (lp_os_level() << 24);
if (lp_domain_master()) {
if (conf_should_domain_master(work->token))
{
work->ElectionCriterion |= 0x80; work->ElectionCriterion |= 0x80;
} }
@ -120,8 +131,8 @@ static struct work_record *make_workgroup(char *name)
remove workgroups remove workgroups
******************************************************************/ ******************************************************************/
struct work_record *remove_workgroup(struct subnet_record *d, struct work_record *remove_workgroup(struct subnet_record *d,
struct work_record *work, struct work_record *work,
BOOL remove_all_servers) BOOL remove_all_servers)
{ {
struct work_record *ret_work = NULL; struct work_record *ret_work = NULL;
@ -154,7 +165,7 @@ struct work_record *remove_workgroup(struct subnet_record *d,
lmhosts file to be added. lmhosts file to be added.
**************************************************************************/ **************************************************************************/
struct work_record *find_workgroupstruct(struct subnet_record *d, struct work_record *find_workgroupstruct(struct subnet_record *d,
fstring name, BOOL add) fstring name, BOOL add)
{ {
struct work_record *ret, *work; struct work_record *ret, *work;
@ -163,51 +174,39 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
DEBUG(4, ("workgroup search for %s: ", name)); DEBUG(4, ("workgroup search for %s: ", name));
if (strequal(name, "*")) if (strequal(name, "*"))
{
#if 0 /* XXXX this is being called too many times */
DEBUG(2,("add any workgroups: initiating browser search on %s\n",
inet_ntoa(d->bcast_ip)));
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
-1,MSBROWSE,0x1,0,0,0,0,NULL,NULL,
True,False, d->bcast_ip, d->bcast_ip);
#endif
return NULL;
}
for (ret = d->workgrouplist; ret; ret = ret->next)
{
if (!strcmp(ret->work_group,name))
{ {
DEBUG(2,("add any workgroups: initiating browser search on %s\n",
inet_ntoa(d->bcast_ip)));
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
MSBROWSE,0x1,0,0,0,NULL,NULL,
True,False, d->bcast_ip, d->bcast_ip);
return NULL;
}
for (ret = d->workgrouplist; ret; ret = ret->next) {
if (!strcmp(ret->work_group,name)) {
DEBUG(4, ("found\n")); DEBUG(4, ("found\n"));
return(ret); return(ret);
} }
} }
if (!add) if (!add) {
{
DEBUG(4, ("not found\n")); DEBUG(4, ("not found\n"));
return NULL; return NULL;
} }
DEBUG(4,("not found: creating\n")); DEBUG(4,("not found: creating\n"));
if ((work = make_workgroup(name)) != NULL) if ((work = make_workgroup(name)))
{
DEBUG(4,("bcast_ip:%s preferred master=%s local_master=%s\n",
inet_ntoa(d->bcast_ip),
BOOLSTR(conf_should_preferred_master(work->token)),
BOOLSTR(conf_should_local_master(work->token)) ));
if (!ip_equal(d->bcast_ip, ipgrp) &&
conf_should_preferred_master(work->token) &&
conf_should_local_master (work->token))
{ {
DEBUG(3, ("preferred master startup for %s\n", work->work_group)); if (!ip_equal(d->bcast_ip, ipgrp) &&
work->needelection = True; lp_preferred_master() &&
work->ElectionCriterion |= (1<<3); strequal(lp_workgroup(), name))
} {
DEBUG(3, ("preferred master startup for %s\n", work->work_group));
work->needelection = True;
work->ElectionCriterion |= (1<<3);
}
add_workgroup(work, d); add_workgroup(work, d);
return(work); return(work);
} }
@ -225,25 +224,25 @@ void dump_workgroups(void)
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
if (d->workgrouplist) if (d->workgrouplist)
{ {
struct work_record *work; struct work_record *work;
DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip)));
DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip)));
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); DEBUG(4,("\t%s(%d)\n", work->work_group, work->token));
if (work->serverlist) if (work->serverlist)
{ {
struct server_record *s; struct server_record *s;
for (s = work->serverlist; s; s = s->next) for (s = work->serverlist; s; s = s->next)
{ {
DEBUG(4,("\t\t%s %8x (%s)\n", DEBUG(4,("\t\t%s %8x (%s)\n",
s->serv.name, s->serv.type, s->serv.comment)); s->serv.name, s->serv.type, s->serv.comment));
} }
} }
} }
} }
} }
} }

View File

@ -28,12 +28,10 @@
04 jul 96: lkcl@pires.co.uk 04 jul 96: lkcl@pires.co.uk
added system to become a master browser by stages. added system to become a master browser by stages.
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
extern int ClientNMB; extern int ClientNMB;
extern int ClientDGRAM; extern int ClientDGRAM;
@ -41,6 +39,7 @@ extern int ClientDGRAM;
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
extern pstring scope; extern pstring scope;
extern pstring myname;
extern struct in_addr ipzero; extern struct in_addr ipzero;
extern struct in_addr ipgrp; extern struct in_addr ipgrp;
@ -52,9 +51,6 @@ extern struct subnet_record *subnetlist;
extern uint16 nb_type; /* samba's NetBIOS name type */ extern uint16 nb_type; /* samba's NetBIOS name type */
extern pstring myname;
/******************************************************************* /*******************************************************************
occasionally check to see if the master browser is around occasionally check to see if the master browser is around
******************************************************************/ ******************************************************************/
@ -72,22 +68,22 @@ void check_master_browser(void)
dump_workgroups(); dump_workgroups();
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{ {
/* if we are not the browse master of a workgroup, and we can't struct work_record *work;
find a browser on the subnet, do something about it. */
if (!AM_MASTER(work)) for (work = d->workgrouplist; work; work = work->next)
{ {
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, /* if we are not the browse master of a workgroup, and we can't
work->token, work->work_group,0x1d,REGISTER,0,0,0,NULL,NULL, find a browser on the subnet, do something about it. */
True,False,d->bcast_ip,d->bcast_ip);
} if (!AM_MASTER(work))
{
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
work->work_group,0x1d,0,0,0,NULL,NULL,
True,False,d->bcast_ip,d->bcast_ip);
}
}
} }
}
} }
@ -106,10 +102,11 @@ void browser_gone(char *work_name, struct in_addr ip)
if (ip_equal(d->bcast_ip,ipgrp)) if (ip_equal(d->bcast_ip,ipgrp))
return; return;
if (conf_should_local_master(work->token)) if (strequal(work->work_group, lp_workgroup()))
{ {
DEBUG(2,("Forcing election on %s %s\n", DEBUG(2,("Forcing election on %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip))); work->work_group,inet_ntoa(d->bcast_ip)));
/* we can attempt to become master browser */ /* we can attempt to become master browser */
work->needelection = True; work->needelection = True;
@ -117,10 +114,10 @@ void browser_gone(char *work_name, struct in_addr ip)
else else
{ {
/* local interfaces: force an election */ /* local interfaces: force an election */
send_election(d, work->work_group, 0, 0, conf_browsing_alias(work->token)); send_election(d, work->work_group, 0, 0, myname);
/* only removes workgroup completely on a local interface /* only removes workgroup completely on a local interface
persistent lmhosts entries on a local interface _will_ be removed. persistent lmhosts entries on a local interface _will_ be removed).
*/ */
remove_workgroup(d, work,True); remove_workgroup(d, work,True);
} }
@ -131,7 +128,7 @@ void browser_gone(char *work_name, struct in_addr ip)
send an election packet send an election packet
**************************************************************************/ **************************************************************************/
void send_election(struct subnet_record *d, char *group,uint32 criterion, void send_election(struct subnet_record *d, char *group,uint32 criterion,
int timeup,char *name) int timeup,char *name)
{ {
pstring outbuf; pstring outbuf;
char *p; char *p;
@ -139,7 +136,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
if (!d) return; if (!d) return;
DEBUG(2,("Sending election to %s for workgroup %s\n", DEBUG(2,("Sending election to %s for workgroup %s\n",
inet_ntoa(d->bcast_ip),group)); inet_ntoa(d->bcast_ip),group));
bzero(outbuf,sizeof(outbuf)); bzero(outbuf,sizeof(outbuf));
p = outbuf; p = outbuf;
@ -155,7 +152,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
p = skip_string(p,1); p = skip_string(p,1);
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip)); name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
} }
@ -175,10 +172,8 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
if (!(work = find_workgroupstruct(d, name, False))) return; if (!(work = find_workgroupstruct(d, name, False))) return;
if (!AM_MASTER(work) && !AM_DMBRSE(work)) return;
if (ms_browser_name(name, name_type) || if (ms_browser_name(name, name_type) ||
(conf_should_workgroup_member(work->token) && (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
(name_type == 0x1d || name_type == 0x1b))) (name_type == 0x1d || name_type == 0x1b)))
{ {
int remove_type = 0; int remove_type = 0;
@ -189,7 +184,7 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
remove_type = SV_TYPE_MASTER_BROWSER; remove_type = SV_TYPE_MASTER_BROWSER;
if (name_type == 0x1b) if (name_type == 0x1b)
remove_type = SV_TYPE_DOMAIN_MASTER; remove_type = SV_TYPE_DOMAIN_MASTER;
become_nonmaster(d, work, remove_type); become_nonmaster(d, work, remove_type);
} }
} }
@ -202,17 +197,17 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
whether to proceed to the next stage in samba becoming a master browser. whether to proceed to the next stage in samba becoming a master browser.
**************************************************************************/ **************************************************************************/
void name_register_work(struct subnet_record *d, int token, void name_register_work(struct subnet_record *d, char *name, int name_type,
char *name, int name_type, enum name_source source, int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast)
{ {
enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
SELF : REGISTER;
if (source == SELF) if (source == SELF)
{ {
char *work_name = conf_workgroup_name(token); struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
struct work_record *work = find_workgroupstruct(d, work_name, False);
add_netbios_entry(d,name,name_type,data->nb_flags, add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
ttl,source,data->ip,True,!bcast);
if (work) if (work)
{ {
@ -254,8 +249,6 @@ void name_register_work(struct subnet_record *d, int token,
******************************************************************/ ******************************************************************/
void become_master(struct subnet_record *d, struct work_record *work) void become_master(struct subnet_record *d, struct work_record *work)
{ {
pstring comment;
/* domain type must be limited to domain enum + server type. it must /* domain type must be limited to domain enum + server type. it must
not have SV_TYPE_SERVER or anything else with SERVER in it, else not have SV_TYPE_SERVER or anything else with SERVER in it, else
clients get confused and start thinking this entry is a server clients get confused and start thinking this entry is a server
@ -263,26 +256,10 @@ void become_master(struct subnet_record *d, struct work_record *work)
*/ */
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
char *my_name ;
char *my_comment;
if (!work) return; if (!work) return;
my_name = conf_browsing_alias(work->token);
my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
if (!conf_should_local_master(work->token))
{
DEBUG(1,("Should not become master for %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip)));
work->state = MST_NONE;
return;
}
DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n", DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
work->work_group,inet_ntoa(d->bcast_ip),work->state)); work->work_group,inet_ntoa(d->bcast_ip),work->state));
switch (work->state) switch (work->state)
{ {
@ -295,10 +272,10 @@ void become_master(struct subnet_record *d, struct work_record *work)
/* update our server status */ /* update our server status */
work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER; work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
add_server_entry(d,work,my_name,work->ServerType,0,comment,True); add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
/* add special browser name */ /* add special browser name */
add_my_name_entry(d,work->token,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP); add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */ /* DON'T do anything else after calling add_my_name_entry() */
return; return;
@ -309,11 +286,10 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->state = MST_MSB; /* ... registering MSBROWSE was successful */ work->state = MST_MSB; /* ... registering MSBROWSE was successful */
/* add server entry on successful registration of MSBROWSE */ /* add server entry on successful registration of MSBROWSE */
add_server_entry(d,work,work->work_group, add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
domain_type,0,conf_browsing_alias(work->token),True);
/* add master name */ /* add master name */
add_my_name_entry(d,work->token,work->work_group,0x1d,nb_type|NB_ACTIVE); add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
/* DON'T do anything else after calling add_my_name_entry() */ /* DON'T do anything else after calling add_my_name_entry() */
return; return;
@ -325,8 +301,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
/* update our server status */ /* update our server status */
work->ServerType |= SV_TYPE_MASTER_BROWSER; work->ServerType |= SV_TYPE_MASTER_BROWSER;
add_server_entry(d,work,conf_browsing_alias(work->token), add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
work->ServerType,0,comment,True);
if (work->serverlist == NULL) /* no servers! */ if (work->serverlist == NULL) /* no servers! */
{ {
@ -346,14 +321,13 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_NONE: case MST_DOMAIN_NONE:
{ {
if (conf_should_domain_master(work->token)) if (lp_domain_master())
{ {
work->state = MST_DOMAIN_MEM; /* ... become domain member */ work->state = MST_DOMAIN_MEM; /* ... become domain member */
DEBUG(3,("domain first stage: register as domain member\n")); DEBUG(3,("domain first stage: register as domain member\n"));
/* add domain member name */ /* add domain member name */
add_my_name_entry(d,work->token,work->work_group,0x1e, add_my_name_entry(d,work->work_group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */ /* DON'T do anything else after calling add_my_name_entry() */
return; return;
@ -368,20 +342,19 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_MEM: case MST_DOMAIN_MEM:
{ {
if (conf_should_domain_master(work->token)) if (lp_domain_master())
{ {
work->state = MST_DOMAIN_TST; /* ... possibly become domain master */ work->state = MST_DOMAIN_TST; /* ... possibly become domain master */
DEBUG(3,("domain second stage: register as domain master\n")); DEBUG(3,("domain second stage: register as domain master\n"));
if (conf_should_domain_logon(work->token)) if (lp_domain_logons())
{ {
work->ServerType |= SV_TYPE_DOMAIN_MEMBER; work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
add_server_entry(d,work,my_name,work->ServerType,0,comment,True); add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
} }
/* add domain master name */ /* add domain master name */
add_my_name_entry(d,work->token,work->work_group,0x1b, add_my_name_entry(d,work->work_group,0x1b,nb_type|NB_ACTIVE );
nb_type|NB_ACTIVE );
/* DON'T do anything else after calling add_my_name_entry() */ /* DON'T do anything else after calling add_my_name_entry() */
return; return;
@ -397,10 +370,10 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_TST: /* while we were still a master browser... */ case MST_DOMAIN_TST: /* while we were still a master browser... */
{ {
/* update our server status */ /* update our server status */
if (conf_should_domain_master(work->token)) if (lp_domain_master())
{ {
struct subnet_record *d1; struct subnet_record *d1;
uint32 update_type = 0; uint32 update_type = 0;
DEBUG(3,("domain third stage: samba is now a domain master.\n")); DEBUG(3,("domain third stage: samba is now a domain master.\n"));
work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */ work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */
@ -408,30 +381,30 @@ void become_master(struct subnet_record *d, struct work_record *work)
update_type |= DFLT_SERVER_TYPE | SV_TYPE_DOMAIN_MASTER | update_type |= DFLT_SERVER_TYPE | SV_TYPE_DOMAIN_MASTER |
SV_TYPE_POTENTIAL_BROWSER; SV_TYPE_POTENTIAL_BROWSER;
work->ServerType |= update_type; work->ServerType |= update_type;
add_server_entry(d,work,my_name,work->ServerType,0,comment,True); add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
for (d1 = subnetlist; d1; d1 = d1->next) for (d1 = subnetlist; d1; d1 = d1->next)
{ {
struct work_record *w; struct work_record *w;
if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue;
for (w = d1->workgrouplist; w; w = w->next) for (w = d1->workgrouplist; w; w = w->next)
{ {
struct server_record *s = find_server(w, my_name); struct server_record *s = find_server(w, myname);
if (strequal(w->work_group, work->work_group)) if (strequal(w->work_group, work->work_group))
{ {
w->ServerType |= update_type; w->ServerType |= update_type;
} }
if (s) if (s)
{ {
s->serv.type |= update_type; s->serv.type |= update_type;
DEBUG(4,("found server %s on %s: update to %8x\n", DEBUG(4,("found server %s on %s: update to %8x\n",
s->serv.name, inet_ntoa(d1->bcast_ip), s->serv.name, inet_ntoa(d1->bcast_ip),
s->serv.type)); s->serv.type));
} }
} }
} }
} }
break; break;
@ -452,25 +425,11 @@ void become_master(struct subnet_record *d, struct work_record *work)
names, and tells the world that we are no longer a master browser. names, and tells the world that we are no longer a master browser.
******************************************************************/ ******************************************************************/
void become_nonmaster(struct subnet_record *d, struct work_record *work, void become_nonmaster(struct subnet_record *d, struct work_record *work,
int remove_type) int remove_type)
{ {
int new_server_type = work->ServerType; int new_server_type = work->ServerType;
pstring comment; DEBUG(2,("Becoming non-master for %s\n",work->work_group));
char *my_name ;
char *my_comment;
BOOL wins = ip_equal(d->bcast_ip, ipgrp);
enum master_state state;
if (!work) return;
my_name = conf_browsing_alias (work->token);
my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
DEBUG(2,("Becoming non-master for %s alias %s\n",work->work_group, my_name));
/* can only remove master or domain types with this function */ /* can only remove master or domain types with this function */
remove_type &= SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER; remove_type &= SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
@ -480,7 +439,6 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
remove_type |= SV_TYPE_DOMAIN_MASTER; remove_type |= SV_TYPE_DOMAIN_MASTER;
new_server_type &= ~remove_type; new_server_type &= ~remove_type;
state = work->state;
if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER))) if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)))
{ {
@ -490,40 +448,25 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
work->ElectionCriterion &= ~0x4; work->ElectionCriterion &= ~0x4;
work->state = MST_NONE; work->state = MST_NONE;
remove_name_entry(d,work->token,MSBROWSE,0x01); /* announce ourselves as no longer active as a master browser. */
announce_server(d, work, work->work_group, myname, 0, 0);
remove_name_entry(d,MSBROWSE ,0x01);
} }
work->ServerType = new_server_type; work->ServerType = new_server_type;
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER)) if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
{ {
if (state == MST_DOMAIN) if (work->state == MST_DOMAIN)
{ work->state = MST_BROWSER;
if (wins) remove_name_entry(d,work->work_group,0x1b);
work->state = MST_NONE;
else
work->state = MST_BROWSER;
}
remove_name_entry(d,work->token,work->work_group,0x1b);
} }
if (!(work->ServerType & SV_TYPE_MASTER_BROWSER)) if (!(work->ServerType & SV_TYPE_MASTER_BROWSER))
{ {
if (state >= MST_BROWSER) if (work->state >= MST_BROWSER)
work->state = MST_NONE; work->state = MST_NONE;
remove_name_entry(d,work->token,work->work_group,0x1d); remove_name_entry(d,work->work_group,0x1d);
}
/* update our internal records with our new server state */
add_server_entry(d, work, my_name, work->ServerType, 0, my_comment, True);
/* announce change in status on local interface */
if (!wins)
{
/* XXXX do we need also to do an announce with a time of zero
if we are no longer a local master browser?
*/
work->needannounce = True;
} }
} }
@ -547,27 +490,25 @@ void run_elections(void)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (work->RunningElection) if (work->RunningElection)
{ {
char *alias = conf_browsing_alias(work->token); send_election(d,work->work_group, work->ElectionCriterion,
t-StartupTime,myname);
if (work->ElectionCount++ >= 4)
{
/* I won! now what :-) */
DEBUG(2,(">>> Won election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
work->RunningElection = False;
work->state = MST_NONE;
send_election(d,work->work_group, work->ElectionCriterion, become_master(d, work);
t-StartupTime,alias); }
}
if (work->ElectionCount++ >= 4) }
{
/* I won! now what :-) */
DEBUG(2,(">>> Won election for %s as %s on %s <<<\n",
work->work_group,alias,inet_ntoa(d->bcast_ip)));
work->RunningElection = False;
work->state = MST_NONE;
become_master(d, work);
}
}
}
} }
} }
@ -576,7 +517,7 @@ void run_elections(void)
work out if I win an election work out if I win an election
******************************************************************/ ******************************************************************/
static BOOL win_election(struct work_record *work,int version,uint32 criterion, static BOOL win_election(struct work_record *work,int version,uint32 criterion,
int timeup,char *name) int timeup,char *name)
{ {
int mytimeup = time(NULL) - StartupTime; int mytimeup = time(NULL) - StartupTime;
uint32 mycriterion = work->ElectionCriterion; uint32 mycriterion = work->ElectionCriterion;
@ -596,7 +537,7 @@ static BOOL win_election(struct work_record *work,int version,uint32 criterion,
if (timeup > mytimeup) return(False); if (timeup > mytimeup) return(False);
if (timeup < mytimeup) return(True); if (timeup < mytimeup) return(True);
if (strcasecmp(conf_browsing_alias(work->token),name) > 0) return(False); if (strcasecmp(myname,name) > 0) return(False);
return(True); return(True);
} }
@ -634,38 +575,30 @@ void process_election(struct packet_struct *p,char *buf)
if (same_context(dgram)) return; if (same_context(dgram)) return;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (!conf_should_local_master(work->token)) continue; if (!strequal(work->work_group, lp_workgroup()))
continue;
if (win_election(work, version,criterion,timeup,name)) if (win_election(work, version,criterion,timeup,name)) {
{ if (!work->RunningElection) {
if (!work->RunningElection) work->needelection = True;
{ work->ElectionCount=0;
work->needelection = True; work->state = MST_NONE;
work->ElectionCount=0; }
work->state = MST_NONE; } else {
} work->needelection = False;
if (work->RunningElection || AM_MASTER(work)) {
work->RunningElection = False;
DEBUG(3,(">>> Lost election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
if (AM_MASTER(work))
become_nonmaster(d, work,
SV_TYPE_MASTER_BROWSER|
SV_TYPE_DOMAIN_MASTER);
}
}
} }
else
{
work->needelection = False;
if (work->RunningElection || AM_MASTER(work))
{
work->RunningElection = False;
DEBUG(3,(">>> Lost election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
/* if we are the master then remove our masterly names */
if (AM_MASTER(work))
{
become_nonmaster(d, work,
SV_TYPE_MASTER_BROWSER|
SV_TYPE_DOMAIN_MASTER);
}
}
}
}
} }
@ -686,18 +619,18 @@ BOOL check_elections(void)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
run_any_election |= work->RunningElection; run_any_election |= work->RunningElection;
if (work->needelection && !work->RunningElection) if (work->needelection && !work->RunningElection)
{ {
DEBUG(3,(">>> Starting election on %s %s <<<\n", DEBUG(3,(">>> Starting election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip))); work->work_group,inet_ntoa(d->bcast_ip)));
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;
} }

View File

@ -21,11 +21,7 @@
Revision History: Revision History:
14 jan 96: lkcl@pires.co.uk 14 jan 96: lkcl@pires.co.uk
added domain master browser support added multiple workgroup domain master support
30 aug 96: lkcl@pires.co.uk
added multiple domain logon support, using extensions to David Chappell's
multiple domain master browser code.
*/ */
@ -33,8 +29,13 @@
extern int ClientDGRAM; extern int ClientDGRAM;
#define TEST_CODE /* want to debug unknown browse packets */
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
extern pstring myname;
/**************************************************************************** /****************************************************************************
process a domain logon packet process a domain logon packet
@ -53,18 +54,14 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
pstring outbuf; pstring outbuf;
int code,reply_code; int code,reply_code;
struct work_record *work; struct work_record *work;
char *my_name;
if (!d) return; if (!d) return;
if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
return; return;
if ((my_name = conf_browsing_alias(work->token)) == NULL) return; if (!lp_domain_logons()) {
DEBUG(3,("No domain logons\n"));
if (!conf_should_domain_logon(work->token))
{
DEBUG(3,("No domain logons for %s (%s)\n", work->work_group, my_name));
return; return;
} }
@ -76,7 +73,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
char *user = skip_string(machine,1); char *user = skip_string(machine,1);
logname = skip_string(user,1); logname = skip_string(user,1);
reply_code = 6; reply_code = 6;
strcpy(reply_name, my_name); strcpy(reply_name,myname);
strupper(reply_name); strupper(reply_name);
add_slashes = True; add_slashes = True;
DEBUG(3,("Domain login request from %s(%s) user=%s\n", DEBUG(3,("Domain login request from %s(%s) user=%s\n",
@ -90,7 +87,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
reply_code = 7; reply_code = 7;
strcpy(reply_name,lp_domain_controller()); strcpy(reply_name,lp_domain_controller());
if (!*reply_name) { if (!*reply_name) {
strcpy(reply_name,my_name); strcpy(reply_name,myname);
reply_code = 0xC; reply_code = 0xC;
} }
strupper(reply_name); strupper(reply_name);
@ -124,8 +121,8 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
PutUniCode(q,reply_name); PutUniCode(q,reply_name);
q += 2*(strlen(reply_name) + 1); q += 2*(strlen(reply_name) + 1);
PutUniCode(q,work->work_group); PutUniCode(q,lp_workgroup());
q += 2*(strlen(work->work_group) + 1); q += 2*(strlen(lp_workgroup()) + 1);
SIVAL(q,0,1); SIVAL(q,0,1);
q += 4; q += 4;
@ -137,6 +134,6 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
q += 2; q += 2;
send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf), send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
my_name,&dgram->source_name.name[0],0x20,0,p->ip, myname,&dgram->source_name.name[0],0x20,0,p->ip,
*iface_ip(p->ip)); *iface_ip(p->ip));
} }

View File

@ -38,92 +38,7 @@ BOOL CanRecurse = True;
extern pstring scope; extern pstring scope;
extern struct in_addr ipgrp; extern struct in_addr ipgrp;
extern uint16 name_trn_id; static uint16 name_trn_id=0;
/****************************************************************************
process a nmb packet
****************************************************************************/
static void process_nmb(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
debug_nmb_packet(p);
switch (nmb->header.opcode)
{
case 8: /* what is this?? */
case NMB_REG:
case NMB_REG_REFRESH:
{
if (nmb->header.response)
{
if (nmb->header.ancount==0) break;
response_netbios_packet(p);
}
else
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
reply_name_reg(p);
}
break;
}
case 0:
{
if (nmb->header.response)
{
switch (nmb->question.question_type)
{
case 0x0:
{
response_netbios_packet(p);
break;
}
}
return;
}
else if (nmb->header.qdcount>0)
{
switch (nmb->question.question_type)
{
case NMB_QUERY:
{
reply_name_query(p);
break;
}
case NMB_STATUS:
{
reply_name_status(p);
break;
}
}
return;
}
break;
}
case NMB_REL:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0)
{
DEBUG(2,("netbios release packet rejected\n"));
break;
}
if (nmb->header.response)
{
if (nmb->header.ancount==0) break;
response_netbios_packet(p);
}
else
{
reply_name_release(p);
}
break;
}
}
}
/*************************************************************************** /***************************************************************************
@ -134,69 +49,79 @@ void debug_browse_data(char *outbuf, int len)
int i,j; int i,j;
for (i = 0; i < len; i+= 16) for (i = 0; i < len; i+= 16)
{ {
DEBUG(4, ("%3x char ", i)); DEBUG(4, ("%3x char ", i));
for (j = 0; j < 16; j++) for (j = 0; j < 16; j++)
{ {
unsigned char x = outbuf[i+j]; unsigned char x = outbuf[i+j];
if (x < 32 || x > 127) x = '.'; if (x < 32 || x > 127) x = '.';
if (i+j >= len) break; if (i+j >= len) break;
DEBUG(4, ("%c", x)); DEBUG(4, ("%c", x));
} }
DEBUG(4, (" hex ", i)); DEBUG(4, (" hex ", i));
for (j = 0; j < 16; j++) for (j = 0; j < 16; j++)
{ {
if (i+j >= len) break; if (i+j >= len) break;
DEBUG(4, (" %02x", (unsigned char)outbuf[i+j])); DEBUG(4, (" %02x", outbuf[i+j]));
} }
DEBUG(4, ("\n")); DEBUG(4, ("\n"));
} }
} }
/***************************************************************************
updates the unique transaction identifier
**************************************************************************/
static void update_name_trn_id(void)
{
if (!name_trn_id)
{
name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
}
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
}
/**************************************************************************** /****************************************************************************
initiate a netbios packet initiate a netbios packet
if we are making queries to samba, then the ip must be zero. in this
instance, the packet is constructed and then dealt with immediately.
netbios packets sent to an ip of zero are dealt with immediately by calling
process_nmb(), in order to allow, for example, querying of samba's WINS
records. at first, this seems like a really dumb thing to do. but then
again, the packet_struct created contains _exactly_ the information
required. the alternative is to take packet_struct out of the loop,
which is a fairly messy operation.
****************************************************************************/ ****************************************************************************/
BOOL initiate_netbios_packet(uint16 id, void initiate_netbios_packet(uint16 *id,
int fd,int quest_type,char *name,int name_type, int fd,int quest_type,char *name,int name_type,
int nb_flags,BOOL bcast,BOOL recurse, int nb_flags,BOOL bcast,BOOL recurse,
struct in_addr to_ip) struct in_addr to_ip)
{ {
struct packet_struct p; struct packet_struct p;
struct nmb_packet *nmb = &p.packet.nmb; struct nmb_packet *nmb = &p.packet.nmb;
struct res_rec additional_rec; struct res_rec additional_rec;
char *pkt_type = "unknown"; char *packet_type = "unknown";
int opcode = -1; int opcode = -1;
if (quest_type == NMB_STATUS) { pkt_type = "nmb_status"; opcode = 0; } if (!id) return;
if (quest_type == NMB_QUERY ) { pkt_type = "nmb_query"; opcode = 0; }
if (quest_type == NMB_REG ) { pkt_type = "nmb_reg"; opcode = 5; } if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
if (quest_type == NMB_REG_REFRESH) { pkt_type="nmb_reg_refresh"; opcode=9; } if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
if (quest_type == NMB_REL ) { pkt_type = "nmb_rel"; opcode = 6; } if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
if (quest_type == NMB_REG_REFRESH ) { packet_type = "nmb_reg_refresh"; opcode = 9; }
if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n", DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
pkt_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip))); packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
if (opcode == -1) return False; if (opcode == -1) return;
bzero((char *)&p,sizeof(p)); bzero((char *)&p,sizeof(p));
nmb->header.name_trn_id = id; if (*id == 0xffff) {
update_name_trn_id();
*id = name_trn_id; /* allow resending with same id */
}
nmb->header.name_trn_id = *id;
nmb->header.opcode = opcode; nmb->header.opcode = opcode;
nmb->header.response = False; nmb->header.response = False;
@ -237,7 +162,7 @@ BOOL initiate_netbios_packet(uint16 id,
nmb->additional->rdlength = 6; nmb->additional->rdlength = 6;
nmb->additional->rdata[0] = nb_flags; nmb->additional->rdata[0] = nb_flags;
putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip)); putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
} }
p.ip = to_ip; p.ip = to_ip;
p.port = NMB_PORT; p.port = NMB_PORT;
@ -245,21 +170,12 @@ BOOL initiate_netbios_packet(uint16 id,
p.timestamp = time(NULL); p.timestamp = time(NULL);
p.packet_type = NMB_PACKET; p.packet_type = NMB_PACKET;
if (zero_ip(to_ip)) /* samba's own ip */ if (!send_packet(&p)) {
{ DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
DEBUG(4,("process packet ourselves\n")); *id = 0xffff;
/* respond internally to the packet. */
process_nmb(&p);
} }
else
{ return;
if (!send_packet(&p)) {
DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
return False;
}
}
return True;
} }
@ -267,9 +183,9 @@ BOOL initiate_netbios_packet(uint16 id,
reply to a netbios name packet reply to a netbios name packet
****************************************************************************/ ****************************************************************************/
void reply_netbios_packet(struct packet_struct *p1,int trn_id, void reply_netbios_packet(struct packet_struct *p1,int trn_id,
int rcode, int rcv_code, int opcode, BOOL recurse, int rcode, int rcv_code, int opcode, BOOL recurse,
struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
char *data,int len) char *data,int len)
{ {
struct packet_struct p; struct packet_struct p;
struct nmb_packet *nmb = &p.packet.nmb; struct nmb_packet *nmb = &p.packet.nmb;
@ -282,31 +198,31 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
switch (rcv_code) switch (rcv_code)
{ {
case NMB_STATUS: case NMB_STATUS:
{ {
packet_type = "nmb_status"; packet_type = "nmb_status";
recursion_desired = True; recursion_desired = True;
break; break;
} }
case NMB_QUERY: case NMB_QUERY:
{ {
packet_type = "nmb_query"; packet_type = "nmb_query";
recursion_desired = True; recursion_desired = True;
break; break;
} }
case NMB_REG: case NMB_REG:
{ {
packet_type = "nmb_reg"; packet_type = "nmb_reg";
recursion_desired = True; recursion_desired = True;
break; break;
} }
case NMB_REL: case NMB_REL:
{ {
packet_type = "nmb_rel"; packet_type = "nmb_rel";
recursion_desired = False; recursion_desired = False;
break; break;
} }
case NMB_WAIT_ACK: case NMB_WAIT_ACK:
{ {
packet_type = "nmb_wack"; packet_type = "nmb_wack";
recursion_desired = False; recursion_desired = False;
break; break;
@ -314,14 +230,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
default: default:
{ {
DEBUG(1,("replying netbios packet: %s %s\n", DEBUG(1,("replying netbios packet: %s %s\n",
packet_type, namestr(rr_name), inet_ntoa(p.ip))); packet_type, namestr(rr_name), inet_ntoa(p.ip)));
return; return;
} }
} }
DEBUG(4,("replying netbios packet: %s %s\n", DEBUG(4,("replying netbios packet: %s %s\n",
packet_type, namestr(rr_name), inet_ntoa(p.ip))); packet_type, namestr(rr_name), inet_ntoa(p.ip)));
nmb->header.name_trn_id = trn_id; nmb->header.name_trn_id = trn_id;
nmb->header.opcode = opcode; nmb->header.opcode = opcode;
@ -349,25 +265,16 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
nmb->answers->ttl = ttl; nmb->answers->ttl = ttl;
if (data && len) if (data && len)
{ {
nmb->answers->rdlength = len; nmb->answers->rdlength = len;
memcpy(nmb->answers->rdata, data, len); memcpy(nmb->answers->rdata, data, len);
} }
p.packet_type = NMB_PACKET; p.packet_type = NMB_PACKET;
debug_nmb_packet(&p); debug_nmb_packet(&p);
if (zero_ip(p.ip)) /* samba's own ip */ send_packet(&p);
{
DEBUG(4,("process response packet ourselves\n"));
/* respond internally to the packet. */
process_nmb(&p);
}
else
{
send_packet(&p);
}
} }
@ -445,7 +352,7 @@ static void process_dgram(struct packet_struct *p)
buf = &dgram->data[0]; buf = &dgram->data[0];
buf -= 4; /* XXXX for the pseudo tcp length - buf -= 4; /* XXXX for the pseudo tcp length -
someday I need to get rid of this */ someday I need to get rid of this */
if (CVAL(buf,smb_com) != SMBtrans) return; if (CVAL(buf,smb_com) != SMBtrans) return;
@ -453,8 +360,8 @@ static void process_dgram(struct packet_struct *p)
buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n", DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
namestr(&dgram->source_name),namestr(&dgram->dest_name), namestr(&dgram->source_name),namestr(&dgram->dest_name),
smb_buf(buf),CVAL(buf2,0),len)); smb_buf(buf),CVAL(buf2,0),len));
if (len <= 0) return; if (len <= 0) return;
@ -472,6 +379,83 @@ static void process_dgram(struct packet_struct *p)
} }
} }
/****************************************************************************
process a nmb packet
****************************************************************************/
static void process_nmb(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
debug_nmb_packet(p);
switch (nmb->header.opcode)
{
case 8: /* what is this?? */
case NMB_REG:
case NMB_REG_REFRESH:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
if (nmb->header.response)
response_netbios_packet(p); /* response to registration dealt
with here */
else
reply_name_reg(p);
break;
}
case 0:
{
if (nmb->header.response)
{
switch (nmb->question.question_type)
{
case 0x0:
{
response_netbios_packet(p);
break;
}
}
return;
}
else if (nmb->header.qdcount>0)
{
switch (nmb->question.question_type)
{
case NMB_QUERY:
{
reply_name_query(p);
break;
}
case NMB_STATUS:
{
reply_name_status(p);
break;
}
}
return;
}
break;
}
case NMB_REL:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0)
{
DEBUG(2,("netbios release packet rejected\n"));
break;
}
if (nmb->header.response)
response_netbios_packet(p); /* response to reply dealt with
in here */
else
reply_name_release(p);
break;
}
}
}
/******************************************************************* /*******************************************************************
run elements off the packet queue till its empty run elements off the packet queue till its empty
******************************************************************/ ******************************************************************/
@ -482,15 +466,15 @@ void run_packet_queue()
while ((p=packet_queue)) while ((p=packet_queue))
{ {
switch (p->packet_type) switch (p->packet_type)
{ {
case NMB_PACKET: case NMB_PACKET:
process_nmb(p); process_nmb(p);
break; break;
case DGRAM_PACKET: case DGRAM_PACKET:
process_dgram(p); process_dgram(p);
break; break;
} }
packet_queue = packet_queue->next; packet_queue = packet_queue->next;
if (packet_queue) packet_queue->prev = NULL; if (packet_queue) packet_queue->prev = NULL;
@ -566,8 +550,8 @@ try_again:
wrong things to do! I should send to the requestors port. XXX wrong things to do! I should send to the requestors port. XXX
**************************************************************************/ **************************************************************************/
BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
char *dstname,int src_type,int dest_type, char *dstname,int src_type,int dest_type,
struct in_addr dest_ip,struct in_addr src_ip) struct in_addr dest_ip,struct in_addr src_ip)
{ {
struct packet_struct p; struct packet_struct p;
struct dgram_packet *dgram = &p.packet.dgram; struct dgram_packet *dgram = &p.packet.dgram;

View File

@ -35,30 +35,15 @@ extern pstring scope;
extern struct in_addr ipzero; extern struct in_addr ipzero;
extern struct in_addr ipgrp; extern struct in_addr ipgrp;
uint16 name_trn_id=0;
/***************************************************************************
updates the unique transaction identifier
**************************************************************************/
void update_name_trn_id(void)
{
if (!name_trn_id)
{
name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
}
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
}
/*************************************************************************** /***************************************************************************
deals with an entry before it dies deals with an entry before it dies
**************************************************************************/ **************************************************************************/
static void dead_netbios_entry(struct subnet_record *d, static void dead_netbios_entry(struct subnet_record *d,
struct response_record *n) struct response_record *n)
{ {
DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n", DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
debug_state_type(n->state); debug_state_type(n->state);
@ -66,118 +51,118 @@ static void dead_netbios_entry(struct subnet_record *d,
{ {
case NAME_QUERY_CONFIRM: case NAME_QUERY_CONFIRM:
{ {
if (!lp_wins_support()) return; /* only if we're a WINS server */ if (!lp_wins_support()) return; /* only if we're a WINS server */
if (n->num_msgs == 0) if (n->num_msgs == 0)
{ {
/* oops. name query had no response. check that the name is /* oops. name query had no response. check that the name is
unique and then remove it from our WINS database */ unique and then remove it from our WINS database */
/* IMPORTANT: see query_refresh_names() */ /* IMPORTANT: see query_refresh_names() */
if ((!NAME_GROUP(n->reply.nb_flags))) if ((!NAME_GROUP(n->nb_flags)))
{ {
struct subnet_record *d1 = find_subnet(ipgrp); struct subnet_record *d1 = find_subnet(ipgrp);
if (d1) if (d1)
{ {
/* remove the name that had been registered with us, /* remove the name that had been registered with us,
and we're now getting no response when challenging. and we're now getting no response when challenging.
see rfc1001.txt 15.5.2 see rfc1001.txt 15.5.2
*/ */
remove_netbios_name(d1, n->name.name, n->name.name_type, remove_netbios_name(d1, n->name.name, n->name.name_type,
REGISTER, n->send_ip); REGISTER, n->send_ip);
} }
} }
} }
break; break;
} }
case NAME_QUERY_MST_CHK: case NAME_QUERY_MST_CHK:
{ {
/* if no response received, the master browser must have gone /* if no response received, the master browser must have gone
down on that subnet, without telling anyone. */ down on that subnet, without telling anyone. */
/* IMPORTANT: see response_netbios_packet() */ /* IMPORTANT: see response_netbios_packet() */
if (n->num_msgs == 0) if (n->num_msgs == 0)
browser_gone(n->name.name, n->send_ip); browser_gone(n->name.name, n->send_ip);
break; break;
} }
case NAME_RELEASE: case NAME_RELEASE:
{ {
/* if no response received, it must be OK for us to release the /* if no response received, it must be OK for us to release the
name. nobody objected (including a potentially dead or deaf name. nobody objected (including a potentially dead or deaf
WINS server) */ WINS server) */
/* IMPORTANT: see response_name_release() */ /* IMPORTANT: see response_name_release() */
if (ismyip(n->send_ip)) if (ismyip(n->send_ip))
{ {
name_unregister_work(d,n->name.name,n->name.name_type); name_unregister_work(d,n->name.name,n->name.name_type);
} }
if (!n->bcast) if (!n->bcast)
{ {
DEBUG(0,("WINS server did not respond to name release!\n")); DEBUG(0,("WINS server did not respond to name release!\n"));
/* XXXX whoops. we have problems. must deal with this */ /* XXXX whoops. we have problems. must deal with this */
} }
break; break;
} }
case NAME_REGISTER_CHALLENGE: case NAME_REGISTER_CHALLENGE:
{ {
/* name challenge: no reply. we can reply to the person that /* name challenge: no reply. we can reply to the person that
wanted the unique name and tell them that they can have it wanted the unique name and tell them that they can have it
*/ */
add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name,
n->reply.nb_flags, GET_TTL(0), n->nb_flags, GET_TTL(0),
n->reply.ip, False, n->reply.ip); n->reply_to_ip, False, n->reply_to_ip);
if (!n->bcast) if (!n->bcast)
{ {
DEBUG(1,("WINS server did not respond to name registration!\n")); DEBUG(1,("WINS server did not respond to name registration!\n"));
/* XXXX whoops. we have problems. must deal with this */ /* XXXX whoops. we have problems. must deal with this */
} }
break; break;
} }
case NAME_REGISTER: case NAME_REGISTER:
{ {
/* if no response received, and we are using a broadcast registration /* if no response received, and we are using a broadcast registration
method, it must be OK for us to register the name: nobody objected method, it must be OK for us to register the name: nobody objected
on that subnet. if we are using a WINS server, then the WINS on that subnet. if we are using a WINS server, then the WINS
server must be dead or deaf. server must be dead or deaf.
*/ */
if (n->bcast) if (n->bcast)
{ {
/* broadcast method: implicit acceptance of the name registration /* broadcast method: implicit acceptance of the name registration
by not receiving any objections. */ by not receiving any objections. */
/* IMPORTANT: see response_name_reg() */ /* IMPORTANT: see response_name_reg() */
name_register_work(d,n->token,n->name.name,n->name.name_type, name_register_work(d,n->name.name,n->name.name_type,
n->source, &n->reply, n->ttl, n->reply.ip, n->bcast); n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
} }
else else
{ {
/* received no response. rfc1001.txt states that after retrying, /* received no response. rfc1001.txt states that after retrying,
we should assume the WINS server is dead, and fall back to we should assume the WINS server is dead, and fall back to
broadcasting (see bits about M nodes: can't find any right broadcasting (see bits about M nodes: can't find any right
now) */ now) */
DEBUG(1,("WINS server did not respond to name registration!\n")); DEBUG(1,("WINS server did not respond to name registration!\n"));
/* XXXX whoops. we have problems. must deal with this */ /* XXXX whoops. we have problems. must deal with this */
} }
break; break;
} }
default: default:
{ {
/* nothing to do but delete the dead expected-response structure */ /* nothing to do but delete the dead expected-response structure */
/* this is normal. */ /* this is normal. */
break; break;
} }
} }
} }
@ -199,52 +184,81 @@ void expire_netbios_response_entries()
for (n = d->responselist; n; n = nextn) for (n = d->responselist; n; n = nextn)
{ {
nextn = n->next; nextn = n->next;
if (n->repeat_time <= time(NULL)) if (n->repeat_time <= time(NULL))
{ {
if (n->repeat_count > 0) if (n->repeat_count > 0)
{ {
/* resend the entry */ /* resend the entry */
initiate_netbios_packet(n->response_id, n->fd, n->quest_type, initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
n->name.name, n->name.name_type, n->name.name, n->name.name_type,
n->reply.nb_flags, n->bcast, n->recurse, n->send_ip); n->nb_flags, n->bcast, n->recurse, n->send_ip);
n->repeat_time += n->repeat_interval; /* XXXX ms needed */ n->repeat_time += n->repeat_interval; /* XXXX ms needed */
n->repeat_count--; n->repeat_count--;
} }
else else
{ {
DEBUG(4,("timeout response %d for %s %s\n", DEBUG(4,("timeout response %d for %s %s\n",
n->response_id, namestr(&n->name), n->response_id, namestr(&n->name),
inet_ntoa(n->send_ip))); inet_ntoa(n->send_ip)));
dead_netbios_entry (d,n); /* process the non-response */ dead_netbios_entry (d,n); /* process the non-response */
remove_response_record(d,n); /* remove the non-response */ remove_response_record(d,n); /* remove the non-response */
continue; continue;
} }
} }
} }
} }
} }
/**************************************************************************** /****************************************************************************
wrapper function to override a broadcast message and send it to the WINS
name server instead, if it exists. if wins is false, and there has been no
WINS server specified, the packet will NOT be sent.
****************************************************************************/ ****************************************************************************/
void queue_netbios_pkt_wins(struct subnet_record *d, struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum state_type state, int fd,int quest_type,enum state_type state,
int token, char *name,int name_type, char *name,int name_type,int nb_flags, time_t ttl,
enum name_source source, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment,
int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse,
BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip)
struct in_addr send_ip, struct in_addr reply_to_ip)
{ {
queue_netbios_packet(d,fd, quest_type, state, /* XXXX note: please see rfc1001.txt section 10 for details on this
token, name, name_type, source, nb_flags, ttl, function: it is currently inappropriate to use this - it will do
for now - once there is a clarification of B, M and P nodes and
which one samba is supposed to be
*/
if ((!lp_wins_support()) && (*lp_wins_server()))
{
/* samba is not a WINS server, and we are using a WINS server */
struct in_addr wins_ip;
wins_ip = *interpret_addr2(lp_wins_server());
if (!zero_ip(wins_ip))
{
bcast = False;
send_ip = wins_ip;
}
else
{
/* oops. smb.conf's wins server parameter MUST be a host_name
or an ip_address. */
DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
}
}
if (zero_ip(send_ip)) return NULL;
return queue_netbios_packet(d,fd, quest_type, state,
name, name_type, nb_flags, ttl,
server_type,my_name,my_comment, server_type,my_name,my_comment,
bcast, recurse, send_ip, reply_to_ip); bcast, recurse, send_ip, reply_to_ip);
} }
@ -253,83 +267,36 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
this is intended to be used (not exclusively) for broadcasting to this is intended to be used (not exclusively) for broadcasting to
master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
complete lists across a wide area network complete lists across a wide area network
a broadcast message will be over-ridden if the packet it sent to an
ip of zero, and the packet will be sent to the WINS name server instead,
if it exists. if samba is configured to be a WINS server, then the
packet will be dealt with _as if_ it had been sent on the network,
but in fact the function process_nmb() is called.
****************************************************************************/ ****************************************************************************/
void queue_netbios_packet(struct subnet_record *d, struct response_record *queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum state_type state, int fd,int quest_type,enum state_type state,char *name,
int token, char *name, int name_type, int name_type,int nb_flags, time_t ttl,
enum name_source source, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment,
int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse,
BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip)
struct in_addr send_ip, struct in_addr reply_to_ip)
{ {
struct in_addr wins_ip = ipgrp;
struct response_record *n; struct response_record *n;
uint16 id = 0xffff;
/* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */ /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
if (ip_equal(send_ip, ipgrp)) return; if (ip_equal(wins_ip, send_ip)) return NULL;
/* XXXX note: please see rfc1001.txt section 10 for details on this initiate_netbios_packet(&id, fd, quest_type, name, name_type,
function: it is currently inappropriate to use this - it will do nb_flags, bcast, recurse, send_ip);
for now - once there is a clarification of B, M and P nodes and
which one samba is supposed to be
*/
if ((!lp_wins_support()) && (*lp_wins_server())) if (id == 0xffff) {
{ DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
/* samba is not a WINS server, and we are using a WINS server */ return NULL;
struct in_addr wins_ip;
wins_ip = *interpret_addr2(lp_wins_server());
if (!zero_ip(wins_ip))
{
bcast = False;
send_ip = wins_ip;
}
else
{
/* oops. smb.conf's wins server parameter MUST be a host_name
or an ip_address. */
DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
}
} }
if (zero_ip(send_ip)) if ((n = make_response_queue_record(state,id,fd,
{ quest_type,name,name_type,nb_flags,ttl,
/* doing a netbios query to samba as a WINS server, internally */ server_type,my_name, my_comment,
if (lp_wins_support()) /* samba is a WINS server */ bcast,recurse,send_ip,reply_to_ip)))
{ {
DEBUG(4,("queue netbios packet with ourselves...\n")); add_response_record(d,n);
bcast = False; return n;
} }
else return NULL;
{
return;
}
}
update_name_trn_id();
/* queue the response expected because if we do a query with an ip
of zero, we are expecting to hear from ourself immediately */
if ((n = make_response_queue_record(state, name_trn_id, fd, quest_type,
token, name, name_type, source, nb_flags, ttl,
server_type, my_name, my_comment,
bcast, recurse, send_ip, reply_to_ip)))
{
add_response_record(d,n);
}
if (!initiate_netbios_packet(name_trn_id, fd, quest_type, name, name_type,
nb_flags, bcast, recurse, send_ip))
{
/* packet wasn't sent - not expecting a response */
DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
remove_response_record(d, n);
return;
}
} }

View File

@ -51,7 +51,7 @@ extern uint16 nb_type; /* samba's NetBIOS type */
XXXX at present, the name is removed _even_ if a WINS server says keep it. XXXX at present, the name is removed _even_ if a WINS server says keep it.
****************************************************************************/ ****************************************************************************/
void remove_name_entry(struct subnet_record *d, int token, char *name,int type) void remove_name_entry(struct subnet_record *d, char *name,int type)
{ {
/* XXXX BUG: if samba is offering WINS support, it should still broadcast /* XXXX BUG: if samba is offering WINS support, it should still broadcast
a de-registration packet to the local subnet before removing the a de-registration packet to the local subnet before removing the
@ -80,18 +80,17 @@ void remove_name_entry(struct subnet_record *d, int token, char *name,int type)
don't really own */ don't really own */
remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip); remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip);
if (ip_equal(d->bcast_ip, ipgrp)) if (ip_equal(d->bcast_ip, ipgrp)) {
{ if (!lp_wins_support()) {
/* use WINS. this function can now be used to _either_ /* not a WINS server: we have to release them on the network */
do the release on samba's own database _or_ release
the name with an arbitrary WINS server */
queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE, queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
token, name, type, SELF, 0, 0,0,NULL,NULL, name, type, 0, 0,0,NULL,NULL,
False, True, ipzero, ipzero); False, True, ipzero, ipzero);
}
} else { } else {
/* local interface: release them on the network */ /* local interface: release them on the network */
queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE, queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
token, name, type, SELF, 0, 0,0,NULL,NULL, name, type, 0, 0,0,NULL,NULL,
True, True, d->bcast_ip, d->bcast_ip); True, True, d->bcast_ip, d->bcast_ip);
} }
} }
@ -104,8 +103,7 @@ void remove_name_entry(struct subnet_record *d, int token, char *name,int type)
it's just a matter of when this will be done (e.g after a time-out). it's just a matter of when this will be done (e.g after a time-out).
****************************************************************************/ ****************************************************************************/
void add_my_name_entry(struct subnet_record *d, int token, void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
char *name,int type,int nb_flags)
{ {
BOOL re_reg = False; BOOL re_reg = False;
struct nmb_name n; struct nmb_name n;
@ -117,7 +115,7 @@ void add_my_name_entry(struct subnet_record *d, int token,
make_nmb_name(&n, name, type, scope); make_nmb_name(&n, name, type, scope);
if (find_name(d->namelist, &n, SELF)) if (find_name(d->namelist, &n, SELF))
re_reg = True; re_reg = True;
/* XXXX BUG: if samba is offering WINS support, it should still add the /* XXXX BUG: if samba is offering WINS support, it should still add the
name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28 name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
@ -125,7 +123,6 @@ void add_my_name_entry(struct subnet_record *d, int token,
if (ip_equal(d->bcast_ip, ipgrp)) if (ip_equal(d->bcast_ip, ipgrp))
{ {
#if 0
if (lp_wins_support()) if (lp_wins_support())
{ {
/* we are a WINS server. */ /* we are a WINS server. */
@ -134,38 +131,26 @@ void add_my_name_entry(struct subnet_record *d, int token,
actually be true actually be true
*/ */
struct nmb_ip data;
data.nb_flags = nb_flags;
putip(&data.ip, ipzero);
DEBUG(4,("samba as WINS server adding: ")); DEBUG(4,("samba as WINS server adding: "));
/* this will call add_netbios_entry() */ /* this will call add_netbios_entry() */
name_register_work(d, name, type, nb_flags,0, ipzero, False);
name_register_work(d,token,name,type,SELF,&data,GET_TTL(0),ipzero,False);
} }
else else
{ {
#endif
/* ipzero when not using an arbitrary wins server results in the
netbios packet being short-circuited to process_nmb()
*/
/* a time-to-live allows us to refresh this name with the WINS server. */ /* a time-to-live allows us to refresh this name with the WINS server. */
queue_netbios_pkt_wins(d,ClientNMB, queue_netbios_pkt_wins(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL, name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
False, True, ipzero, ipzero); False, True, ipzero, ipzero);
#if 0
} }
#endif
} }
else else
{ {
/* broadcast the packet, but it comes from ipzero */ /* broadcast the packet, but it comes from ipzero */
queue_netbios_packet(d,ClientNMB, queue_netbios_packet(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL, name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
True, True, d->bcast_ip, ipzero); True, True, d->bcast_ip, ipzero);
} }
} }
@ -176,8 +161,6 @@ void add_my_name_entry(struct subnet_record *d, int token,
void add_my_names(void) void add_my_names(void)
{ {
struct subnet_record *d; struct subnet_record *d;
int token;
/* each subnet entry, including WINS pseudo-subnet, has SELF names */ /* each subnet entry, including WINS pseudo-subnet, has SELF names */
/* XXXX if there was a transport layer added to samba (ipx/spx etc) then /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
@ -186,56 +169,32 @@ void add_my_names(void)
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
BOOL wins = ip_equal(d->bcast_ip,ipgrp); BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp);
for (token = 0; token < get_num_workgroups(); token++)
{
char *my_name = conf_browsing_alias(token);
char *wg_name = conf_workgroup_name(token);
if (my_name)
{
add_my_name_entry(d, token, my_name,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x03,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x00,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x1f,nb_type|NB_ACTIVE);
}
if (wg_name && conf_should_domain_logon(token))
{
/* the 0x1c is to do with domain logons */
add_my_name_entry(d, token, wg_name,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
}
}
add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
/* these names are added permanently (ttl of zero) and will NOT be /* these names are added permanently (ttl of zero) and will NOT be
refreshed with the WINS server */ refreshed with the WINS server */
add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
if (lp_domain_logons()) {
/* XXXX the 0x1c is apparently something to do with domain logons */
add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
}
} }
if (lp_domain_master() && (d = find_subnet(ipgrp)))
/* check becoming a domain master under all browser aliases */
if ((d = find_subnet(ipgrp)))
{ {
for (token = 0; token < get_num_workgroups(); token++) struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True);
if (work && work->state == MST_NONE)
{ {
if (conf_should_domain_master(token)) work->state = MST_DOMAIN_NONE;
{ become_master(d, work);
char *work_name = conf_workgroup_name(token);
if (work_name)
{
struct work_record *work = find_workgroupstruct(d,work_name,True);
if (work && work->state == MST_NONE)
{
work->state = MST_DOMAIN_NONE;
become_master(d, work);
}
}
}
} }
} }
} }
@ -246,24 +205,52 @@ void add_my_names(void)
**************************************************************************/ **************************************************************************/
void remove_my_names() void remove_my_names()
{ {
struct subnet_record *d; struct subnet_record *d;
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{
struct name_record *n, *next;
for (n = d->namelist; n; n = next)
{
next = n->next;
if (n->source == SELF)
{
/* get all SELF names removed from the WINS server's database */
/* XXXX note: problem occurs if this removes the wrong one! */
remove_name_entry(d,n->name.name, n->name.name_type);
}
}
}
}
/*******************************************************************
refresh my own names
******************************************************************/
void refresh_my_names(time_t t)
{
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{
struct name_record *n;
for (n = d->namelist; n; n = n->next)
{ {
struct name_record *n, *next; /* each SELF name has an individual time to be refreshed */
if (n->source == SELF && n->refresh_time < time(NULL) &&
for (n = d->namelist; n; n = next) n->death_time != 0)
{ {
next = n->next; add_my_name_entry(d,n->name.name,n->name.name_type,
if (n->source == SELF) n->ip_flgs[0].nb_flags);
{ /* they get a new lease on life :-) */
/* get all SELF names removed from the WINS server's database */ n->death_time += GET_TTL(0);
/* XXXX note: problem occurs if this removes the wrong one! */ n->refresh_time += GET_TTL(0);
}
remove_name_entry(d, -1, n->name.name, n->name.name_type);
}
}
} }
}
} }
@ -278,55 +265,55 @@ void remove_my_names()
******************************************************************/ ******************************************************************/
void query_refresh_names(void) void query_refresh_names(void)
{ {
struct name_record *n; struct name_record *n;
struct subnet_record *d = find_subnet(ipgrp); struct subnet_record *d = find_subnet(ipgrp);
static time_t lasttime = 0; static time_t lasttime = 0;
time_t t = time(NULL); time_t t = time(NULL);
int count = 0; int count = 0;
int name_refresh_time = NAME_POLL_REFRESH_TIME; int name_refresh_time = NAME_POLL_REFRESH_TIME;
int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
if (max_count > 10) max_count = 10; if (max_count > 10) max_count = 10;
name_refresh_time = NAME_POLL_INTERVAL * max_count / 2; name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
/* if (!lp_poll_wins()) return; polling of registered names allowed */ /* if (!lp_poll_wins()) return; polling of registered names allowed */
if (!d) return; if (!d) return;
if (!lasttime) lasttime = t; if (!lasttime) lasttime = t;
if (t - lasttime < NAME_POLL_INTERVAL) return; if (t - lasttime < NAME_POLL_INTERVAL) return;
lasttime = time(NULL); lasttime = time(NULL);
for (n = d->namelist; n; n = n->next) for (n = d->namelist; n; n = n->next)
{ {
/* only do unique, registered names. */ /* only do unique, registered names */
if (n->source != REGISTER) continue; if (n->source != REGISTER) continue;
if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue;
if (n->refresh_time < t) if (n->refresh_time < t)
{ {
DEBUG(3,("Polling name %s\n", namestr(&n->name))); DEBUG(3,("Polling name %s\n", namestr(&n->name)));
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
-1,n->name.name, n->name.name_type, n->name.name, n->name.name_type,
n->source,0,0,0,NULL,NULL, 0,0,0,NULL,NULL,
False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip);
count++; count++;
} }
if (count >= max_count) if (count >= max_count)
{ {
/* don't do too many of these at once, but do enough to /* don't do too many of these at once, but do enough to
cover everyone in the list */ cover everyone in the list */
return; return;
} }
/* this name will be checked on again, if it's not removed */ /* this name will be checked on again, if it's not removed */
n->refresh_time += name_refresh_time; n->refresh_time += name_refresh_time;
} }
} }

View File

@ -294,8 +294,8 @@ void reply_name_reg(struct packet_struct *p)
/* initiate some enquiries to the current owner. */ /* initiate some enquiries to the current owner. */
queue_netbios_packet(d,ClientNMB,NMB_QUERY, queue_netbios_packet(d,ClientNMB,NMB_QUERY,
NAME_REGISTER_CHALLENGE, NAME_REGISTER_CHALLENGE,
-1,reply_name->name,reply_name->name_type, reply_name->name,reply_name->name_type,
n->source, nb_flags,0,0,NULL,NULL, nb_flags,0,0,NULL,NULL,
False, False, n->ip_flgs[0].ip, p->ip); False, False, n->ip_flgs[0].ip, p->ip);
} }
else else

View File

@ -46,29 +46,38 @@ extern struct in_addr ipzero;
response for a reg release received. samba has asked a WINS server if it response for a reg release received. samba has asked a WINS server if it
could release a name. could release a name.
**************************************************************************/ **************************************************************************/
static void response_name_release(struct nmb_ip *data, struct nmb_name *name, static void response_name_release(struct subnet_record *d,
struct subnet_record *d) struct packet_struct *p)
{ {
struct nmb_packet *nmb = &p->packet.nmb;
char *name = nmb->question.question_name.name;
int type = nmb->question.question_name.name_type;
DEBUG(4,("response name release received\n")); DEBUG(4,("response name release received\n"));
if (data) if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
/* IMPORTANT: see expire_netbios_response_entries() */ /* IMPORTANT: see expire_netbios_response_entries() */
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
/* NOTE: we only release our own names at present */ /* NOTE: we only release our own names at present */
if (ismyip(data->ip)) if (ismyip(found_ip))
{ {
name_unregister_work(d, name->name, name->name_type); name_unregister_work(d,name,type);
} }
else else
{ {
DEBUG(2,("name release for different ip! %s %s\n", DEBUG(2,("name release for different ip! %s %s\n",
inet_ntoa(data->ip),namestr(name))); inet_ntoa(found_ip),
namestr(&nmb->question.question_name)));
} }
} }
else else
{ {
DEBUG(2,("name release for %s rejected!\n",namestr(name))); DEBUG(2,("name release for %s rejected!\n",
namestr(&nmb->question.question_name)));
/* XXXX PANIC! what to do if it's one of samba's own names? */ /* XXXX PANIC! what to do if it's one of samba's own names? */
@ -82,25 +91,34 @@ static void response_name_release(struct nmb_ip *data, struct nmb_name *name,
/**************************************************************************** /****************************************************************************
response for a reg request received response for a reg request received
**************************************************************************/ **************************************************************************/
static void response_name_reg(struct nmb_ip *data, struct nmb_name *name, static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
time_t ttl, BOOL bcast, struct in_addr source_ip,
struct subnet_record *d, enum name_source source, int token)
{ {
struct nmb_packet *nmb = &p->packet.nmb;
char *name = nmb->question.question_name.name;
int type = nmb->question.question_name.name_type;
BOOL bcast = nmb->header.nm_flags.bcast;
DEBUG(4,("response name registration received!\n")); DEBUG(4,("response name registration received!\n"));
if (data) if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
/* IMPORTANT: see expire_netbios_response_entries() */ /* IMPORTANT: see expire_netbios_response_entries() */
name_register_work(d, token, name->name,name->name_type, int nb_flags = nmb->answers->rdata[0];
source, data, ttl, source_ip, bcast); int ttl = nmb->answers->ttl;
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
} }
else else
{ {
DEBUG(1,("name registration for %s rejected!\n", namestr(name))); DEBUG(1,("name registration for %s rejected!\n",
namestr(&nmb->question.question_name)));
/* oh dear. we have problems. possibly unbecome a master browser. */ /* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work(d,name->name,name->name_type); name_unregister_work(d,name,type);
} }
} }
@ -109,56 +127,58 @@ static void response_name_reg(struct nmb_ip *data, struct nmb_name *name,
response from a name query announce host response from a name query announce host
NAME_QUERY_ANNOUNCE_HOST is dealt with here NAME_QUERY_ANNOUNCE_HOST is dealt with here
****************************************************************************/ ****************************************************************************/
static void response_announce_host(struct nmb_ip *data, static void response_announce_host(struct nmb_name *ans_name,
struct nmb_name *ans_name, struct nmb_packet *nmb,
struct response_record *n, struct subnet_record *d) struct response_record *n, struct subnet_record *d)
{ {
DEBUG(4, ("Name query at %s ip %s - ", DEBUG(4, ("Name query at %s ip %s - ",
namestr(&n->name), inet_ntoa(n->send_ip))); namestr(&n->name), inet_ntoa(n->send_ip)));
if (!name_equal(&n->name, ans_name)) if (!name_equal(&n->name, ans_name))
{
/* someone gave us the wrong name as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
/* someone gave us the wrong name as a reply. oops. */ /* we had sent out a name query to the current owner
/* XXXX should say to them 'oi! release that name!' */ of a name because someone else wanted it. now they
have responded saying that they still want the name,
so the other host can't have it.
*/
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); /* first check all the details are correct */
return;
}
if (data) int nb_flags = nmb->answers->rdata[0];
{ struct in_addr found_ip;
/* we had sent out a name query to the current owner
of a name because someone else wanted it. now they
have responded saying that they still want the name,
so the other host can't have it.
*/
/* first check all the details are correct */ putip((char*)&found_ip,&nmb->answers->rdata[2]);
if (data->nb_flags != n->reply.nb_flags) if (nb_flags != n->nb_flags)
{ {
/* someone gave us the wrong nb_flags as a reply. oops. */ /* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */ /* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags)); DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags)); DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
return; return;
} }
/* do an announce host */ /* do an announce host */
do_announce_host(ANN_HostAnnouncement, do_announce_host(ANN_HostAnnouncement,
n->my_name , 0x00, d->myip, n->my_name , 0x00, d->myip,
n->name.name, 0x1d, data->ip, n->name.name, 0x1d, found_ip,
n->ttl, n->ttl,
n->my_name, n->server_type, n->my_name, n->server_type, n->my_comment);
HOST_MAJOR_VERSION, HOST_MINOR_VERSION, }
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE, else
n->my_comment); {
} /* XXXX negative name query response. no master exists. oops */
else }
{
/* XXXX negative name query response. no master exists. oops */
}
} }
@ -167,18 +187,18 @@ static void response_announce_host(struct nmb_ip *data,
NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here. NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
****************************************************************************/ ****************************************************************************/
static void response_server_check(struct nmb_name *ans_name, static void response_server_check(struct nmb_name *ans_name,
struct response_record *n, struct subnet_record *d) struct response_record *n, struct subnet_record *d)
{ {
/* issue another state: this time to do a name status check */ /* issue another state: this time to do a name status check */
enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ? enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK;
/* initiate a name status check on the server that replied */ /* initiate a name status check on the server that replied */
queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
-1,ans_name->name, ans_name->name_type, ans_name->name, ans_name->name_type,
0,0,0,0,NULL,NULL, 0,0,0,NULL,NULL,
False,False,n->send_ip,n->reply.ip); False,False,n->send_ip,n->reply_to_ip);
} }
@ -188,8 +208,8 @@ static void response_server_check(struct nmb_name *ans_name,
add all the names it finds into the namelist. add all the names it finds into the namelist.
****************************************************************************/ ****************************************************************************/
static BOOL interpret_node_status(struct subnet_record *d, static BOOL interpret_node_status(struct subnet_record *d,
char *p, struct nmb_name *name,int t, char *p, struct nmb_name *name,int t,
char *serv_name, struct in_addr ip, BOOL bcast) char *serv_name, struct in_addr ip, BOOL bcast)
{ {
int level = t==0x20 ? 4 : 0; int level = t==0x20 ? 4 : 0;
int numnames = CVAL(p,0); int numnames = CVAL(p,0);
@ -232,44 +252,44 @@ static BOOL interpret_node_status(struct subnet_record *d,
/* might as well update our namelist while we're at it */ /* might as well update our namelist while we're at it */
if (add) if (add)
{ {
struct in_addr nameip; struct in_addr nameip;
enum name_source src; enum name_source src;
if (ismyip(ip)) { if (ismyip(ip)) {
nameip = ipzero; nameip = ipzero;
src = SELF; src = SELF;
} else { } else {
nameip = ip; nameip = ip;
src = STATUS_QUERY; src = STATUS_QUERY;
} }
add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
} }
/* we want the server name */ /* we want the server name */
if (serv_name && !*serv_name && !group && t == 0) if (serv_name && !*serv_name && !group && t == 0)
{ {
StrnCpy(serv_name,qname,15); StrnCpy(serv_name,qname,15);
serv_name[15] = 0; serv_name[15] = 0;
} }
/* looking for a name and type? */ /* looking for a name and type? */
if (name && !found && (t == type)) if (name && !found && (t == type))
{ {
/* take a guess at some of the name types we're going to ask for. /* take a guess at some of the name types we're going to ask for.
evaluate whether they are group names or no... */ evaluate whether they are group names or no... */
if (((t == 0x1b || t == 0x1d ) && !group) || if (((t == 0x1b || t == 0x1d ) && !group) ||
((t == 0x20 || t == 0x1c || t == 0x1e) && group)) ((t == 0x20 || t == 0x1c || t == 0x1e) && group))
{ {
found = True; found = True;
make_nmb_name(name,qname,type,scope); make_nmb_name(name,qname,type,scope);
} }
} }
DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags)); DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
} }
DEBUG(level,("num_good_sends=%d num_good_receives=%d\n", DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
IVAL(p,20),IVAL(p,24))); IVAL(p,20),IVAL(p,24)));
return found; return found;
} }
@ -279,26 +299,28 @@ static BOOL interpret_node_status(struct subnet_record *d,
and NAME_STATUS_SRV_CHK dealt with here. and NAME_STATUS_SRV_CHK dealt with here.
****************************************************************************/ ****************************************************************************/
static void response_name_status_check(struct in_addr ip, static void response_name_status_check(struct in_addr ip,
char *data, BOOL bcast, struct nmb_packet *nmb, BOOL bcast,
struct response_record *n, struct subnet_record *d) struct response_record *n, struct subnet_record *d)
{ {
/* NMB_STATUS arrives: contains workgroup name and server name required. /* NMB_STATUS arrives: contains workgroup name and server name required.
amongst other things. */ amongst other things. */
struct nmb_name name; struct nmb_name name;
fstring serv_name; fstring serv_name;
if (interpret_node_status(d,data,&name,name.name_type,serv_name,ip,bcast)) if (interpret_node_status(d,nmb->answers->rdata,
{ &name,name.name_type,serv_name,ip,bcast))
if (*serv_name) {
{ if (*serv_name)
sync_server(n->state,serv_name,name.name,name.name_type,n->send_ip); {
} sync_server(n->state,serv_name,
} name.name,name.name_type, n->send_ip);
else }
{ }
DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); else
} {
DEBUG(1,("No 0x1d name type in interpret_node_status()\n"));
}
} }
@ -306,74 +328,79 @@ static void response_name_status_check(struct in_addr ip,
response from a name query for secured WINS registration. a state of response from a name query for secured WINS registration. a state of
NAME_REGISTER_CHALLENGE is dealt with here. NAME_REGISTER_CHALLENGE is dealt with here.
****************************************************************************/ ****************************************************************************/
static void response_name_query_register(struct nmb_ip *data, static void response_name_query_register(struct nmb_packet *nmb,
struct nmb_name *ans_name, struct nmb_name *ans_name,
struct response_record *n, struct subnet_record *d) struct response_record *n, struct subnet_record *d)
{ {
struct in_addr register_ip; struct in_addr register_ip;
BOOL new_owner; BOOL new_owner;
DEBUG(4, ("Name query at %s ip %s - ", DEBUG(4, ("Name query at %s ip %s - ",
namestr(&n->name), inet_ntoa(n->send_ip))); namestr(&n->name), inet_ntoa(n->send_ip)));
if (!name_equal(&n->name, ans_name)) if (!name_equal(&n->name, ans_name))
{
/* someone gave us the wrong name as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
/* someone gave us the wrong name as a reply. oops. */ /* we had sent out a name query to the current owner
/* XXXX should say to them 'oi! release that name!' */ of a name because someone else wanted it. now they
have responded saying that they still want the name,
so the other host can't have it.
*/
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); /* first check all the details are correct */
return;
}
if (data) int nb_flags = nmb->answers->rdata[0];
{ struct in_addr found_ip;
/* we had sent out a name query to the current owner
of a name because someone else wanted it. now they
have responded saying that they still want the name,
so the other host can't have it.
*/
/* first check all the details are correct */ putip((char*)&found_ip,&nmb->answers->rdata[2]);
if (data->nb_flags != n->reply.nb_flags) if (nb_flags != n->nb_flags)
{ {
/* someone gave us the wrong nb_flags as a reply. oops. */ /* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */ /* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags)); DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags)); DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
return; return;
} }
if (!ip_equal(n->send_ip, data->ip)) if (!ip_equal(n->send_ip, found_ip))
{ {
/* someone gave us the wrong ip as a reply. oops. */ /* someone gave us the wrong ip as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */ /* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(data->ip))); DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
return; return;
} }
DEBUG(4, (" OK: %s\n", inet_ntoa(data->ip))); DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
/* fine: now tell the other host they can't have the name */ /* fine: now tell the other host they can't have the name */
register_ip = n->send_ip; register_ip = n->send_ip;
new_owner = False; new_owner = False;
} }
else else
{ {
DEBUG(4, (" NEGATIVE RESPONSE!\n")); DEBUG(4, (" NEGATIVE RESPONSE!\n"));
/* the owner didn't want the name: the other host can have it */ /* the owner didn't want the name: the other host can have it */
register_ip = n->reply.ip; register_ip = n->reply_to_ip;
new_owner = True; new_owner = True;
} }
/* register the old or the new owners' ip */ /* register the old or the new owners' ip */
add_name_respond(d, n->fd, d->myip, n->response_id,&n->name, add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags,
n->reply.nb_flags, GET_TTL(0), register_ip, GET_TTL(0), register_ip,
new_owner, n->reply.ip); new_owner, n->reply_to_ip);
} }
@ -381,68 +408,73 @@ static void response_name_query_register(struct nmb_ip *data,
response from a name query to sync browse lists or to update our netbios response from a name query to sync browse lists or to update our netbios
entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
****************************************************************************/ ****************************************************************************/
static void response_name_query_sync(struct nmb_ip *data, static void response_name_query_sync(struct nmb_packet *nmb,
struct nmb_name *ans_name, BOOL bcast, struct nmb_name *ans_name, BOOL bcast,
struct response_record *n, struct subnet_record *d) struct response_record *n, struct subnet_record *d)
{ {
DEBUG(4, ("Name query at %s ip %s - ", DEBUG(4, ("Name query at %s ip %s - ",
namestr(&n->name), inet_ntoa(n->send_ip))); namestr(&n->name), inet_ntoa(n->send_ip)));
if (!name_equal(&n->name, ans_name)) if (!name_equal(&n->name, ans_name))
{
/* someone gave us the wrong name as a reply. oops. */
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
/* someone gave us the wrong name as a reply. oops. */ int nb_flags = nmb->answers->rdata[0];
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); struct in_addr found_ip;
return;
}
if (data) putip((char*)&found_ip,&nmb->answers->rdata[2]);
{
if (!ip_equal(n->send_ip, data->ip))
{
/* someone gave us the wrong ip as a reply. oops. */
DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(data->ip)));
return;
}
DEBUG(4, (" OK: %s\n", inet_ntoa(data->ip))); if (!ip_equal(n->send_ip, found_ip))
{
/* someone gave us the wrong ip as a reply. oops. */
DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
return;
}
if (n->state == NAME_QUERY_SYNC_LOCAL || DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
n->state == NAME_QUERY_SYNC_REMOTE)
{
struct work_record *work = NULL;
if ((work = find_workgroupstruct(d, ans_name->name, False)))
{
BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
/* the server is there: sync quick before it (possibly) dies! */ if (n->state == NAME_QUERY_SYNC_LOCAL ||
sync_browse_lists(d, work, ans_name->name, ans_name->name_type, n->state == NAME_QUERY_SYNC_REMOTE)
data->ip, local_list_only); {
} struct work_record *work = NULL;
} if ((work = find_workgroupstruct(d, ans_name->name, False)))
else {
{ BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
/* update our netbios name list (re-register it if necessary) */
add_netbios_entry(d, ans_name->name, ans_name->name_type,
data->nb_flags,GET_TTL(0),REGISTER,
data->ip,False,!bcast);
}
}
else
{
DEBUG(4, (" NEGATIVE RESPONSE!\n"));
if (n->state == NAME_QUERY_CONFIRM) /* the server is there: sync quick before it (possibly) dies! */
{ sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
/* XXXX remove_netbios_entry()? */ found_ip, local_list_only);
/* lots of things we ought to do, here. if we get here, }
then we're in a mess: our name database doesn't match }
reality. sort it out else
{
/* update our netbios name list (re-register it if necessary) */
add_netbios_entry(d, ans_name->name, ans_name->name_type,
nb_flags,GET_TTL(0),REGISTER,
found_ip,False,!bcast);
}
}
else
{
DEBUG(4, (" NEGATIVE RESPONSE!\n"));
if (n->state == NAME_QUERY_CONFIRM)
{
/* XXXX remove_netbios_entry()? */
/* lots of things we ought to do, here. if we get here,
then we're in a mess: our name database doesn't match
reality. sort it out
*/ */
remove_netbios_name(d,n->name.name, n->name.name_type, remove_netbios_name(d,n->name.name, n->name.name_type,
REGISTER,n->send_ip); REGISTER,n->send_ip);
} }
} }
} }
@ -454,9 +486,9 @@ static void debug_rr_type(int rr_type)
switch (rr_type) switch (rr_type)
{ {
case NMB_STATUS: DEBUG(3,("Name status ")); break; case NMB_STATUS: DEBUG(3,("Name status ")); break;
case NMB_QUERY : DEBUG(3,("Name query ")); break; case NMB_QUERY : DEBUG(3,("Name query ")); break;
case NMB_REG : DEBUG(3,("Name registration ")); break; case NMB_REG : DEBUG(3,("Name registration ")); break;
case NMB_REL : DEBUG(3,("Name release ")); break; case NMB_REL : DEBUG(3,("Name release ")); break;
default : DEBUG(1,("wrong response packet type received")); break; default : DEBUG(1,("wrong response packet type received")); break;
} }
} }
@ -496,7 +528,7 @@ void debug_state_type(int state)
(responses for certain types of operations are only expected from one host) (responses for certain types of operations are only expected from one host)
****************************************************************************/ ****************************************************************************/
static BOOL response_problem_check(struct response_record *n, static BOOL response_problem_check(struct response_record *n,
struct nmb_packet *nmb, char *qname) struct nmb_packet *nmb, char *qname)
{ {
switch (nmb->answers->rr_type) switch (nmb->answers->rr_type)
{ {
@ -524,21 +556,21 @@ static BOOL response_problem_check(struct response_record *n,
{ {
if (n->num_msgs > 1) if (n->num_msgs > 1)
{ {
if (nmb->header.rcode == 0 && nmb->answers->rdata) if (nmb->header.rcode == 0 && nmb->answers->rdata)
{ {
int nb_flags = nmb->answers->rdata[0]; int nb_flags = nmb->answers->rdata[0];
if ((!NAME_GROUP(nb_flags))) if ((!NAME_GROUP(nb_flags)))
{ {
/* oh dear. more than one person responded to a unique name. /* oh dear. more than one person responded to a unique name.
there is either a network problem, a configuration problem there is either a network problem, a configuration problem
or a server is mis-behaving */ or a server is mis-behaving */
/* XXXX mark the name as in conflict, and then let the /* XXXX mark the name as in conflict, and then let the
person who just responded know that they must also mark it person who just responded know that they must also mark it
as in conflict, and therefore must NOT use it. as in conflict, and therefore must NOT use it.
see rfc1001.txt 15.1.3.5 */ see rfc1001.txt 15.1.3.5 */
/* this may cause problems for some early versions of nmbd */ /* this may cause problems for some early versions of nmbd */
switch (n->state) switch (n->state)
@ -548,35 +580,35 @@ static BOOL response_problem_check(struct response_record *n,
/* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */ /* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */
return False; return False;
} }
case NAME_QUERY_ANNOUNCE_HOST: case NAME_QUERY_ANNOUNCE_HOST:
case NAME_QUERY_DOM_SRV_CHK: case NAME_QUERY_DOM_SRV_CHK:
case NAME_QUERY_SRV_CHK: case NAME_QUERY_SRV_CHK:
case NAME_QUERY_MST_CHK: case NAME_QUERY_MST_CHK:
{ {
if (!strequal(qname,n->name.name)) if (!strequal(qname,n->name.name))
{ {
/* one subnet, one master browser per workgroup */ /* one subnet, one master browser per workgroup */
/* XXXX force an election? */ /* XXXX force an election? */
DEBUG(3,("more than one master browser replied!\n")); DEBUG(3,("more than one master browser replied!\n"));
return True; return True;
} }
break; break;
} }
default: break; default: break;
} }
DEBUG(3,("Unique Name conflict detected!\n")); DEBUG(3,("Unique Name conflict detected!\n"));
return True; return True;
} }
} }
else else
{ {
/* we have received a negative reply, having already received /* we have received a negative reply, having already received
at least one response (pos/neg). something's really wrong! */ at least one response (pos/neg). something's really wrong! */
DEBUG(3,("wierd name query problem detected!\n")); DEBUG(3,("wierd name query problem detected!\n"));
return True; return True;
} }
} }
} }
} }
@ -587,30 +619,27 @@ static BOOL response_problem_check(struct response_record *n,
check that the response received is compatible with the response record check that the response received is compatible with the response record
****************************************************************************/ ****************************************************************************/
static BOOL response_compatible(struct response_record *n, static BOOL response_compatible(struct response_record *n,
struct nmb_packet *nmb) struct nmb_packet *nmb)
{ {
switch (n->state) switch (n->state)
{ {
case NAME_RELEASE: case NAME_RELEASE:
{ {
if (nmb->answers->rr_type != NMB_REL) if (nmb->answers->rr_type != NMB_REL)
{ {
DEBUG(1,("Name release reply has wrong answer rr_type\n")); DEBUG(1,("Name release reply has wrong answer rr_type\n"));
return False; return False;
} }
break; break;
} }
case NAME_REGISTER: case NAME_REGISTER:
{ {
/* rfc1002.txt states that nmb->answers->rr_type must equal 0x20 */ if (nmb->answers->rr_type != NMB_REG)
#if 0 {
if (nmb->answers->rr_type != NMB_REG) DEBUG(1,("Name register reply has wrong answer rr_type\n"));
{ return False;
DEBUG(1,("Name register reply has wrong answer rr_type\n")); }
return False;
}
#endif
break; break;
} }
@ -624,29 +653,29 @@ static BOOL response_compatible(struct response_record *n,
case NAME_QUERY_FIND_MST: case NAME_QUERY_FIND_MST:
case NAME_QUERY_MST_CHK: case NAME_QUERY_MST_CHK:
{ {
if (nmb->answers->rr_type != NMB_QUERY) if (nmb->answers->rr_type != NMB_QUERY)
{ {
DEBUG(1,("Name query reply has wrong answer rr_type\n")); DEBUG(1,("Name query reply has wrong answer rr_type\n"));
return False; return False;
} }
break; break;
} }
case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_DOM_SRV_CHK:
case NAME_STATUS_SRV_CHK: case NAME_STATUS_SRV_CHK:
{ {
if (nmb->answers->rr_type != NMB_STATUS) if (nmb->answers->rr_type != NMB_STATUS)
{ {
DEBUG(1,("Name status reply has wrong answer rr_type\n")); DEBUG(1,("Name status reply has wrong answer rr_type\n"));
return False; return False;
} }
break; break;
} }
default: default:
{ {
DEBUG(1,("unknown state type received in response_netbios_packet\n")); DEBUG(1,("unknown state type received in response_netbios_packet\n"));
return False; return False;
} }
} }
return True; return True;
@ -656,62 +685,27 @@ static BOOL response_compatible(struct response_record *n,
/**************************************************************************** /****************************************************************************
process the response packet received process the response packet received
****************************************************************************/ ****************************************************************************/
void response_process(struct in_addr ip, struct subnet_record *d, static void response_process(struct subnet_record *d, struct packet_struct *p,
struct response_record *n, struct response_record *n, struct nmb_packet *nmb,
int rcode, char *nmb_data, struct nmb_name *q_name, BOOL bcast, struct nmb_name *ans_name)
time_t ttl, BOOL bcast, struct nmb_name *ans_name)
{ {
switch (n->state) switch (n->state)
{ {
case NAME_RELEASE: case NAME_RELEASE:
{ {
struct nmb_ip found; response_name_release(d, p);
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_release(data, q_name, d);
break; break;
} }
case NAME_REGISTER: case NAME_REGISTER:
{ {
struct nmb_ip found; response_name_reg(d, p);
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_reg(data,ans_name,ttl,bcast,ip,d,n->source,n->token);
break; break;
} }
case NAME_REGISTER_CHALLENGE: case NAME_REGISTER_CHALLENGE:
{ {
struct nmb_ip found; response_name_query_register(nmb, ans_name, n, d);
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_query_register(data, ans_name, n, d);
break; break;
} }
@ -719,66 +713,44 @@ void response_process(struct in_addr ip, struct subnet_record *d,
case NAME_QUERY_SRV_CHK: case NAME_QUERY_SRV_CHK:
case NAME_QUERY_FIND_MST: case NAME_QUERY_FIND_MST:
{ {
response_server_check(ans_name, n, d); response_server_check(ans_name, n, d);
break; break;
} }
case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_DOM_SRV_CHK:
case NAME_STATUS_SRV_CHK: case NAME_STATUS_SRV_CHK:
{ {
response_name_status_check(ip,nmb_data,bcast,n,d); response_name_status_check(p->ip, nmb, bcast, n, d);
break; break;
} }
case NAME_QUERY_ANNOUNCE_HOST: case NAME_QUERY_ANNOUNCE_HOST:
{ {
struct nmb_ip found; response_announce_host(ans_name, nmb, n, d);
struct nmb_ip *data = NULL; break;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_announce_host(data, ans_name, n, d);
break;
} }
case NAME_QUERY_CONFIRM: case NAME_QUERY_CONFIRM:
case NAME_QUERY_SYNC_LOCAL: case NAME_QUERY_SYNC_LOCAL:
case NAME_QUERY_SYNC_REMOTE: case NAME_QUERY_SYNC_REMOTE:
{ {
struct nmb_ip found; response_name_query_sync(nmb, ans_name, bcast, n, d);
struct nmb_ip *data = NULL; break;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_query_sync(data,ans_name,bcast,n,d);
break;
} }
case NAME_QUERY_MST_CHK: case NAME_QUERY_MST_CHK:
{ {
/* no action required here. it's when NO responses are received /* no action required here. it's when NO responses are received
that we need to do something. see expire_name_query_entries() */ that we need to do something. see expire_name_query_entries() */
DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n",
namestr(&n->name), inet_ntoa(n->send_ip))); namestr(&n->name), inet_ntoa(n->send_ip)));
break; break;
} }
default: default:
{ {
DEBUG(1,("unknown state type received in response_netbios_packet\n")); DEBUG(1,("unknown state type received in response_netbios_packet\n"));
break; break;
} }
} }
} }
@ -808,9 +780,7 @@ void response_netbios_packet(struct packet_struct *p)
return; return;
} }
DEBUG(4,("response packet received: %s %d\n", /* args wrong way round: spotted by ccm@shentel.net */
inet_ntoa(p->ip),n->response_id));
if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */ if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
{ {
DEBUG(2,("response from %s. ", inet_ntoa(p->ip))); DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
@ -822,13 +792,13 @@ void response_netbios_packet(struct packet_struct *p)
{ {
/* hm. the packet received was a response, but with no answer. wierd! */ /* hm. the packet received was a response, but with no answer. wierd! */
DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
inet_ntoa(p->ip), BOOLSTR(bcast))); inet_ntoa(p->ip), BOOLSTR(bcast)));
return; return;
} }
ans_name = &nmb->answers->rr_name; ans_name = &nmb->answers->rr_name;
DEBUG(3,("response for %s from %s (bcast=%s)\n", DEBUG(3,("response for %s from %s (bcast=%s)\n",
namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast)));
debug_rr_type(nmb->answers->rr_type); debug_rr_type(nmb->answers->rr_type);
@ -846,13 +816,7 @@ void response_netbios_packet(struct packet_struct *p)
return; return;
/* now deal with the current state */ /* now deal with the current state */
response_process(p->ip, d, n, response_process(d, p, n, nmb, bcast, ans_name);
nmb->header.rcode,
nmb->answers->rdata,
question,
nmb->answers->ttl, bcast, ans_name);
remove_response_record(d, n);
} }

View File

@ -23,9 +23,6 @@
14 jan 96: lkcl@pires.co.uk 14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -33,34 +30,41 @@
extern int ClientNMB; extern int ClientNMB;
extern int ClientDGRAM; extern int ClientDGRAM;
#define TEST_CODE /* want to debug unknown browse packets */
extern int DEBUGLEVEL; extern int DEBUGLEVEL;
extern pstring scope; extern pstring scope;
extern BOOL CanRecurse; extern BOOL CanRecurse;
extern pstring myname;
extern int ClientNMB; extern int ClientNMB;
extern int ClientDGRAM; extern int ClientDGRAM;
extern struct in_addr ipzero; extern struct in_addr ipzero;
extern int workgroup_count; /* total number of workgroups we know about */
/* this is our domain/workgroup/server database */ /* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist; extern struct subnet_record *subnetlist;
extern int updatecount; extern int updatecount;
/* backup request types: which servers are to be included */
#define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
#define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL )
extern time_t StartupTime; extern time_t StartupTime;
extern BOOL updatedlists; extern BOOL updatedlists;
extern pstring myname;
/**************************************************************************** /****************************************************************************
tell a server to become a backup browser tell a server to become a backup browser
state - 0x01 become backup instead of master state - 0x01 become backup instead of master
- 0x02 remove all entries in browse list and become non-master - 0x02 remove all entries in browse list and become non-master
- 0x04 stop master browser service altogether. NT ignores this - 0x04 stop master browser service altogether. NT ignores this
**************************************************************************/ **************************************************************************/
void reset_server(struct work_record *work, char *name, int state, struct in_addr ip) void reset_server(char *name, int state, struct in_addr ip)
{ {
char outbuf[20]; char outbuf[20];
char *p; char *p;
@ -73,10 +77,10 @@ void reset_server(struct work_record *work, char *name, int state, struct in_add
p += 2; p += 2;
DEBUG(2,("sending reset to %s %s of state %d\n", DEBUG(2,("sending reset to %s %s of state %d\n",
name,inet_ntoa(ip),state)); name,inet_ntoa(ip),state));
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
conf_browsing_alias(work->token),name,0x20,0x1d,ip,*iface_ip(ip)); myname,name,0x20,0x1d,ip,*iface_ip(ip));
} }
@ -95,47 +99,47 @@ void tell_become_backup(void)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
struct server_record *s; struct server_record *s;
int num_servers = 0; int num_servers = 0;
int num_backups = 0; int num_backups = 0;
for (s = work->serverlist; s; s = s->next) for (s = work->serverlist; s; s = s->next)
{ {
if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
num_servers++; num_servers++;
if (strequal(conf_browsing_alias(work->token), s->serv.name)) continue; if (strequal(myname, s->serv.name)) continue;
if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
num_backups++; num_backups++;
continue; continue;
} }
if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
DEBUG(3,("num servers: %d num backups: %d\n", DEBUG(3,("num servers: %d num backups: %d\n",
num_servers, num_backups)); num_servers, num_backups));
/* make first server a backup server. thereafter make every /* make first server a backup server. thereafter make every
tenth server a backup server */ tenth server a backup server */
if (num_backups != 0 && (num_servers+9) / num_backups > 10) if (num_backups != 0 && (num_servers+9) / num_backups > 10)
{ {
continue; continue;
} }
DEBUG(2,("sending become backup to %s %s for %s\n", DEBUG(2,("sending become backup to %s %s for %s\n",
s->serv.name, inet_ntoa(d->bcast_ip), s->serv.name, inet_ntoa(d->bcast_ip),
work->work_group)); work->work_group));
/* type 11 request from conf_browsing_alias(work->token)(20) to WG(1e) for SERVER */ /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
do_announce_request(s->serv.name, s->serv.name, work->work_group, do_announce_request(s->serv.name, work->work_group,
ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
} }
} }
} }
} }
@ -146,23 +150,8 @@ void tell_become_backup(void)
******************************************************************/ ******************************************************************/
BOOL same_context(struct dgram_packet *dgram) BOOL same_context(struct dgram_packet *dgram)
{ {
if (!strequal(dgram->dest_name .scope,scope )) return True; if (!strequal(dgram->dest_name .scope,scope )) return(True);
if ( strequal(dgram->source_name.name ,myname)) return(True);
return False;
}
/*******************************************************************
am I listening on a name. XXXX check the type of name as well.
******************************************************************/
BOOL listening_name(struct work_record *work, struct nmb_name *n)
{
if (strequal(n->name,conf_browsing_alias(work->token)) ||
strequal(n->name,work->work_group) ||
strequal(n->name,MSBROWSE))
{
return(True);
}
return(False); return(False);
} }
@ -208,8 +197,8 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15])); DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n", DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n",
namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
servertype,browse_type,browse_sig,comment)); servertype,browse_type,browse_sig,comment));
name[15] = 0; name[15] = 0;
@ -224,7 +213,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
dgram->dest_name.name_type != 0x1)) dgram->dest_name.name_type != 0x1))
{ {
DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
command, inet_ntoa(ip), namestr(&dgram->dest_name))); command, inet_ntoa(ip), namestr(&dgram->dest_name)));
return; return;
} }
@ -276,7 +265,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf)
if (command == ANN_LocalMasterAnnouncement) if (command == ANN_LocalMasterAnnouncement)
{ {
add_browser_entry(serv_name,dgram->dest_name.name_type, add_browser_entry(serv_name,dgram->dest_name.name_type,
work->work_group,30,ip,True); work->work_group,30,ip,True);
} }
} }
@ -289,40 +278,26 @@ static void process_master_announce(struct packet_struct *p,char *buf)
struct in_addr ip = dgram->header.source_ip; struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip); struct subnet_record *d = find_subnet(ip);
struct subnet_record *mydomain = find_subnet(*iface_bcast(ip)); struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
char *to_name = dgram->dest_name.name; /* our primary name or an alias */
char *name = buf; char *name = buf;
char *work_name; struct work_record *work;
int token;
name[15] = 0; name[15] = 0;
DEBUG(3,("Master Announce from %s (%s)\n", name, inet_ntoa(ip))); DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
if (same_context(dgram)) return; if (same_context(dgram)) return;
if (!d || !mydomain) return; if (!d || !mydomain) return;
token = conf_alias_to_token(to_name); if (!lp_domain_master()) return;
if (token == -1)
{
DEBUG(4, ("alias %s not known\n", to_name));
return;
}
/* carry on only if we are a domain master under the server alias */
if (!conf_should_domain_master(token)) return;
/* Convert the server name by which the master browser
called this server to the workgroup name. */
if ((work_name = conf_workgroup_name(token)) == (char*)NULL)
{
DEBUG(4, ("process_master_announce(): no alias for \"%s\"\n", to_name));
return;
}
/* merge browse lists with them */ for (work = mydomain->workgrouplist; work; work = work->next)
add_browser_entry(name, 0x1b, work_name,30,ip,True); {
if (AM_MASTER(work))
{
/* merge browse lists with them */
add_browser_entry(name,0x1b, work->work_group,30,ip,True);
}
}
} }
/******************************************************************* /*******************************************************************
@ -343,44 +318,62 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
struct dgram_packet *dgram = &p->packet.dgram; struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip; struct in_addr ip = dgram->header.source_ip;
int count = CVAL(buf,0); int count = CVAL(buf,0);
unsigned int pick;
uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */ uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
char *buf1; char *buf1;
DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n", DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
namestr(&dgram->dest_name), inet_ntoa(ip), namestr(&dgram->dest_name), inet_ntoa(ip),
count, info)); count, info));
if (same_context(dgram)) return; if (same_context(dgram)) return;
if (count <= 0) return; if (count <= 0) return;
pick = sys_random(count);
/* go through the list of servers attempting to sync browse lists */ /* go through the list of servers attempting to sync browse lists */
for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
{ {
struct in_addr back_ip;
struct subnet_record *d; struct subnet_record *d;
if (count != pick) continue; DEBUG(4,("Searching for backup browser %s at %s...\n",
buf1, inet_ntoa(ip)));
DEBUG(4,("Searching for backup browser %s...\n", buf1));
if ((d = find_subnet(ip)) != NULL) /* XXXX assume name is a DNS name NOT a netbios name. a more complete
{ approach is to use reply_name_query functionality to find the name */
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) back_ip = *interpret_addr2(buf1);
{
if (work->token == 0 /* token */) if (zero_ip(back_ip))
{ {
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, DEBUG(4,("Failed to find backup browser server using DNS\n"));
work->token,work->work_group,0x1d, continue;
0,0,0,0,NULL,NULL, }
False,False,ipzero,ipzero);
return; DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
} DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
}
} /* XXXX function needs work */
continue;
if ((d = find_subnet(back_ip)))
{
struct subnet_record *d1;
for (d1 = subnetlist; d1; d1 = d1->next)
{
struct work_record *work;
for (work = d1->workgrouplist; work; work = work->next)
{
if (work->token == 0 /* token */)
{
queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
work->work_group,0x1d,
0,0,0,NULL,NULL,
False,False,back_ip,back_ip);
return;
}
}
}
}
} }
} }
@ -388,9 +381,9 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
/**************************************************************************** /****************************************************************************
send a backup list response. send a backup list response.
**************************************************************************/ **************************************************************************/
static void send_backup_list(struct work_record *work, struct nmb_name *src_name, static void send_backup_list(char *work_name, struct nmb_name *src_name,
int token, uint32 info, int token, uint32 info,
int name_type, struct in_addr ip) int name_type, struct in_addr ip)
{ {
char outbuf[1024]; char outbuf[1024];
char *p, *countptr, *nameptr; char *p, *countptr, *nameptr;
@ -398,8 +391,8 @@ static void send_backup_list(struct work_record *work, struct nmb_name *src_name
char *theirname = src_name->name; char *theirname = src_name->name;
DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
work->work_group, inet_ntoa(ip), work_name, inet_ntoa(ip),
conf_browsing_alias(work->token),0x0,theirname,0x0)); myname,0x0,theirname,0x0));
if (name_type == 0x1d) if (name_type == 0x1d)
{ {
@ -431,51 +424,62 @@ static void send_backup_list(struct work_record *work, struct nmb_name *src_name
#if 0 #if 0
struct server_record *s; for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (s = work->serverlist; s; s = s->next) for (work = d->workgrouplist; work; work = work->next)
{ {
BOOL found = False; struct server_record *s;
char *n;
if (!strequal(work->work_group, work_name)) continue;
if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
for (s = work->serverlist; s; s = s->next)
for (n = nameptr; n < p; n = skip_string(n, 1)) {
{ BOOL found = False;
if (strequal(n, s->serv.name)) found = True; char *n;
}
if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
if (found) continue; /* exclude names already added */
for (n = nameptr; n < p; n = skip_string(n, 1))
/* workgroup request: include all backup browsers in the list */ {
/* domain request: include all domain members in the list */ if (strequal(n, s->serv.name)) found = True;
}
if (found) continue; /* exclude names already added */
/* workgroup request: include all backup browsers in the list */
/* domain request: include all domain members in the list */
if ((name_type == 0x1d && (s->serv.type & SV_TYPE_MASTER_BROWSER)) || if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
(name_type == 0x1b && (s->serv.type & SV_TYPE_DOMAIN_BROWSER))) (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
{ {
DEBUG(4, ("%s ", s->serv.name)); DEBUG(4, ("%s ", s->serv.name));
count++; count++;
strcpy(p,s->serv.name); strcpy(p,s->serv.name);
strupper(p); strupper(p);
p = skip_string(p,1); p = skip_string(p,1);
} }
}
}
} }
#endif #endif
count++; count++;
strcpy(p,conf_browsing_alias(work->token)); strcpy(p,myname);
strupper(p); strupper(p);
p = skip_string(p,1); p = skip_string(p,1);
if (count == 0) if (count == 0)
{ {
DEBUG(4, ("none\n")); DEBUG(4, ("none\n"));
} }
else else
{ {
DEBUG(4, (" - count %d\n", count)); DEBUG(4, (" - count %d\n", count));
} }
CVAL(countptr, 0) = count; CVAL(countptr, 0) = count;
@ -484,7 +488,7 @@ static void send_backup_list(struct work_record *work, struct nmb_name *src_name
debug_browse_data(outbuf, len); debug_browse_data(outbuf, len);
} }
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
conf_browsing_alias(work->token),theirname,0x0,0x0,ip,*iface_ip(ip)); myname,theirname,0x0,0x0,ip,*iface_ip(ip));
} }
@ -515,24 +519,24 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
if (name_type != 0x1b && name_type != 0x1d) { if (name_type != 0x1b && name_type != 0x1d) {
DEBUG(0,("backup request to wrong type %d from %s\n", DEBUG(0,("backup request to wrong type %d from %s\n",
name_type,inet_ntoa(ip))); name_type,inet_ntoa(ip)));
return; return;
} }
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (strequal(work->work_group, dgram->dest_name.name)) if (strequal(work->work_group, dgram->dest_name.name))
{ {
DEBUG(2,("sending backup list to %s %s id=%x\n", DEBUG(2,("sending backup list to %s %s id=%x\n",
namestr(&dgram->dest_name),inet_ntoa(ip),info)); namestr(&dgram->dest_name),inet_ntoa(ip),info));
send_backup_list(work,&dgram->source_name, send_backup_list(work->work_group,&dgram->source_name,
token,info,name_type,ip); token,info,name_type,ip);
return; return;
} }
} }
} }
} }
@ -552,23 +556,23 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
int state = CVAL(buf,0); int state = CVAL(buf,0);
DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n", DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n",
namestr(&dgram->dest_name), state)); namestr(&dgram->dest_name), state));
/* stop being a master but still deal with being a backup browser */ /* stop being a master but still deal with being a backup browser */
if (state & 0x1) if (state & 0x1)
{ {
struct subnet_record *d; struct subnet_record *d;
for (d = subnetlist; d; d = d->next) for (d = subnetlist; d; d = d->next)
{ {
struct work_record *work; struct work_record *work;
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (AM_MASTER(work)) if (AM_MASTER(work))
{ {
become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER); become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
} }
} }
} }
} }
/* XXXX documentation inconsistency: the above description does not /* XXXX documentation inconsistency: the above description does not
@ -577,24 +581,21 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
/* totally delete all servers and start afresh */ /* totally delete all servers and start afresh */
if (state & 0x2) if (state & 0x2)
{
/* remove all workgroups (and their servers) from database */
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{ {
struct work_record *work; struct subnet_record *d;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True)); for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
}
add_my_subnets(lp_workgroup());
} }
/* add all known workgroups back into database */
add_workgroups_to_subnets();
}
/* stop browsing altogether. i don't think this is a good idea! */ /* stop browsing altogether. i don't think this is a good idea! */
if (state & 0x4) if (state & 0x4)
{ {
DEBUG(1,("ignoring request to stop being a browser. sorry!\n")); DEBUG(1,("ignoring request to stop being a browser. sorry!\n"));
} }
} }
/******************************************************************* /*******************************************************************
@ -610,43 +611,39 @@ static void process_announce_request(struct packet_struct *p,char *buf)
struct in_addr ip = dgram->header.source_ip; struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip); struct subnet_record *d = find_subnet(ip);
int token = CVAL(buf,0); int token = CVAL(buf,0);
int wg_token = 0;
char *name = buf+1; char *name = buf+1;
char *samba_alias;
name[15] = 0; name[15] = 0;
DEBUG(3,("Announce request from %s to %s token=0x%X\n", DEBUG(3,("Announce request from %s to %s token=0x%X\n",
name,namestr(&dgram->dest_name), token)); name,namestr(&dgram->dest_name), token));
/* look up the index for this workgroup */ if (strequal(dgram->source_name.name,myname)) return;
wg_token = conf_workgroup_name_to_token(dgram->dest_name.name,myname);
if (wg_token == -1) return;
/* check that samba is participating in this workgroup */
if (!conf_should_workgroup_member(wg_token)) return;
/* find samba's NetBIOS alias it operates under in this workgroup */
if ((samba_alias = conf_browsing_alias(wg_token)) == (char*)NULL) return;
/* ignore announce requests from samba under its own alias.
this should no longer happen because code has been added to
discard packets from ourself. */
if (strequal(dgram->source_name.name,samba_alias)) return;
/* XXXX BUG or FEATURE?: need to ensure that we are a member of
this workgroup before announcing, particularly as we only
respond on local interfaces anyway.
if (strequal(dgram->dest_name, lp_workgroup()) return; ???
*/
if (!d) return; if (!d) return;
/* XXXX BUG: the destination name type should also be checked,
not just the name. e.g if the name is WORKGROUP(0x1d) then
we should only respond if we own that name */
for (work = d->workgrouplist; work; work = work->next) for (work = d->workgrouplist; work; work = work->next)
{ {
if (wg_token == work->token) work->needannounce = True; /* XXXX BUG: the destination name type should also be checked,
} not just the name. e.g if the name is WORKGROUP(0x1d) then
we should only respond if we own that name */
if (strequal(dgram->dest_name.name,work->work_group))
{
work->needannounce = True;
}
}
} }
/**************************************************************************** /****************************************************************************
process a browse frame process a browse frame
****************************************************************************/ ****************************************************************************/
@ -660,27 +657,27 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
case ANN_LocalMasterAnnouncement: case ANN_LocalMasterAnnouncement:
{ {
debug_browse_data(buf, len); debug_browse_data(buf, len);
process_announce(p,command,buf+1); process_announce(p,command,buf+1);
break; break;
} }
case ANN_AnnouncementRequest: case ANN_AnnouncementRequest:
{ {
process_announce_request(p,buf+1); process_announce_request(p,buf+1);
break; break;
} }
case ANN_Election: case ANN_Election:
{ {
process_election(p,buf+1); process_election(p,buf+1);
break; break;
} }
case ANN_GetBackupListReq: case ANN_GetBackupListReq:
{ {
debug_browse_data(buf, len); debug_browse_data(buf, len);
process_send_backup_list(p,buf+1); process_send_backup_list(p,buf+1);
break; break;
} }
case ANN_GetBackupListResp: case ANN_GetBackupListResp:
@ -692,22 +689,22 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
case ANN_ResetBrowserState: case ANN_ResetBrowserState:
{ {
process_reset_browser(p, buf+1); process_reset_browser(p, buf+1);
break; break;
} }
case ANN_MasterAnnouncement: case ANN_MasterAnnouncement:
{ {
process_master_announce(p,buf+1); process_master_announce(p,buf+1);
break; break;
} }
default: default:
{ {
struct dgram_packet *dgram = &p->packet.dgram; struct dgram_packet *dgram = &p->packet.dgram;
DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", DEBUG(4,("ignoring browse packet %d from %s %s to %s\n",
command, namestr(&dgram->source_name), command, namestr(&dgram->source_name),
inet_ntoa(p->ip), namestr(&dgram->dest_name))); inet_ntoa(p->ip), namestr(&dgram->dest_name)));
} }
} }
} }

View File

@ -23,10 +23,6 @@
14 jan 96: lkcl@pires.co.uk 14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/ */
#include "includes.h" #include "includes.h"
@ -169,10 +165,10 @@ static void expire_names_and_servers(void)
time_t t = time(NULL); time_t t = time(NULL);
if (!lastrun) lastrun = t; if (!lastrun) lastrun = t;
if (t < lastrun + 15) return; /* give samba time to check its names */ if (t < lastrun + 5) return;
lastrun = t; lastrun = t;
check_expire_names(t); /* this checks samba's NetBIOS names */ expire_names(t);
expire_servers(t); expire_servers(t);
} }
@ -191,10 +187,10 @@ BOOL reload_services(BOOL test)
pstring fname; pstring fname;
strcpy(fname,lp_configfile()); strcpy(fname,lp_configfile());
if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
{ {
strcpy(servicesf,fname); strcpy(servicesf,fname);
test = False; test = False;
} }
} }
if (test && !lp_file_list_changed()) if (test && !lp_file_list_changed())
@ -255,32 +251,32 @@ static void load_hosts_file(char *fname)
if (count <= 0) continue; if (count <= 0) continue;
if (count > 0 && count < 2) { if (count > 0 && count < 2) {
DEBUG(0,("Ill formed hosts line [%s]\n",line)); DEBUG(0,("Ill formed hosts line [%s]\n",line));
continue; continue;
} }
if (count >= 4) { if (count >= 4) {
DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
continue; continue;
} }
DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags)); DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
if (strchr(flags,'G') || strchr(flags,'S')) { if (strchr(flags,'G') || strchr(flags,'S')) {
DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
continue; continue;
} }
if (strchr(flags,'M')) { if (strchr(flags,'M')) {
source = SELF; source = SELF;
strcpy(myname,name); strcpy(myname,name);
} }
ipaddr = *interpret_addr2(ip); ipaddr = *interpret_addr2(ip);
d = find_subnet(ipaddr); d = find_subnet(ipaddr);
if (d) { if (d) {
add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True); add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True); add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
} }
} }
@ -296,7 +292,8 @@ static void process(void)
BOOL run_election; BOOL run_election;
while (True) while (True)
{ {
time_t t = time(NULL);
run_election = check_elections(); run_election = check_elections();
listen_for_packets(run_election); listen_for_packets(run_election);
@ -313,11 +310,12 @@ static void process(void)
expire_names_and_servers(); expire_names_and_servers();
expire_netbios_response_entries(); expire_netbios_response_entries();
refresh_my_names(t);
write_browse_list(); write_browse_list();
do_browser_lists(); do_browser_lists();
check_master_browser(); check_master_browser();
} }
} }
@ -437,50 +435,50 @@ static void usage(char *pname)
while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF) while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
{ {
switch (opt) switch (opt)
{ {
case 's': case 's':
strcpy(servicesf,optarg); strcpy(servicesf,optarg);
break; break;
case 'N': case 'N':
case 'B': case 'B':
case 'I': case 'I':
case 'C': case 'C':
case 'G': case 'G':
DEBUG(0,("Obsolete option '%c' used\n",opt)); DEBUG(0,("Obsolete option '%c' used\n",opt));
break; break;
case 'H': case 'H':
strcpy(host_file,optarg); strcpy(host_file,optarg);
break; break;
case 'n': case 'n':
strcpy(myname,optarg); strcpy(myname,optarg);
strupper(myname); strupper(myname);
break; break;
case 'l': case 'l':
sprintf(debugf,"%s.nmb",optarg); sprintf(debugf,"%s.nmb",optarg);
break; break;
case 'i': case 'i':
strcpy(scope,optarg); strcpy(scope,optarg);
strupper(scope); strupper(scope);
break; break;
case 'D': case 'D':
is_daemon = True; is_daemon = True;
break; break;
case 'd': case 'd':
DEBUGLEVEL = atoi(optarg); DEBUGLEVEL = atoi(optarg);
break; break;
case 'p': case 'p':
port = atoi(optarg); port = atoi(optarg);
break; break;
case 'h': case 'h':
usage(argv[0]); usage(argv[0]);
exit(0); exit(0);
break; break;
default: default:
if (!is_a_socket(0)) { if (!is_a_socket(0)) {
usage(argv[0]); usage(argv[0]);
} }
break; break;
} }
} }
DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION)); DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
@ -489,18 +487,10 @@ static void usage(char *pname)
get_myname(myhostname,NULL); get_myname(myhostname,NULL);
if (!reload_services(False)) if (!reload_services(False))
return(-1); return(-1);
init_structs(); init_structs();
/* reads the smbbrowse.conf file. this is an alias mapping between
workgroups and samba NetBIOS aliases. samba can therefore be
a member of multiple workgroups, a local master browser of
multiple workgroups, or a domain master browser of multiple
workgroups, via each NetBIOS name alias. the aliases MUST
be unique for this to work. */
read_smbbrowse_conf(myname);
reload_services(True); reload_services(True);
set_samba_nb_type(); set_samba_nb_type();
@ -530,7 +520,7 @@ static void usage(char *pname)
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
} }
add_workgroups_to_subnets(); add_my_subnets(lp_workgroup());
DEBUG(3,("Checked names\n")); DEBUG(3,("Checked names\n"));

View File

@ -48,7 +48,7 @@ fudge for getpass function
****************************************************************************/ ****************************************************************************/
char *getsmbpass(char *pass) char *getsmbpass(char *pass)
{ {
return "dummy"; /* return anything: it should be ignored anyway */ return "dummy"; /* return anything: it should be ignored anyway */
} }
/**************************************************************************** /****************************************************************************
@ -84,46 +84,43 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
p = skip_string(p,1); p = skip_string(p,1);
if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, if (cli_call_api(PTR_DIFF(p,param),0, 8,10000,
&rprcnt,&rdrcnt, param,NULL, &rprcnt,&rdrcnt, param,NULL,
&rparam,&rdata)) &rparam,&rdata))
{ {
int res = SVAL(rparam,0); int res = SVAL(rparam,0);
int converter=SVAL(rparam,2); int converter=SVAL(rparam,2);
int i; int i;
if (res == 0) if (res == 0)
{ {
count=SVAL(rparam,4); count=SVAL(rparam,4);
p = rdata; p = rdata;
for (i = 0;i < count;i++, p += 26) for (i = 0;i < count;i++, p += 26)
{ {
char *sname = p; char *sname = p;
uint32 stype = IVAL(p,18); uint32 stype = IVAL(p,18);
int comment_offset = IVAL(p,22) & 0xFFFF; int comment_offset = IVAL(p,22) & 0xFFFF;
char *cmnt = comment_offset?(rdata+comment_offset-converter):""; char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
struct work_record *w = work; struct work_record *w = work;
DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt));
if (stype & SV_TYPE_DOMAIN_ENUM) if (stype & SV_TYPE_DOMAIN_ENUM)
{ {
/* creates workgroup on remote subnet */ /* creates workgroup on remote subnet */
if ((w = find_workgroupstruct(d,sname,True))) if ((w = find_workgroupstruct(d,sname,True)))
{ {
announce_request(w, d->bcast_ip); announce_request(w, d->bcast_ip);
} }
} }
if (w) if (w)
{ add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False);
add_server_entry(d,w,sname,stype & ~SV_TYPE_LOCAL_LIST_ONLY, }
lp_max_ttl(),cmnt,False); }
}
}
} }
}
if (rparam) free(rparam); if (rparam) free(rparam);
if (rdata) free(rdata); if (rdata) free(rdata);
@ -139,7 +136,7 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
do a NetServerEnum and update our server and workgroup databases. do a NetServerEnum and update our server and workgroup databases.
******************************************************************/ ******************************************************************/
void sync_browse_lists(struct subnet_record *d, struct work_record *work, void sync_browse_lists(struct subnet_record *d, struct work_record *work,
char *name, int nm_type, struct in_addr ip, BOOL local) char *name, int nm_type, struct in_addr ip, BOOL local)
{ {
uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
@ -154,7 +151,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
got_pass = True; got_pass = True;
DEBUG(4,("sync browse lists with %s for %s %s\n", DEBUG(4,("sync browse lists with %s for %s %s\n",
work->work_group, name, inet_ntoa(ip))); work->work_group, name, inet_ntoa(ip)));
strcpy(workgroup,work->work_group); strcpy(workgroup,work->work_group);
strcpy(desthost,name); strcpy(desthost,name);
@ -173,11 +170,11 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
if (cli_open_sockets(SMB_PORT)) if (cli_open_sockets(SMB_PORT))
{ {
if (cli_send_login(NULL,NULL,True,True)) if (cli_send_login(NULL,NULL,True,True))
{ {
add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM); add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM);
add_info(d, work, local_type|(SV_TYPE_ALL& add_info(d, work, local_type|(SV_TYPE_ALL&
~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY))); ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY)));
} }
close_sockets(); close_sockets();
} }

View File

@ -106,34 +106,33 @@ extern int coding_system;
*/ */
typedef struct typedef struct
{ {
char *szAutoServices; char *szPrintcapname;
char *szCharacterSet; char *szLockDir;
char *szConfigFile; char *szRootdir;
char *szDefaultService; char *szDefaultService;
char *szDfree; char *szDfree;
char *szDomainController;
char *szHostsEquiv;
char *szInterfaces;
char *szLockDir;
char *szLogFile;
char *szLogonScript;
char *szMsgCommand; char *szMsgCommand;
char *szPasswdChat; char *szHostsEquiv;
char *szPasswdProgram;
char *szPasswordServer;
char *szPrintcapname;
char *szRemoteAnnounce;
char *szRootdir;
char *szServerComment;
char *szServerString; char *szServerString;
char *szSmbrun; char *szAutoServices;
char *szPasswdProgram;
char *szPasswdChat;
char *szLogFile;
char *szConfigFile;
char *szSMBPasswdFile; char *szSMBPasswdFile;
char *szSocketAddress; char *szPasswordServer;
char *szSocketOptions; char *szSocketOptions;
char *szUsernameMap;
char *szValidChars; char *szValidChars;
char *szWINSserver;
char *szWorkGroup; char *szWorkGroup;
char *szDomainController;
char *szUsernameMap;
char *szCharacterSet;
char *szLogonScript;
char *szSmbrun;
char *szWINSserver;
char *szInterfaces;
char *szRemoteAnnounce;
char *szSocketAddress;
int max_log_size; int max_log_size;
int mangled_stack; int mangled_stack;
int max_xmit; int max_xmit;
@ -153,7 +152,6 @@ typedef struct
BOOL bWINSsupport; BOOL bWINSsupport;
BOOL bWINSproxy; BOOL bWINSproxy;
BOOL bPreferredMaster; BOOL bPreferredMaster;
BOOL bLocalMaster;
BOOL bDomainMaster; BOOL bDomainMaster;
BOOL bDomainLogons; BOOL bDomainLogons;
BOOL bEncryptPasswords; BOOL bEncryptPasswords;
@ -384,7 +382,6 @@ struct parm_struct
{"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL}, {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
{"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
{"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
{"server comment", P_STRING, P_GLOBAL, &Globals.szServerComment, NULL},
{"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL}, {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
{"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
{"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
@ -428,7 +425,6 @@ struct parm_struct
{"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL}, {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
{"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
{"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
{"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL},
{"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL}, {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
{"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL}, {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
{"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL}, {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
@ -564,9 +560,6 @@ static void init_globals(void)
string_set(&Globals.szSocketAddress, "0.0.0.0"); string_set(&Globals.szSocketAddress, "0.0.0.0");
sprintf(s,"Samba %s",VERSION); sprintf(s,"Samba %s",VERSION);
string_set(&Globals.szServerString,s); string_set(&Globals.szServerString,s);
strcpy(s,"Samba %v"); /* samba comment */
string_sub(s,"%v",VERSION);
string_set(&Globals.szServerComment,s);
Globals.bLoadPrinters = True; Globals.bLoadPrinters = True;
Globals.bUseRhosts = False; Globals.bUseRhosts = False;
Globals.max_packet = 65535; Globals.max_packet = 65535;
@ -591,9 +584,8 @@ static void init_globals(void)
Globals.bSyslogOnly = False; Globals.bSyslogOnly = False;
Globals.os_level = 0; Globals.os_level = 0;
Globals.max_ttl = 60*60*4; /* 2 hours default */ Globals.max_ttl = 60*60*4; /* 2 hours default */
Globals.bPreferredMaster = True; /* force election on startup */ Globals.bPreferredMaster = True;
Globals.bLocalMaster = True; /* master browser on local subnet */ Globals.bDomainMaster = False;
Globals.bDomainMaster = False; /* maintain wide area network browse list */
Globals.bDomainLogons = False; Globals.bDomainLogons = False;
Globals.bBrowseList = True; Globals.bBrowseList = True;
Globals.bWINSsupport = True; Globals.bWINSsupport = True;
@ -732,7 +724,6 @@ FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile) FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile) FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString) FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
FN_GLOBAL_STRING(lp_server_comment,&Globals.szServerComment)
FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname) FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir) FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir) FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
@ -756,7 +747,6 @@ FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy) FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster) FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons) FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster) FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)

View File

@ -812,7 +812,10 @@ static int get_server_info(uint32 servertype,
if (!next_token(&ptr,s->name , NULL)) continue; if (!next_token(&ptr,s->name , NULL)) continue;
if (!next_token(&ptr,stype , NULL)) continue; if (!next_token(&ptr,stype , NULL)) continue;
if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) {
/* this allows us to cope with an old nmbd */
strcpy(s->domain,lp_workgroup());
}
if (sscanf(stype,"%X",&s->type) != 1) { if (sscanf(stype,"%X",&s->type) != 1) {
DEBUG(4,("r:host file ")); DEBUG(4,("r:host file "));
@ -980,22 +983,8 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
if (strcmp(str1, "WrLehDz") == 0) { if (strcmp(str1, "WrLehDz") == 0) {
StrnCpy(domain, p, sizeof(fstring)-1); StrnCpy(domain, p, sizeof(fstring)-1);
} } else {
else StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
{
/* a server will connect to us under one of samba's NetBIOS
name aliases, and by not giving us a domain name it
assumes we know which domain it's talking about.
do a look-up for the workgroup name against the name
the host connected to us as.
*/
char *work_alias;
work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, sizeof(fstring)-1);
} }
if (lp_browse_list()) if (lp_browse_list())
@ -1679,19 +1668,9 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
pstring comment; pstring comment;
uint32 servertype=DFLT_SERVER_TYPE; uint32 servertype=DFLT_SERVER_TYPE;
char *work_alias;
char domain[16];
work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, sizeof(fstring)-1);
else
*domain = 0;
strcpy(comment,lp_serverstring()); strcpy(comment,lp_serverstring());
if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) { if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
for (i=0;i<count;i++) for (i=0;i<count;i++)
if (strequal(servers[i].name,local_machine)) { if (strequal(servers[i].name,local_machine)) {
servertype = servers[i].type; servertype = servers[i].type;
@ -1744,14 +1723,6 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
char *p2; char *p2;
extern pstring sesssetup_user; extern pstring sesssetup_user;
int level = SVAL(p,0); int level = SVAL(p,0);
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
DEBUG(4,("NetWkstaGetInfo level %d\n",level)); DEBUG(4,("NetWkstaGetInfo level %d\n",level));
@ -1782,7 +1753,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
p += 4; p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata)); SIVAL(p,0,PTR_DIFF(p2,*rdata));
StrCpy(p2,domain); strcpy(p2,lp_workgroup());
p2 = skip_string(p2,1); p2 = skip_string(p2,1);
p += 4; p += 4;
@ -1791,7 +1762,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
p += 2; p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata)); SIVAL(p,0,PTR_DIFF(p2,*rdata));
strcpy(p2,domain); /* login domain?? */ strcpy(p2,lp_workgroup()); /* login domain?? */
p2 = skip_string(p2,1); p2 = skip_string(p2,1);
p += 4; p += 4;
@ -2014,14 +1985,6 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
int uLevel; int uLevel;
struct pack_desc desc; struct pack_desc desc;
char* name; char* name;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
uLevel = SVAL(p,0); uLevel = SVAL(p,0);
name = p + 2; name = p + 2;
@ -2064,7 +2027,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
strupper(mypath); strupper(mypath);
PACKS(&desc,"z",mypath); /* computer */ PACKS(&desc,"z",mypath); /* computer */
} }
PACKS(&desc,"z",domain);/* domain */ PACKS(&desc,"z",lp_workgroup());/* domain */
PACKS(&desc,"z",lp_logon_script()); /* script path */ PACKS(&desc,"z",lp_logon_script()); /* script path */
PACKI(&desc,"D",0); /* reserved */ PACKI(&desc,"D",0); /* reserved */
} }

View File

@ -44,8 +44,6 @@ extern BOOL case_sensitive;
extern pstring sesssetup_user; extern pstring sesssetup_user;
extern int Client; extern int Client;
extern pstring local_machine;
/* this macro should always be used to extract an fnum (smb_fid) from /* this macro should always be used to extract an fnum (smb_fid) from
a packet to ensure chaining works correctly */ a packet to ensure chaining works correctly */
#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
@ -253,18 +251,9 @@ static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
{ {
uint32 dword1; uint32 dword1;
uint16 word1; uint16 word1;
int wglen; char * workgroup = lp_workgroup();
int wglen = strlen(workgroup);
int i; int i;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
wglen = strlen(domain);
/* All kinds of mysterious numbers here */ /* All kinds of mysterious numbers here */
*rdata_len = 90 + 2 * wglen; *rdata_len = 90 + 2 * wglen;
@ -290,7 +279,7 @@ static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
SIVAL(*rdata,0x2C,4); SIVAL(*rdata,0x2C,4);
SIVAL(*rdata,0x34,wglen); SIVAL(*rdata,0x34,wglen);
for ( i = 0 ; i < wglen ; i++ ) for ( i = 0 ; i < wglen ; i++ )
(*rdata)[0x38 + i * 2] = domain[i]; (*rdata)[0x38 + i * 2] = workgroup[i];
/* Now fill in the rest */ /* Now fill in the rest */
i = 0x38 + wglen * 2; i = 0x38 + wglen * 2;

View File

@ -37,7 +37,6 @@ extern connection_struct Connections[];
extern files_struct Files[]; extern files_struct Files[];
extern BOOL case_sensitive; extern BOOL case_sensitive;
extern pstring sesssetup_user; extern pstring sesssetup_user;
extern fstring local_machine;
extern int Client; extern int Client;
/* this macro should always be used to extract an fnum (smb_fid) from /* this macro should always be used to extract an fnum (smb_fid) from
@ -55,6 +54,7 @@ int reply_special(char *inbuf,char *outbuf)
int msg_flags = CVAL(inbuf,1); int msg_flags = CVAL(inbuf,1);
pstring name1,name2; pstring name1,name2;
extern fstring remote_machine; extern fstring remote_machine;
extern fstring local_machine;
char *p; char *p;
*name1 = *name2 = 0; *name1 = *name2 = 0;
@ -319,14 +319,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
BOOL guest=False; BOOL guest=False;
BOOL computer_id=False; BOOL computer_id=False;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
*smb_apasswd = 0; *smb_apasswd = 0;
sess_uid = SVAL(inbuf,smb_uid); sess_uid = SVAL(inbuf,smb_uid);
@ -460,7 +452,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
p = smb_buf(outbuf); p = smb_buf(outbuf);
strcpy(p,"Unix"); p = skip_string(p,1); strcpy(p,"Unix"); p = skip_string(p,1);
strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
strcpy(p,domain); p = skip_string(p,1); strcpy(p,lp_workgroup()); p = skip_string(p,1);
set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
/* perhaps grab OS version here?? */ /* perhaps grab OS version here?? */
} }

View File

@ -3746,8 +3746,6 @@ static void usage(char *pname)
DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
} }
read_smbbrowse_conf(myhostname);
process(); process();
close_sockets(); close_sockets();