From afd08462ad5ff6b3c4bf621e39c55853a608175e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 15:41:30 +0000 Subject: 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 45e66a69d320024877c8b13f12b21bf895e04410) --- source3/client/client.c | 16 +- source3/include/nameserv.h | 80 ++--- source3/include/proto.h | 151 ++++----- source3/include/smb.h | 6 +- source3/lib/system.c | 9 - source3/libsmb/nmblib.c | 2 +- source3/nameannounce.c | 480 +++++++++++++--------------- source3/namebrowse.c | 57 ++-- source3/nameconf.c | 103 +++--- source3/namedbname.c | 283 ++++++++--------- source3/namedbresp.c | 12 +- source3/namedbserver.c | 89 +++--- source3/namedbsubnet.c | 189 +++++------ source3/namedbwork.c | 133 ++++---- source3/nameelect.c | 339 ++++++++------------ source3/namelogon.c | 31 +- source3/namepacket.c | 346 ++++++++++---------- source3/nameresp.c | 395 +++++++++++------------ source3/nameserv.c | 249 +++++++-------- source3/nameservreply.c | 4 +- source3/nameservresp.c | 762 +++++++++++++++++++++------------------------ source3/namework.c | 465 ++++++++++++++------------- source3/nmbd/nmbd.c | 144 ++++----- source3/nmbsync.c | 77 +++-- source3/param/loadparm.c | 52 ++-- source3/smbd/ipc.c | 57 +--- source3/smbd/pipes.c | 17 +- source3/smbd/reply.c | 12 +- source3/smbd/server.c | 2 - 29 files changed, 2065 insertions(+), 2497 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 6db0f4694e..cdf33a14b3 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3787,12 +3787,10 @@ static BOOL list_servers(char *wk_grp) for (i=0;iServerType & SV_TYPE_MASTER_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 */ #define MSBROWSE "\001\002__MSBROWSE__\002" @@ -112,19 +99,19 @@ enum master_state enum state_type { - NAME_STATUS_DOM_SRV_CHK, - NAME_STATUS_SRV_CHK, - NAME_REGISTER_CHALLENGE, - NAME_REGISTER, - NAME_RELEASE, - NAME_QUERY_CONFIRM, - NAME_QUERY_ANNOUNCE_HOST, - NAME_QUERY_SYNC_LOCAL, - NAME_QUERY_SYNC_REMOTE, - NAME_QUERY_DOM_SRV_CHK, - NAME_QUERY_SRV_CHK, - NAME_QUERY_FIND_MST, - NAME_QUERY_MST_CHK + NAME_STATUS_DOM_SRV_CHK, + NAME_STATUS_SRV_CHK, + NAME_REGISTER_CHALLENGE, + NAME_REGISTER, + NAME_RELEASE, + NAME_QUERY_CONFIRM, + NAME_QUERY_ANNOUNCE_HOST, + NAME_QUERY_SYNC_LOCAL, + NAME_QUERY_SYNC_REMOTE, + NAME_QUERY_DOM_SRV_CHK, + NAME_QUERY_SRV_CHK, + NAME_QUERY_FIND_MST, + NAME_QUERY_MST_CHK }; /* a netbios name structure */ @@ -134,14 +121,6 @@ struct nmb_name { 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 */ /* this is used for multi-homed systems and for internet group names */ struct nmb_ip @@ -169,16 +148,16 @@ struct name_record /* browse and backup server cache for synchronising browse list */ struct browse_cache_record { - struct browse_cache_record *next; - struct browse_cache_record *prev; - - char name[17]; - int type; - char group[17]; - struct in_addr ip; - time_t sync_time; - BOOL synced; - BOOL local; + struct browse_cache_record *next; + struct browse_cache_record *prev; + + pstring name; + int type; + pstring group; + struct in_addr ip; + time_t sync_time; + BOOL synced; + BOOL local; }; /* 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; /* work group info */ - char work_group[17]; + fstring work_group; int token; /* used when communicating with backup browsers */ int ServerType; @@ -235,18 +214,17 @@ struct response_record int fd; int quest_type; struct nmb_name name; - struct nmb_ip reply; + int nb_flags; time_t ttl; - enum name_source source; - int token; /* unique workgroup token id */ int server_type; - char my_name[17]; - char my_comment[50]; + fstring my_name; + fstring my_comment; BOOL bcast; BOOL recurse; struct in_addr send_ip; + struct in_addr reply_to_ip; int num_msgs; diff --git a/source3/include/proto.h b/source3/include/proto.h index 5f18c488ce..1b76591abd 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -124,7 +124,6 @@ char *lp_smbrun(void); char *lp_configfile(void); char *lp_smb_passwd_file(void); char *lp_serverstring(void); -char *lp_server_comment(void); char *lp_printcapname(void); char *lp_lockdir(void); char *lp_rootdir(void); @@ -147,7 +146,6 @@ char *lp_interfaces(void); char *lp_socket_address(void); BOOL lp_wins_support(void); BOOL lp_wins_proxy(void); -BOOL lp_local_master(void); BOOL lp_domain_master(void); BOOL lp_domain_logons(void); BOOL lp_preferred_master(void); @@ -294,22 +292,20 @@ int reply_sendend(char *inbuf,char *outbuf); /*The following definitions come from nameannounce.c */ void announce_request(struct work_record *work, struct in_addr ip); -void do_announce_request(char *info, char *from_name, char *to_name, - int announce_type, int from, int to, struct in_addr dest_ip); +void do_announce_request(char *info, char *to_name, int announce_type, + int from, + int to, struct in_addr dest_ip); void sync_server(enum state_type state, char *serv_name, char *work_name, - int name_type, - struct in_addr ip); + int name_type, + struct in_addr ip); void do_announce_host(int command, - char *from_name, int from_type, struct in_addr from_ip, - char *to_name , int to_type , struct in_addr to_ip, - time_t announce_interval, - char *server_name, int server_type, - char major_version, char minor_version, - uint16 browse_version, uint16 browse_sig, - char *server_comment); + char *from_name, int from_type, struct in_addr from_ip, + char *to_name , int to_type , struct in_addr to_ip, + time_t announce_interval, + char *server_name, int server_type, char *server_comment); void remove_my_servers(void); 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_master(void); void announce_remote(void); @@ -318,7 +314,7 @@ void announce_remote(void); void expire_browse_cache(time_t t); 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); /*The following definitions come from nameconf.c */ @@ -326,10 +322,8 @@ void do_browser_lists(void); int get_num_workgroups(void); int conf_workgroup_name_to_token(char *workgroup_name,char *default_name); char *conf_workgroup_name(int token); -int conf_should_preferred_master(int token); int conf_should_workgroup_member(int token); int conf_should_local_master(int token); -int conf_should_domain_logon(int token); int conf_should_domain_master(int token); char *conf_browsing_alias(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); void remove_name(struct subnet_record *d, struct name_record *n); struct name_record *find_name(struct name_record *n, - struct nmb_name *name, - int search); + struct nmb_name *name, + int search); struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip); + struct nmb_name *name, + int search, struct in_addr ip); void dump_names(void); void load_netbios_names(void); void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip); + char *name,int type, enum name_source source, + struct in_addr ip); struct name_record *add_netbios_entry(struct subnet_record *d, - char *name, int type, int nb_flags, - int ttl, enum name_source source, struct in_addr ip, - BOOL new_only,BOOL wins); -void check_expire_names(time_t t); + char *name, int type, int nb_flags, + int ttl, enum name_source source, struct in_addr ip, + BOOL new_only,BOOL wins); +void expire_names(time_t t); struct name_record *search_for_name(struct subnet_record **d, - struct nmb_name *question, - struct in_addr ip, int Time, int search); + struct nmb_name *question, + struct in_addr ip, int Time, int search); /*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, struct response_record *n); struct response_record *make_response_queue_record(enum state_type state, - int id,uint16 fd, int quest_type, - int token, char *name,int type, - enum name_source source, int nb_flags, time_t ttl, + int id,uint16 fd, + int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, 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 */ 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 *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace); + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, + BOOL replace); void expire_servers(time_t t); /*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_req_subnet(struct in_addr ip, BOOL bcast); void add_subnet_interfaces(void); -void add_workgroup_to_subnet(char *group, struct in_addr bcast_ip, - struct in_addr mask_ip); -void add_workgroups_to_subnets(); +void add_my_subnets(char *group); struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, - char *name, BOOL add, BOOL lmhosts); + struct in_addr mask_ip, + char *name, BOOL add, BOOL lmhosts); void write_browse_list(void); /*The following definitions come from namedbwork.c */ struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers); + struct work_record *work, + BOOL remove_all_servers); struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add); + fstring name, BOOL add); void dump_workgroups(void); /*The following definitions come from nameelect.c */ @@ -418,14 +409,13 @@ void dump_workgroups(void); void check_master_browser(void); void browser_gone(char *work_name, struct in_addr ip); 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_register_work(struct subnet_record *d, int token, - char *name, int name_type, enum name_source source, - struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast); +void name_register_work(struct subnet_record *d, char *name, int name_type, + int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast); void become_master(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 process_election(struct packet_struct *p,char *buf); 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 */ void debug_browse_data(char *outbuf, int len); -BOOL initiate_netbios_packet(uint16 id, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip); +void initiate_netbios_packet(uint16 *id, + int fd,int quest_type,char *name,int name_type, + int nb_flags,BOOL bcast,BOOL recurse, + struct in_addr to_ip); void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len); + int rcode, int rcv_code, int opcode, BOOL recurse, + struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, + char *data,int len); void queue_packet(struct packet_struct *packet); void run_packet_queue(); void listen_for_packets(BOOL run_election); BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, - char *dstname,int src_type,int dest_type, - struct in_addr dest_ip,struct in_addr src_ip); + char *dstname,int src_type,int dest_type, + struct in_addr dest_ip,struct in_addr src_ip); /*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 */ -void update_name_trn_id(void); void expire_netbios_response_entries(); -void queue_netbios_pkt_wins(struct subnet_record *d, - int fd,int quest_type,enum state_type state, - int token, char *name,int name_type, - enum name_source source, int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); -void queue_netbios_packet(struct subnet_record *d, - int fd,int quest_type,enum state_type state, - int token, char *name, int name_type, - enum name_source source, int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); +struct response_record *queue_netbios_pkt_wins(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + char *name,int name_type,int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip); +struct response_record *queue_netbios_packet(struct subnet_record *d, + int fd,int quest_type,enum state_type state,char *name, + int name_type,int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip); /*The following definitions come from nameserv.c */ -void remove_name_entry(struct subnet_record *d, int token, char *name,int type); -void add_my_name_entry(struct subnet_record *d, int token, - char *name,int type,int nb_flags); +void remove_name_entry(struct subnet_record *d, char *name,int type); +void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags); void add_my_names(void); void remove_my_names(); +void refresh_my_names(time_t t); void query_refresh_names(void); /*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 */ 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); /*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); 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); /*The following definitions come from nmbd.c */ @@ -545,7 +527,7 @@ int main(int argc,char *argv[]); char *getsmbpass(char *pass); 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 */ @@ -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_unlink(char *fname); -unsigned int sys_random(int max_range); int sys_open(char *fname,int flags,int mode); DIR *sys_opendir(char *dname); int sys_stat(char *fname,struct stat *sbuf); diff --git a/source3/include/smb.h b/source3/include/smb.h index 56ad8cbacd..f5d35d5261 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -380,10 +380,10 @@ typedef struct /* used for server information: client, nameserv and ipc */ struct server_info_struct { - char name[17]; + fstring name; uint32 type; - char comment[50]; - char domain[17]; /* used ONLY in ipc.c NOT namework.c */ + fstring comment; + fstring domain; /* used ONLY in ipc.c NOT namework.c */ BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ }; diff --git a/source3/lib/system.c b/source3/lib/system.c index f6b916881b..81e9a6679a 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -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 ********************************************************************/ diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index ef5c9da434..4113b34cab 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -65,7 +65,7 @@ static void debug_nmb_res_rec(struct res_rec *res, char *hdr) for (j = 0; j < 16; j++) { 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")); diff --git a/source3/nameannounce.c b/source3/nameannounce.c index c7a52473b6..fec8895510 100644 --- a/source3/nameannounce.c +++ b/source3/nameannounce.c @@ -23,18 +23,19 @@ 14 jan 96: lkcl@pires.co.uk added multiple workgroup domain master support - 30 July 96: David.Chappell@mail.trincoll.edu - Expanded multiple workgroup domain master browser support. - */ #include "includes.h" +#define TEST_CODE + extern int DEBUGLEVEL; extern BOOL CanRecurse; extern struct in_addr ipzero; +extern pstring myname; + extern int ClientDGRAM; extern int ClientNMB; @@ -42,17 +43,14 @@ extern int ClientNMB; extern struct subnet_record *subnetlist; 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. - - This is called by become_master(). This purpose of this action is to - encourage servers to send us host announcements right away. + send a announce request to the local net **************************************************************************/ 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; 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)); 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 */ p++; - StrnCpy(p,conf_browsing_alias(work->token),16); + StrnCpy(p,myname,16); + strupper(p); p = skip_string(p,1); /* 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! */ send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - conf_browsing_alias(work->token),work->work_group, - 0x20, 0x1e, - ip,*iface_ip(ip)); + myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip)); } /**************************************************************************** request an announcement **************************************************************************/ -void do_announce_request(char *info, char *from_name, char *to_name, - int announce_type, int from, int to, struct in_addr dest_ip) +void do_announce_request(char *info, char *to_name, int announce_type, + int from, + int to, struct in_addr dest_ip) { pstring outbuf; char *p; @@ -102,15 +100,14 @@ void do_announce_request(char *info, char *from_name, char *to_name, p++; 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); strupper(p); p = skip_string(p,1); send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - from_name,to_name,from,to, - dest_ip,*iface_ip(dest_ip)); + myname,to_name,from,to,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. **************************************************************************/ void sync_server(enum state_type state, char *serv_name, char *work_name, - int name_type, - struct in_addr ip) -{ - int token = conf_workgroup_name_to_token(work_name, myname); - + int name_type, + struct in_addr ip) +{ /* with a domain master we can get the whole list (not local only list) */ BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK); 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 */ - do_announce_request(conf_browsing_alias(token), /* info */ - conf_browsing_alias(token), /* from */ - serv_name, /* to */ - ANN_MasterAnnouncement, 0x20, 0,ip); + do_announce_request(myname, serv_name, 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 **************************************************************************/ void do_announce_host(int command, - char *from_name, int from_type, struct in_addr from_ip, - char *to_name , int to_type , struct in_addr to_ip, - time_t announce_interval, - char *server_name, int server_type, - char major_version, char minor_version, - uint16 browse_version, uint16 browse_sig, - char *server_comment) + char *from_name, int from_type, struct in_addr from_ip, + char *to_name , int to_type , struct in_addr to_ip, + time_t announce_interval, + char *server_name, int server_type, char *server_comment) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - bzero(outbuf,sizeof(outbuf)); - p = outbuf+1; + bzero(outbuf,sizeof(outbuf)); + p = outbuf+1; - /* command type */ - CVAL(outbuf,0) = command; + /* command type */ + CVAL(outbuf,0) = command; - /* announcement parameters */ - CVAL(p,0) = updatecount; - SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ + /* announcement parameters */ + CVAL(p,0) = updatecount; + SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ - StrnCpy(p+5,server_name,16); - strupper(p+5); + StrnCpy(p+5,server_name,16); + strupper(p+5); - CVAL(p,21) = major_version; - CVAL(p,22) = minor_version; + CVAL(p,21) = 0x02; /* major 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); - SSVAL(p,29,browse_sig); - - strcpy(p+31,server_comment); - 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)); - /* send the announcement */ - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - from_name, to_name, - from_type, to_type, - to_ip, from_ip); + /* send the announcement */ + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + from_name, to_name, + from_type, to_type, + to_ip, from_ip); } @@ -196,23 +185,20 @@ void do_announce_host(int command, ****************************************************************************/ void remove_my_servers(void) { - struct subnet_record *d; - for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (!strequal(conf_browsing_alias(work->token),s->serv.name)) - { - continue; - } - announce_server(d, work, s->serv.name, s->serv.comment, 0, 0); - } - } - } + struct subnet_record *d; + for (d = subnetlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + if (!strequal(myname,s->serv.name)) 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 ****************************************************************************/ 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 a client into thinking that the domain is in fact a server. (SV_TYPE_SERVER_UNIX, for example) */ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; - BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp); 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 */ 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()) { /* look up the domain master with the WINS server */ queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, 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, 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? 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 @@ -268,13 +256,10 @@ void announce_server(struct subnet_record *d, struct work_record *work, inet_ntoa(d->bcast_ip),work->work_group)); do_announce_host(ANN_LocalMasterAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1e, d->bcast_ip, - ttl*1000, - name, server_type, - HOST_MAJOR_VERSION, HOST_MINOR_VERSION, - HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE, - comment); + name , 0x00, d->myip, + work->work_group, 0x1e, d->bcast_ip, + ttl*1000, + name, server_type, comment); DEBUG(3,("sending domain announce to %s for %s\n", 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) { do_announce_host(ANN_DomainAnnouncement, - name , 0x00, d->myip, - MSBROWSE, 0x01, d->bcast_ip, - ttl*1000, - work->work_group, server_type ? domain_type : 0, - WG_MAJOR_VERSION, WG_MINOR_VERSION, - WG_BROWSE_VERSION, WG_BROWSE_SIGNATURE, - name); + name , 0x00, d->myip, + MSBROWSE, 0x01, d->bcast_ip, + ttl*1000, + work->work_group, server_type ? domain_type : 0, + name); } } else @@ -298,13 +281,10 @@ void announce_server(struct subnet_record *d, struct work_record *work, inet_ntoa(d->bcast_ip),work->work_group)); do_announce_host(ANN_HostAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1d, d->bcast_ip, - ttl*1000, - name, server_type, - HOST_MAJOR_VERSION, HOST_MINOR_VERSION, - HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE, - comment); + name , 0x00, d->myip, + work->work_group, 0x1d, d->bcast_ip, + ttl*1000, + name, server_type, comment); } } } @@ -317,6 +297,11 @@ void announce_host(void) time_t t = time(NULL); struct subnet_record *d; pstring comment; + char *my_name; + + StrnCpy(comment, lp_serverstring(), 43); + + my_name = *myname ? myname : "NoName"; for (d = subnetlist; d; d = d->next) { @@ -325,63 +310,62 @@ void announce_host(void) if (ip_equal(d->bcast_ip, ipgrp)) continue; for (work = d->workgrouplist; work; work = work->next) - { - uint32 stype = work->ServerType; - struct server_record *s; - - char *my_name = conf_browsing_alias(work->token); - char *my_comment = conf_browsing_alias_comment(work->token); - - StrnCpy(comment, my_comment, 43); - + { + uint32 stype = work->ServerType; + struct server_record *s; + BOOL announce = False; + /* must work on the code that does announcements at up to 30 seconds later if a master browser sends us a request announce. */ - if (work->needannounce) { - /* drop back to a max 3 minute announce - this is to prevent a - single lost packet from stuffing things up for too long */ - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - } - - /* announce every minute at first then progress to every 12 mins */ - if (work->lastannounce_time && - (t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (s = work->serverlist; s; s = s->next) { - if (strequal(my_name, s->serv.name)) - { - announce_server(d,work,my_name,comment, - work->announce_interval,stype); - break; - } - } - - if (work->needannounce) - { - work->needannounce = False; - break; - /* sorry: can't do too many announces. do some more later */ - } - } + if (work->needannounce) { + /* drop back to a max 3 minute announce - this is to prevent a + single lost packet from stuffing things up for too long */ + work->announce_interval = MIN(work->announce_interval, + CHECK_TIME_MIN_HOST_ANNCE*60); + work->lastannounce_time = t - (work->announce_interval+1); + } + + /* announce every minute at first then progress to every 12 mins */ + if (work->lastannounce_time && + (t - work->lastannounce_time) < work->announce_interval) + continue; + + if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) + work->announce_interval += 60; + + work->lastannounce_time = t; + + for (s = work->serverlist; s; s = s->next) { + if (strequal(myname, s->serv.name)) { + announce = True; + break; + } + } + + if (announce) { + announce_server(d,work,my_name,comment, + work->announce_interval,stype); + } + + if (work->needannounce) + { + 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 - 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() **************************************************************************/ void announce_master(void) @@ -393,108 +377,97 @@ void announce_master(void) if (!last) last = t; if (t-last < CHECK_TIME_MST_ANNOUNCE * 60) - return; + return; last = t; 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)) - { - am_master = True; - } + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + if (AM_MASTER(work)) + { + am_master = True; + } + } } - } if (!am_master) return; /* only proceed if we are a master browser */ for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (strequal(s->serv.name, conf_browsing_alias(work->token))) continue; - - /* all master browsers */ - if (s->serv.type & SV_TYPE_DOMAIN_MASTER) - { - /* check the existence of a domain master for this workgroup, - and if one exists at the specified ip, sync with it and - announce ourselves as a local master browser to it */ - - /* exclude lp_domain_controller() from this check if it's - in our browse lists, because it's dealt with separately - */ - if (!*lp_domain_controller() || - !strequal(lp_domain_controller(), s->serv.name)) - { - if (lp_wins_support() || *lp_wins_server()) - { - /* query the WINS server (that may include samba itself) - to find the browse master - */ - 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, ipzero, ipzero); - } - else - { - struct subnet_record *d2; - for (d2 = subnetlist; d2; d2 = d2->next) - { - /* 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, - True, False, d2->bcast_ip, d2->bcast_ip); - } - } - } - } - } - - /* now do primary domain controller - the one that's not - 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()) - { - struct in_addr ip; - - ip = *interpret_addr2(lp_domain_controller()); - - /* 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 - samba's local subnets - */ - - DEBUG(2, ("Searching for DOM %s at %s\n", - lp_domain_controller(), inet_ntoa(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); - } + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + if (strequal(s->serv.name, myname)) continue; + + /* all DOMs (which should also be master browsers) */ + if (s->serv.type & SV_TYPE_DOMAIN_CTRL) + { + /* 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 */ + + if (!*lp_domain_controller() || + !strequal(lp_domain_controller(), s->serv.name)) + { + if (!lp_wins_support() && *lp_wins_server()) + { + queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, + NAME_QUERY_DOM_SRV_CHK, + work->work_group,0x1b,0,0,0,NULL,NULL, + False, False, ipzero, ipzero); + } + else + { + struct subnet_record *d2; + for (d2 = subnetlist; d2; d2 = d2->next) + { + queue_netbios_packet(d,ClientNMB,NMB_QUERY, + NAME_QUERY_DOM_SRV_CHK, + work->work_group,0x1b,0,0,0,NULL,NULL, + True, False, d2->bcast_ip, d2->bcast_ip); + } + } + } + } + } + + /* now do primary domain controller - the one that's not + 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()) + { + struct in_addr ip; + BOOL bcast = False; + + ip = *interpret_addr2(lp_domain_controller()); + + if (zero_ip(ip)) { + ip = d->bcast_ip; + bcast = True; + } + + DEBUG(2, ("Searching for DOM %s at %s\n", + lp_domain_controller(), inet_ntoa(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->work_group,0x1b,0,0,0,NULL,NULL, + bcast, False, ip, ip); + } + } } - } } @@ -512,7 +485,6 @@ void announce_remote(void) pstring s2; struct in_addr addr; char *comment,*workgroup; - int token; int stype = DFLT_SERVER_TYPE; if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL) @@ -523,16 +495,13 @@ void announce_remote(void) s = lp_remote_announce(); if (!*s) return; - comment = lp_serverstring(); /* default comment */ - workgroup = lp_workgroup(); /* default workgroup name */ + comment = lp_serverstring(); + 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 WORKGROUP being optional */ char *wgroup; - char *my_name; - extern pstring myname; /* samba's default NetBIOS name */ wgroup = strchr(s2,'/'); if (wgroup) *wgroup++ = 0; @@ -541,17 +510,10 @@ void announce_remote(void) addr = *interpret_addr2(s2); - token = conf_workgroup_name_to_token(wgroup, myname); - my_name = conf_browsing_alias(token); - my_name = my_name ? my_name : myname; - - 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); + do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr), + wgroup,0x1e,addr, + REMOTE_ANNOUNCE_INTERVAL, + myname,stype,comment); } + } diff --git a/source3/namebrowse.c b/source3/namebrowse.c index 494315ec81..b426bc7a15 100644 --- a/source3/namebrowse.c +++ b/source3/namebrowse.c @@ -23,9 +23,6 @@ 14 jan 96: lkcl@pires.co.uk added multiple workgroup domain master support - 30 July 96: David.Chappell@mail.trincoll.edu - Expanded multiple workgroup domain master browser support. - */ #include "includes.h" @@ -74,21 +71,21 @@ void expire_browse_cache(time_t t) for (b = browserlist; b; b = nextb) { if (b->synced && b->sync_time < t) - { - DEBUG(3,("Removing dead cached browser %s\n",b->name)); - nextb = b->next; - - if (b->prev) b->prev->next = b->next; - if (b->next) b->next->prev = b->prev; - - if (browserlist == b) browserlist = b->next; - - free(b); - } + { + DEBUG(3,("Removing dead cached browser %s\n",b->name)); + nextb = b->next; + + if (b->prev) b->prev->next = b->next; + if (b->next) b->next->prev = b->prev; + + if (browserlist == b) browserlist = b->next; + + free(b); + } else - { - nextb = b->next; - } + { + nextb = b->next; + } } } @@ -97,7 +94,7 @@ void expire_browse_cache(time_t t) add a browser entry ****************************************************************************/ 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; @@ -112,9 +109,9 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, if (b && b->synced) { /* 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", - b->name, b->group, inet_ntoa(b->ip), b->sync_time)); + b->name, b->group, inet_ntoa(b->ip), b->sync_time)); return NULL; } @@ -149,12 +146,12 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, add_browse_cache(b); 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 { 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); @@ -169,23 +166,23 @@ static void start_sync_browse_entry(struct browse_cache_record *b) struct subnet_record *d; 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; - + /* only sync if we are the master */ if (AM_MASTER(work)) { - + /* first check whether the group we intend to sync with exists. if it doesn't, the server must have died. o dear. */ - + /* see response_netbios_packet() or expire_netbios_response_entries() */ queue_netbios_packet(d,ClientNMB,NMB_QUERY, b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, - work->token,b->group,0x20,0,0,0,0,NULL,NULL, - False,False,b->ip,b->ip); + b->group,0x20,0,0,0,NULL,NULL, + False,False,b->ip,b->ip); } - + b->synced = True; } diff --git a/source3/nameconf.c b/source3/nameconf.c index 2e1bdf5c79..99951a3b0e 100644 --- a/source3/nameconf.c +++ b/source3/nameconf.c @@ -58,12 +58,10 @@ struct smbbrowse char work_name[16]; /* workgroup name */ 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 */ - BOOL should_workgroup_member; /* should we be a member of this workgroup? */ - BOOL should_local_master; /* should we be a master browser? */ - BOOL should_preferred_master; /* should we initiate attempts to become a master browser? */ - BOOL should_domain_master; /* should we be the domain master browser? */ - BOOL should_domain_logon; /* should we be the domain logon? */ -}; + BOOL should_workgroup_member; /* should we try to become a member of this workgroup? */ + BOOL should_local_master; /* should we try to become a master browser? */ + BOOL should_domain_master; /* should we try to become the domain master browser? */ +} ; /* The whole list */ static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL; @@ -89,7 +87,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model, { struct smbbrowse *new; - if ( ! (array_size > nexttoken) ) + if( ! (array_size > nexttoken) ) { array_size += 10; smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups, @@ -98,7 +96,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model, new = &smbbrowse_workgroups[nexttoken]; - if (model != (struct smbbrowse *)NULL ) + if(model != (struct smbbrowse *)NULL ) memcpy(new, model, sizeof(struct smbbrowse)); else memset(new, 0, sizeof(struct smbbrowse)); @@ -129,22 +127,22 @@ int conf_workgroup_name_to_token(char *workgroup_name,char *default_name) int idx; /* 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; } } /* 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], workgroup_name, default_name); - w->should_workgroup_member = True; + w->should_workgroup_member = False; 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) { - if (token < 0 || token >= nexttoken) + if(token < 0 || token >= nexttoken) { DEBUG(0, ("range_check(): failed\n")); return True; @@ -174,25 +172,12 @@ static int range_check(int token) */ char *conf_workgroup_name(int token) { - if (range_check(token)) + if(range_check(token)) return (char*)NULL; 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 ** to become a master browser. @@ -200,7 +185,7 @@ int conf_should_preferred_master(int token) int conf_should_workgroup_member(int token) { - if (range_check(token)) + if(range_check(token)) return False; return smbbrowse_workgroups[token].should_workgroup_member; @@ -211,22 +196,12 @@ int conf_should_workgroup_member(int token) ** to become a master browser. */ 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; -} - -/* -** 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 @@ -234,7 +209,7 @@ int conf_should_domain_logon(int token) */ int conf_should_domain_master(int token) { - if (range_check(token)) + if(range_check(token)) return False; return smbbrowse_workgroups[token].should_domain_master; @@ -244,12 +219,12 @@ int conf_should_domain_master(int token) ** Given a token, return the name. */ char *conf_browsing_alias(int token) -{ - if (range_check(token)) + { + if(range_check(token)) return (char*)NULL; return smbbrowse_workgroups[token].browsing_alias; -} + } /* ** 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) { - if (range_check(token)) + if(range_check(token)) return (char*) NULL; - return lp_server_comment(); -} + return "Browser"; + } /* ** 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)); - for (x=0; x < nexttoken; x++) + for(x=0; x < nexttoken; x++) { 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")); return smbbrowse_workgroups[x].work_name; @@ -295,9 +270,9 @@ int conf_alias_to_token(char *alias) { 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; } @@ -315,19 +290,15 @@ static void default_smbbrowse_conf(char *default_name) /* The workgroup specified in smb.conf */ w = new_workgroup((struct smbbrowse *)NULL, lp_workgroup(), default_name); - w->should_local_master = lp_local_master(); - w->should_domain_master = lp_domain_master(); - w->should_domain_logon = lp_domain_logons(); + w->should_local_master = lp_preferred_master(); + w->should_domain_master = lp_domain_master(); w->should_workgroup_member = True; - /* default action: allow any new workgroup to be added. this is - _not_ the same as the old 1.9.14-1.9.15 definition of "*" - */ + /* default action: allow any new workgroup to be added */ w = new_workgroup((struct smbbrowse *)NULL, "*", default_name); - w->should_local_master = False; - w->should_domain_master = False; + w->should_local_master = False; + w->should_domain_master = 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; w = new_workgroup((struct smbbrowse *)NULL, work_name, default_name); - w->should_local_master = lp_local_master(); - w->should_domain_master = lp_domain_master(); - w->should_preferred_master = lp_preferred_master(); - w->should_domain_logon = lp_domain_logons(); + w->should_local_master = lp_local_master(); + w->should_domain_master = lp_domain_master(); w->should_workgroup_member = True; } diff --git a/source3/namedbname.c b/source3/namedbname.c index f084424a29..1f16553b0f 100644 --- a/source3/namedbname.c +++ b/source3/namedbname.c @@ -27,10 +27,6 @@ 04 jul 96: lkcl@pires.co.uk 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" @@ -47,16 +43,6 @@ extern struct subnet_record *subnetlist; 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 @@ -66,14 +52,14 @@ static char *source_description[] = ****************************************************************************/ void set_samba_nb_type(void) { - if (lp_wins_support() || (*lp_wins_server())) - { - nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ - } - else - { - nb_type = NB_BFLAG; /* samba is broadcast-only node type */ - } + if (lp_wins_support() || (*lp_wins_server())) + { + nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ + } + else + { + 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) { return n1->name_type == n2->name_type && - strequal(n1->name ,n2->name ) && + strequal(n1->name ,n2->name ) && 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. **************************************************************************/ struct name_record *find_name(struct name_record *n, - struct nmb_name *name, - int search) + struct nmb_name *name, + int search) { - struct name_record *ret; + struct name_record *ret; - for (ret = n; ret; ret = ret->next) - { - if (name_equal(&ret->name,name)) - { - /* self search: self names only */ - if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) - continue; - - return ret; - } - } + for (ret = n; ret; ret = ret->next) + { + if (name_equal(&ret->name,name)) + { + /* self search: self names only */ + if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) + continue; + + return ret; + } + } return NULL; } @@ -182,31 +168,29 @@ struct name_record *find_name(struct name_record *n, FIND_WINS - look for names in the WINS record **************************************************************************/ struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip) + struct nmb_name *name, + int search, struct in_addr ip) { - if (d == NULL) return NULL; /* bad error! */ - - if (search & FIND_LOCAL) - { - if (*d != NULL) - { - struct name_record *n = find_name((*d)->namelist, name, search); - DEBUG(4,("find_name on local: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - if (n) return n; - } + if (d == NULL) return NULL; /* bad error! */ + + if (search & FIND_LOCAL) { + if (*d != NULL) { + struct name_record *n = find_name((*d)->namelist, name, search); + DEBUG(4,("find_name on local: %s %s search %x\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. */ *d = find_subnet(ipgrp); - + if (*d == NULL) return NULL; - + 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); } @@ -244,18 +228,20 @@ void dump_names(void) { int i; - DEBUG(3,("%-15s ", inet_ntoa(d->bcast_ip))); - DEBUG(3,("%-19s TTL=%7ld %s ", - namestr(&n->name), - n->death_time?n->death_time-t:0, source_description[n->source])); + DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip))); + DEBUG(3,("%15s ", inet_ntoa(d->mask_ip))); + DEBUG(3,("%-19s TTL=%ld ", + namestr(&n->name), + n->death_time?n->death_time-t:0)); for (i = 0; i < n->num_ips; i++) { - DEBUG(3,("%-15s NB=%2x ", - inet_ntoa(n->ip_flgs[i].ip), - (unsigned char)n->ip_flgs[i].nb_flags)); + DEBUG(3,("%15s NB=%2x source=%d", + inet_ntoa(n->ip_flgs[i].ip), + 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) { @@ -263,16 +249,16 @@ void dump_names(void) anything other than as a hexadecimal number :-) */ fprintf(f, "%s#%02x %ld ", - n->name.name,n->name.name_type, /* XXXX ignore scope for now */ - n->death_time); + n->name.name,n->name.name_type, /* XXXX ignore scope for now */ + n->death_time); for (i = 0; i < n->num_ips; i++) { fprintf(f, "%s %2x ", - inet_ntoa(n->ip_flgs[i].ip), - (unsigned char)n->ip_flgs[i].nb_flags); + inet_ntoa(n->ip_flgs[i].ip), + n->ip_flgs[i].nb_flags); } - fprintf(f, "\n"); + fprintf(f, "\n"); } } @@ -321,12 +307,12 @@ void load_netbios_names(void) int type = 0; unsigned int nb_flags; time_t ttd; - struct in_addr ipaddr; + struct in_addr ipaddr; - enum name_source source; + enum name_source source; char *ptr; - int count = 0; + int count = 0; char *p; @@ -334,20 +320,20 @@ void load_netbios_names(void) if (*line == '#') continue; - ptr = line; + ptr = line; - if (next_token(&ptr,name_str ,NULL)) ++count; - if (next_token(&ptr,ttd_str ,NULL)) ++count; - if (next_token(&ptr,ip_str ,NULL)) ++count; - if (next_token(&ptr,nb_flags_str,NULL)) ++count; + if (next_token(&ptr,name_str ,NULL)) ++count; + if (next_token(&ptr,ttd_str ,NULL)) ++count; + if (next_token(&ptr,ip_str ,NULL)) ++count; + if (next_token(&ptr,nb_flags_str,NULL)) ++count; - if (count <= 0) continue; + if (count <= 0) continue; - if (count != 4) { - DEBUG(0,("Ill formed wins line")); - DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); - continue; - } + if (count != 4) { + DEBUG(0,("Ill formed wins line")); + DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); + continue; + } /* netbios name. # divides the name from the type (hex): netbios#xx */ strcpy(name,name_str); @@ -355,15 +341,15 @@ void load_netbios_names(void) p = strchr(name,'#'); if (p) { - *p = 0; - sscanf(p+1,"%x",&type); + *p = 0; + sscanf(p+1,"%x",&type); } /* decode the netbios flags (hex) and the time-to-die (seconds) */ - sscanf(nb_flags_str,"%x",&nb_flags); - sscanf(ttd_str,"%ld",&ttd); + sscanf(nb_flags_str,"%x",&nb_flags); + sscanf(ttd_str,"%ld",&ttd); - ipaddr = *interpret_addr2(ip_str); + ipaddr = *interpret_addr2(ip_str); if (ip_equal(ipaddr,ipzero)) { source = SELF; @@ -374,7 +360,7 @@ void load_netbios_names(void) } 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 */ if (ttd - 60 > time(NULL) || ttd == 0) @@ -394,8 +380,8 @@ void load_netbios_names(void) remove an entry from the name list ****************************************************************************/ void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip) + char *name,int type, enum name_source source, + struct in_addr ip) { struct nmb_name nn; 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, - char *name, int type, int nb_flags, - int ttl, enum name_source source, struct in_addr ip, - BOOL new_only,BOOL wins) + char *name, int type, int nb_flags, + int ttl, enum name_source source, struct in_addr ip, + BOOL new_only,BOOL wins) { struct name_record *n; struct name_record *n2=NULL; int search = 0; - BOOL self; - - if (iface_ip(ip)) - { - source = SELF; - putip(&ip, &ipzero); - } - - self = source == SELF; + BOOL self = source == SELF; /* add the name to the WINS list if the name comes from a directed query */ 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); 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); } /******************************************************************* - expires or refreshes old names in the namelist - - if the name is a samba SELF name, it must be refreshed rather than - removed. + expires old names in the namelist ******************************************************************/ -void check_expire_names(time_t t) +void expire_names(time_t t) { - struct name_record *n; - struct name_record *next; - struct subnet_record *d; - - /* expire old names */ - for (d = subnetlist; d; d = d->next) - { - for (n = d->namelist; n; n = next) - { - next = n->next; - - if (n->death_time && n->death_time < t) - { - if (n->source == SELF) - { - /* refresh the samba name. if this refresh fails - for any reason, it will be deleted. - */ - DEBUG(3,("Refreshing SELF name %s\n", namestr(&n->name))); - add_my_name_entry(d, -1, - n->name.name, n->name.name_type, - n->ip_flgs[0].nb_flags); - continue; - } - - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - 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); - } - } - } + struct name_record *n; + struct name_record *next; + struct subnet_record *d; + + /* expire old names */ + for (d = subnetlist; d; d = d->next) + { + for (n = d->namelist; n; n = next) + { + next = n->next; + if (n->death_time && n->death_time < t) + { + if (n->source == SELF) { + DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name))); + n->death_time += 300; + continue; + } + DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); + + 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 ****************************************************************************/ struct name_record *search_for_name(struct subnet_record **d, - struct nmb_name *question, - struct in_addr ip, int Time, int search) + struct nmb_name *question, + struct in_addr ip, int Time, int search) { int name_type = question->name_type; 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 */ if (!dns_type && name_type != 0x1b) - { - DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); - return NULL; - } + { + DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); + return NULL; + } /* look it up with DNS */ a = interpret_addr(qname); @@ -582,18 +549,18 @@ struct name_record *search_for_name(struct subnet_record **d, putip((char *)&dns_ip,(char *)&a); if (!a) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - DEBUG(3,("no recursion.\n")); + { + /* no luck with DNS. We could possibly recurse here XXXX */ + DEBUG(3,("no recursion.\n")); /* 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, - True, True); - return NULL; - } + add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, + True, True); + return NULL; + } /* 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, - True,True); + True,True); /* failed to add it? yikes! */ if (!n) return NULL; diff --git a/source3/namedbresp.c b/source3/namedbresp.c index aad6188384..d89bfe8ae8 100644 --- a/source3/namedbresp.c +++ b/source3/namedbresp.c @@ -92,9 +92,8 @@ void remove_response_record(struct subnet_record *d, create a name query response record **************************************************************************/ struct response_record *make_response_queue_record(enum state_type state, - int id,uint16 fd, int quest_type, - int token, char *name,int type, - enum name_source source, int nb_flags, time_t ttl, + int id,uint16 fd, + int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, 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->fd = fd; n->quest_type = quest_type; - - n->token = token; make_nmb_name(&n->name, name, type, scope); + n->nb_flags = nb_flags; n->ttl = ttl; - n->source = source; n->server_type = server_type; n->bcast = bcast; n->recurse = recurse; - n->reply.nb_flags = nb_flags; - n->reply.ip = reply_to_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_comment, n->my_comment, sizeof(n->my_comment)-1); diff --git a/source3/namedbserver.c b/source3/namedbserver.c index 260f8f3475..afb1dc1431 100644 --- a/source3/namedbserver.c +++ b/source3/namedbserver.c @@ -50,7 +50,7 @@ extern BOOL updatedlists; remove_all_servers indicates everybody dies. ******************************************************************/ void remove_old_servers(struct work_record *work, time_t t, - BOOL remove_all) + BOOL remove_all) { struct server_record *s; 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) { if (remove_all || (s->death_time && (t == -1 || s->death_time < t))) - { - DEBUG(3,("Removing dead server %s\n",s->serv.name)); - updatedlists = True; - nexts = s->next; - - if (s->prev) s->prev->next = s->next; - if (s->next) s->next->prev = s->prev; - - if (work->serverlist == s) - work->serverlist = s->next; - - free(s); - } + { + DEBUG(3,("Removing dead server %s\n",s->serv.name)); + updatedlists = True; + nexts = s->next; + + if (s->prev) s->prev->next = s->next; + if (s->next) s->next->prev = s->prev; + + if (work->serverlist == s) + work->serverlist = s->next; + + free(s); + } 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 *ret; + struct server_record *ret; - if (!work) return NULL; - - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - { - return ret; - } - } + if (!work) return NULL; + + for (ret = work->serverlist; ret; ret = ret->next) + { + if (strequal(ret->serv.name,name)) + { + return ret; + } + } return NULL; } @@ -126,15 +126,14 @@ struct server_record *find_server(struct work_record *work, char *name) add a server entry ****************************************************************************/ struct server_record *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace) + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, + BOOL replace) { BOOL newentry=False; struct server_record *s; - int token = conf_workgroup_name_to_token(work->work_group, myname); - + if (name[0] == '*') { return (NULL); @@ -161,14 +160,16 @@ struct server_record *add_server_entry(struct subnet_record *d, bzero((char *)s,sizeof(*s)); } - if (conf_should_workgroup_member(token)) - { - if (servertype) servertype |= SV_TYPE_LOCAL_LIST_ONLY; - } + + if (strequal(lp_workgroup(),work->work_group)) + { + if (servertype) + servertype |= SV_TYPE_LOCAL_LIST_ONLY; + } else - { + { servertype &= ~SV_TYPE_LOCAL_LIST_ONLY; - } + } /* update the entry */ 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", - name,servertype,comment, - work->work_group,inet_ntoa(d->bcast_ip))); + name,servertype,comment, + work->work_group,inet_ntoa(d->bcast_ip))); return(s); } @@ -212,9 +213,9 @@ void expire_servers(time_t t) struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - remove_old_servers(work, t, False); - } + { + remove_old_servers(work, t, False); + } } } diff --git a/source3/namedbsubnet.c b/source3/namedbsubnet.c index 9c7fb1e8dc..0bad79246a 100644 --- a/source3/namedbsubnet.c +++ b/source3/namedbsubnet.c @@ -26,9 +26,6 @@ 04 jul 96: lkcl@pires.co.uk 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" @@ -93,16 +90,16 @@ struct subnet_record *find_subnet(struct in_addr bcast_ip) for (d = subnetlist; d; d = d->next) { if (ip_equal(bcast_ip, wins_ip)) - { + { if (ip_equal(bcast_ip, d->bcast_ip)) { return d; } } else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) - { - return(d); - } + { + return(d); + } } 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) { - struct interface *i; - - /* loop on all local interfaces */ - for (i = local_interfaces; i; i = i->next) - { - /* add the interface into our subnet database */ - if (!find_subnet(i->bcast)) - { - make_subnet(i->bcast,i->nmask); - } - } - - /* add the pseudo-ip interface for WINS: 255.255.255.255 */ - if (lp_wins_support() || (*lp_wins_server())) + struct interface *i; + + /* loop on all local interfaces */ + for (i = local_interfaces; i; i = i->next) + { + /* add the interface into our subnet database */ + if (!find_subnet(i->bcast)) + { + make_subnet(i->bcast,i->nmask); + } + } + + /* add the pseudo-ip interface for WINS: 255.255.255.255 */ + if (lp_wins_support() || (*lp_wins_server())) { - struct in_addr wins_bcast = ipgrp; - struct in_addr wins_nmask = ipzero; - make_subnet(wins_bcast, wins_nmask); + struct in_addr wins_bcast = ipgrp; + struct in_addr wins_nmask = ipzero; + 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 **************************************************************************/ -void add_workgroups_to_subnets() +void add_my_subnets(char *group) { struct interface *i; /* add or find domain on our local subnet, in the default workgroup */ + + if (*group == '*') return; - for (i = local_interfaces; i; i = i->next) - { - int token; - for (token = 0; token < get_num_workgroups(); token++) + /* 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 + messed up! */ + 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. ****************************************************************************/ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, - char *name, BOOL add, BOOL lmhosts) + struct in_addr mask_ip, + char *name, BOOL add, BOOL lmhosts) { 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 */ - 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)) + if ((d = find_subnet(bcast_ip)) || + (d = make_subnet(bcast_ip, mask_ip))) { - /* add samba server name to workgroup list. don't add - lmhosts server entries to local interfaces */ - - 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); - + struct work_record *w = find_workgroupstruct(d, name, add); + + if (!w) return NULL; + + /* 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", 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; } @@ -307,31 +290,31 @@ void write_browse_list(void) { struct work_record *work; for (work = d->workgrouplist; work ; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s ; s = s->next) - { - fstring tmp; - - /* don't list domains I don't have a master for */ - if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) - { - continue; - } - - /* output server details, plus what workgroup/domain - they're in. without the domain information, the - combined list of all servers in all workgroups gets - sent to anyone asking about any workgroup! */ - - sprintf(tmp, "\"%s\"", s->serv.name); - fprintf(f, "%-25s ", tmp); - fprintf(f, "%08x ", s->serv.type); - sprintf(tmp, "\"%s\" ", s->serv.comment); - fprintf(f, "%-30s", tmp); - fprintf(f, "\"%s\"\n", work->work_group); - } - } + { + struct server_record *s; + for (s = work->serverlist; s ; s = s->next) + { + fstring tmp; + + /* don't list domains I don't have a master for */ + if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) + { + continue; + } + + /* output server details, plus what workgroup/domain + they're in. without the domain information, the + combined list of all servers in all workgroups gets + sent to anyone asking about any workgroup! */ + + sprintf(tmp, "\"%s\"", s->serv.name); + fprintf(f, "%-25s ", tmp); + fprintf(f, "%08x ", s->serv.type); + sprintf(tmp, "\"%s\" ", s->serv.comment); + fprintf(f, "%-30s", tmp); + fprintf(f, "\"%s\"\n", work->work_group); + } + } } fclose(f); diff --git a/source3/namedbwork.c b/source3/namedbwork.c index dd4bd88175..04f2103254 100644 --- a/source3/namedbwork.c +++ b/source3/namedbwork.c @@ -26,9 +26,6 @@ 04 jul 96: lkcl@pires.co.uk 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" @@ -43,7 +40,9 @@ extern struct subnet_record *subnetlist; 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 @@ -76,17 +75,11 @@ static void add_workgroup(struct work_record *work, struct subnet_record *d) static struct work_record *make_workgroup(char *name) { struct work_record *work; + struct subnet_record *d; int t = -1; 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)); if (!work) return(NULL); @@ -99,16 +92,34 @@ static struct work_record *make_workgroup(char *name) work->needelection = False; work->needannounce = True; 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 */ /* Win95 uses 01041501 */ /* NTAS uses ???????? */ work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8); work->ElectionCriterion |= (lp_os_level() << 24); - - if (conf_should_domain_master(work->token)) - { + if (lp_domain_master()) { work->ElectionCriterion |= 0x80; } @@ -120,8 +131,8 @@ static struct work_record *make_workgroup(char *name) remove workgroups ******************************************************************/ struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers) + struct work_record *work, + BOOL remove_all_servers) { struct work_record *ret_work = NULL; @@ -154,7 +165,7 @@ struct work_record *remove_workgroup(struct subnet_record *d, lmhosts file to be added. **************************************************************************/ struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add) + fstring name, BOOL add) { 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)); 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))); + 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 + 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)) - { + for (ret = d->workgrouplist; ret; ret = ret->next) { + if (!strcmp(ret->work_group,name)) { DEBUG(4, ("found\n")); return(ret); } } - if (!add) - { + if (!add) { DEBUG(4, ("not found\n")); return NULL; } DEBUG(4,("not found: creating\n")); - if ((work = make_workgroup(name)) != NULL) - { - 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)) + if ((work = make_workgroup(name))) { - DEBUG(3, ("preferred master startup for %s\n", work->work_group)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } + if (!ip_equal(d->bcast_ip, ipgrp) && + lp_preferred_master() && + 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); return(work); } @@ -225,25 +224,25 @@ void dump_workgroups(void) for (d = subnetlist; d; d = d->next) { if (d->workgrouplist) - { - struct work_record *work; - - DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); - DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); - - for (work = d->workgrouplist; work; work = work->next) - { - DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); - if (work->serverlist) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - DEBUG(4,("\t\t%s %8x (%s)\n", - s->serv.name, s->serv.type, s->serv.comment)); - } - } - } - } + { + struct work_record *work; + + DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); + DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); + + for (work = d->workgrouplist; work; work = work->next) + { + DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); + if (work->serverlist) + { + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + DEBUG(4,("\t\t%s %8x (%s)\n", + s->serv.name, s->serv.type, s->serv.comment)); + } + } + } + } } } diff --git a/source3/nameelect.c b/source3/nameelect.c index 6c8a4751f4..be8a405daa 100644 --- a/source3/nameelect.c +++ b/source3/nameelect.c @@ -28,12 +28,10 @@ 04 jul 96: lkcl@pires.co.uk 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 ClientDGRAM; @@ -41,6 +39,7 @@ extern int ClientDGRAM; extern int DEBUGLEVEL; extern pstring scope; +extern pstring myname; extern struct in_addr ipzero; extern struct in_addr ipgrp; @@ -52,9 +51,6 @@ extern struct subnet_record *subnetlist; extern uint16 nb_type; /* samba's NetBIOS name type */ -extern pstring myname; - - /******************************************************************* occasionally check to see if the master browser is around ******************************************************************/ @@ -72,22 +68,22 @@ void check_master_browser(void) dump_workgroups(); 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 - find a browser on the subnet, do something about it. */ + struct work_record *work; - if (!AM_MASTER(work)) - { - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, - work->token, work->work_group,0x1d,REGISTER,0,0,0,NULL,NULL, - True,False,d->bcast_ip,d->bcast_ip); - } + for (work = d->workgrouplist; work; work = work->next) + { + /* if we are not the browse master of a workgroup, and we can't + find a browser on the subnet, do something about it. */ + + 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)) return; - if (conf_should_local_master(work->token)) + if (strequal(work->work_group, lp_workgroup())) { + 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 */ work->needelection = True; @@ -117,10 +114,10 @@ void browser_gone(char *work_name, struct in_addr ip) else { /* 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 - 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); } @@ -131,7 +128,7 @@ void browser_gone(char *work_name, struct in_addr ip) send an election packet **************************************************************************/ void send_election(struct subnet_record *d, char *group,uint32 criterion, - int timeup,char *name) + int timeup,char *name) { pstring outbuf; char *p; @@ -139,7 +136,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion, if (!d) return; 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)); p = outbuf; @@ -155,7 +152,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion, p = skip_string(p,1); 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 (!AM_MASTER(work) && !AM_DMBRSE(work)) return; - 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))) { 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; if (name_type == 0x1b) remove_type = SV_TYPE_DOMAIN_MASTER; - + 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. **************************************************************************/ -void name_register_work(struct subnet_record *d, int token, - char *name, int name_type, enum name_source source, - struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast) +void name_register_work(struct subnet_record *d, char *name, int name_type, + int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast) { + enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ? + SELF : REGISTER; + if (source == SELF) { - char *work_name = conf_workgroup_name(token); - struct work_record *work = find_workgroupstruct(d, work_name, False); + struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False); - add_netbios_entry(d,name,name_type,data->nb_flags, - ttl,source,data->ip,True,!bcast); + add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast); 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) { - pstring comment; - /* 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 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; - char *my_name ; - char *my_comment; - 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", - work->work_group,inet_ntoa(d->bcast_ip),work->state)); + work->work_group,inet_ntoa(d->bcast_ip),work->state)); switch (work->state) { @@ -295,10 +272,10 @@ void become_master(struct subnet_record *d, struct work_record *work) /* update our server status */ 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_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() */ return; @@ -309,11 +286,10 @@ void become_master(struct subnet_record *d, struct work_record *work) work->state = MST_MSB; /* ... registering MSBROWSE was successful */ /* add server entry on successful registration of MSBROWSE */ - add_server_entry(d,work,work->work_group, - domain_type,0,conf_browsing_alias(work->token),True); + add_server_entry(d,work,work->work_group,domain_type,0,myname,True); /* 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() */ return; @@ -325,8 +301,7 @@ void become_master(struct subnet_record *d, struct work_record *work) /* update our server status */ work->ServerType |= SV_TYPE_MASTER_BROWSER; - add_server_entry(d,work,conf_browsing_alias(work->token), - work->ServerType,0,comment,True); + add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True); 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: { - if (conf_should_domain_master(work->token)) + if (lp_domain_master()) { work->state = MST_DOMAIN_MEM; /* ... become domain member */ DEBUG(3,("domain first stage: register as domain member\n")); /* add domain member name */ - add_my_name_entry(d,work->token,work->work_group,0x1e, - nb_type|NB_ACTIVE|NB_GROUP); + add_my_name_entry(d,work->work_group,0x1e,nb_type|NB_ACTIVE|NB_GROUP); /* DON'T do anything else after calling add_my_name_entry() */ return; @@ -368,20 +342,19 @@ void become_master(struct subnet_record *d, struct work_record *work) case MST_DOMAIN_MEM: { - if (conf_should_domain_master(work->token)) + if (lp_domain_master()) { work->state = MST_DOMAIN_TST; /* ... possibly become domain master */ 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; - 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_my_name_entry(d,work->token,work->work_group,0x1b, - nb_type|NB_ACTIVE ); + add_my_name_entry(d,work->work_group,0x1b,nb_type|NB_ACTIVE ); /* DON'T do anything else after calling add_my_name_entry() */ 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... */ { /* update our server status */ - if (conf_should_domain_master(work->token)) + if (lp_domain_master()) { struct subnet_record *d1; - uint32 update_type = 0; + uint32 update_type = 0; DEBUG(3,("domain third stage: samba is now a domain master.\n")); 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 | SV_TYPE_POTENTIAL_BROWSER; - work->ServerType |= update_type; - add_server_entry(d,work,my_name,work->ServerType,0,comment,True); - - for (d1 = subnetlist; d1; d1 = d1->next) - { - struct work_record *w; - if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; - - for (w = d1->workgrouplist; w; w = w->next) - { - struct server_record *s = find_server(w, my_name); - if (strequal(w->work_group, work->work_group)) - { - w->ServerType |= update_type; - } - if (s) - { - s->serv.type |= update_type; - DEBUG(4,("found server %s on %s: update to %8x\n", - s->serv.name, inet_ntoa(d1->bcast_ip), - s->serv.type)); - } - } - } + work->ServerType |= update_type; + add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True); + + for (d1 = subnetlist; d1; d1 = d1->next) + { + struct work_record *w; + if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; + + for (w = d1->workgrouplist; w; w = w->next) + { + struct server_record *s = find_server(w, myname); + if (strequal(w->work_group, work->work_group)) + { + w->ServerType |= update_type; + } + if (s) + { + s->serv.type |= update_type; + DEBUG(4,("found server %s on %s: update to %8x\n", + s->serv.name, inet_ntoa(d1->bcast_ip), + s->serv.type)); + } + } + } } 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. ******************************************************************/ void become_nonmaster(struct subnet_record *d, struct work_record *work, - int remove_type) + int remove_type) { int new_server_type = work->ServerType; - pstring comment; - - 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)); + DEBUG(2,("Becoming non-master for %s\n",work->work_group)); /* can only remove master or domain types with this function */ 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; new_server_type &= ~remove_type; - state = work->state; 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->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; if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER)) { - if (state == MST_DOMAIN) - { - if (wins) - work->state = MST_NONE; - else - work->state = MST_BROWSER; - } - remove_name_entry(d,work->token,work->work_group,0x1b); + if (work->state == MST_DOMAIN) + work->state = MST_BROWSER; + remove_name_entry(d,work->work_group,0x1b); } if (!(work->ServerType & SV_TYPE_MASTER_BROWSER)) { - if (state >= MST_BROWSER) + if (work->state >= MST_BROWSER) work->state = MST_NONE; - remove_name_entry(d,work->token,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; + remove_name_entry(d,work->work_group,0x1d); } } @@ -547,27 +490,25 @@ void run_elections(void) { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - if (work->RunningElection) - { - char *alias = conf_browsing_alias(work->token); - - send_election(d,work->work_group, work->ElectionCriterion, - 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); - } - } - } + { + if (work->RunningElection) + { + 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; + + become_master(d, work); + } + } + } } } @@ -576,7 +517,7 @@ void run_elections(void) work out if I win an election ******************************************************************/ 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; 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(True); - if (strcasecmp(conf_browsing_alias(work->token),name) > 0) return(False); + if (strcasecmp(myname,name) > 0) return(False); return(True); } @@ -634,38 +575,30 @@ void process_election(struct packet_struct *p,char *buf) if (same_context(dgram)) return; for (work = d->workgrouplist; work; work = work->next) - { - if (!conf_should_local_master(work->token)) continue; - - if (win_election(work, version,criterion,timeup,name)) - { - if (!work->RunningElection) - { - work->needelection = True; - 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 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); - } - } + if (!strequal(work->work_group, lp_workgroup())) + continue; + + if (win_election(work, version,criterion,timeup,name)) { + if (!work->RunningElection) { + work->needelection = True; + 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); + } + } } - } } @@ -686,18 +619,18 @@ BOOL check_elections(void) { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - run_any_election |= work->RunningElection; - - if (work->needelection && !work->RunningElection) - { - DEBUG(3,(">>> Starting election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - work->ElectionCount = 0; - work->RunningElection = True; - work->needelection = False; - } - } + { + run_any_election |= work->RunningElection; + + if (work->needelection && !work->RunningElection) + { + DEBUG(3,(">>> Starting election on %s %s <<<\n", + work->work_group,inet_ntoa(d->bcast_ip))); + work->ElectionCount = 0; + work->RunningElection = True; + work->needelection = False; + } + } } return run_any_election; } diff --git a/source3/namelogon.c b/source3/namelogon.c index 6b3b2e01ed..aacf32c280 100644 --- a/source3/namelogon.c +++ b/source3/namelogon.c @@ -21,11 +21,7 @@ Revision History: 14 jan 96: lkcl@pires.co.uk - added domain master browser support - - 30 aug 96: lkcl@pires.co.uk - added multiple domain logon support, using extensions to David Chappell's - multiple domain master browser code. + added multiple workgroup domain master support */ @@ -33,8 +29,13 @@ extern int ClientDGRAM; +#define TEST_CODE /* want to debug unknown browse packets */ + extern int DEBUGLEVEL; +extern pstring myname; + + /**************************************************************************** process a domain logon packet @@ -53,18 +54,14 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) pstring outbuf; int code,reply_code; struct work_record *work; - char *my_name; - + if (!d) return; if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) return; - if ((my_name = conf_browsing_alias(work->token)) == NULL) return; - - if (!conf_should_domain_logon(work->token)) - { - DEBUG(3,("No domain logons for %s (%s)\n", work->work_group, my_name)); + if (!lp_domain_logons()) { + DEBUG(3,("No domain logons\n")); return; } @@ -76,7 +73,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) char *user = skip_string(machine,1); logname = skip_string(user,1); reply_code = 6; - strcpy(reply_name, my_name); + strcpy(reply_name,myname); strupper(reply_name); add_slashes = True; 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; strcpy(reply_name,lp_domain_controller()); if (!*reply_name) { - strcpy(reply_name,my_name); + strcpy(reply_name,myname); reply_code = 0xC; } strupper(reply_name); @@ -124,8 +121,8 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) PutUniCode(q,reply_name); q += 2*(strlen(reply_name) + 1); - PutUniCode(q,work->work_group); - q += 2*(strlen(work->work_group) + 1); + PutUniCode(q,lp_workgroup()); + q += 2*(strlen(lp_workgroup()) + 1); SIVAL(q,0,1); q += 4; @@ -137,6 +134,6 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) q += 2; 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)); } diff --git a/source3/namepacket.c b/source3/namepacket.c index 121cf26eb0..5bfa55d4f1 100644 --- a/source3/namepacket.c +++ b/source3/namepacket.c @@ -38,165 +38,90 @@ BOOL CanRecurse = True; extern pstring scope; 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) +/*************************************************************************** + updates the unique transaction identifier + **************************************************************************/ +void debug_browse_data(char *outbuf, int len) { - 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) + int i,j; + for (i = 0; i < len; i+= 16) { - DEBUG(2,("netbios release packet rejected\n")); - break; + DEBUG(4, ("%3x char ", i)); + + for (j = 0; j < 16; j++) + { + unsigned char x = outbuf[i+j]; + if (x < 32 || x > 127) x = '.'; + + if (i+j >= len) break; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", outbuf[i+j])); + } + + DEBUG(4, ("\n")); } - if (nmb->header.response) - { - if (nmb->header.ancount==0) break; - response_netbios_packet(p); - } - else - { - reply_name_release(p); - } - break; - } - } } /*************************************************************************** updates the unique transaction identifier **************************************************************************/ -void debug_browse_data(char *outbuf, int len) +static void update_name_trn_id(void) { - int i,j; - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = outbuf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", (unsigned char)outbuf[i+j])); - } - - DEBUG(4, ("\n")); - } - + 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 - - 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, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip) +void initiate_netbios_packet(uint16 *id, + int fd,int quest_type,char *name,int name_type, + int nb_flags,BOOL bcast,BOOL recurse, + struct in_addr to_ip) { struct packet_struct p; struct nmb_packet *nmb = &p.packet.nmb; struct res_rec additional_rec; - char *pkt_type = "unknown"; + char *packet_type = "unknown"; int opcode = -1; - if (quest_type == NMB_STATUS) { pkt_type = "nmb_status"; opcode = 0; } - 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_REG_REFRESH) { pkt_type="nmb_reg_refresh"; opcode=9; } - if (quest_type == NMB_REL ) { pkt_type = "nmb_rel"; opcode = 6; } + if (!id) return; + + if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; } + if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; } + 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", - 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)); - 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.response = False; @@ -237,7 +162,7 @@ BOOL initiate_netbios_packet(uint16 id, nmb->additional->rdlength = 6; nmb->additional->rdata[0] = nb_flags; putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip)); - } + } p.ip = to_ip; p.port = NMB_PORT; @@ -245,21 +170,12 @@ BOOL initiate_netbios_packet(uint16 id, p.timestamp = time(NULL); p.packet_type = NMB_PACKET; - if (zero_ip(to_ip)) /* samba's own ip */ - { - DEBUG(4,("process packet ourselves\n")); - /* respond internally to the packet. */ - process_nmb(&p); + if (!send_packet(&p)) { + DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port)); + *id = 0xffff; } - else - { - if (!send_packet(&p)) { - DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port)); - return False; - } - } - - return True; + + return; } @@ -267,9 +183,9 @@ BOOL initiate_netbios_packet(uint16 id, reply to a netbios name packet ****************************************************************************/ void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len) + int rcode, int rcv_code, int opcode, BOOL recurse, + struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, + char *data,int len) { struct packet_struct p; 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) { case NMB_STATUS: - { + { packet_type = "nmb_status"; recursion_desired = True; break; } case NMB_QUERY: - { + { packet_type = "nmb_query"; recursion_desired = True; break; } case NMB_REG: - { + { packet_type = "nmb_reg"; recursion_desired = True; break; } case NMB_REL: - { + { packet_type = "nmb_rel"; recursion_desired = False; break; } case NMB_WAIT_ACK: - { + { packet_type = "nmb_wack"; recursion_desired = False; break; @@ -314,14 +230,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, default: { 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; } } 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.opcode = opcode; @@ -349,25 +265,16 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, nmb->answers->ttl = ttl; if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } + { + nmb->answers->rdlength = len; + memcpy(nmb->answers->rdata, data, len); + } p.packet_type = NMB_PACKET; debug_nmb_packet(&p); - if (zero_ip(p.ip)) /* samba's own ip */ - { - DEBUG(4,("process response packet ourselves\n")); - /* respond internally to the packet. */ - process_nmb(&p); - } - else - { - send_packet(&p); - } + send_packet(&p); } @@ -445,7 +352,7 @@ static void process_dgram(struct packet_struct *p) buf = &dgram->data[0]; 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; @@ -453,8 +360,8 @@ static void process_dgram(struct packet_struct *p) buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n", - namestr(&dgram->source_name),namestr(&dgram->dest_name), - smb_buf(buf),CVAL(buf2,0),len)); + namestr(&dgram->source_name),namestr(&dgram->dest_name), + smb_buf(buf),CVAL(buf2,0),len)); 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 ******************************************************************/ @@ -482,15 +466,15 @@ void run_packet_queue() while ((p=packet_queue)) { switch (p->packet_type) - { - case NMB_PACKET: - process_nmb(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } + { + case NMB_PACKET: + process_nmb(p); + break; + + case DGRAM_PACKET: + process_dgram(p); + break; + } packet_queue = packet_queue->next; 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 **************************************************************************/ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, - char *dstname,int src_type,int dest_type, - struct in_addr dest_ip,struct in_addr src_ip) + char *dstname,int src_type,int dest_type, + struct in_addr dest_ip,struct in_addr src_ip) { struct packet_struct p; struct dgram_packet *dgram = &p.packet.dgram; diff --git a/source3/nameresp.c b/source3/nameresp.c index bd64fba2b6..7fcb41e79f 100644 --- a/source3/nameresp.c +++ b/source3/nameresp.c @@ -35,30 +35,15 @@ extern pstring scope; extern struct in_addr ipzero; 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 **************************************************************************/ 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", - 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); @@ -66,118 +51,118 @@ static void dead_netbios_entry(struct subnet_record *d, { 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 - unique and then remove it from our WINS database */ - - /* IMPORTANT: see query_refresh_names() */ - - if ((!NAME_GROUP(n->reply.nb_flags))) - { - struct subnet_record *d1 = find_subnet(ipgrp); - if (d1) - { - /* remove the name that had been registered with us, - and we're now getting no response when challenging. - see rfc1001.txt 15.5.2 - */ - remove_netbios_name(d1, n->name.name, n->name.name_type, - REGISTER, n->send_ip); - } - } - } - break; + /* oops. name query had no response. check that the name is + unique and then remove it from our WINS database */ + + /* IMPORTANT: see query_refresh_names() */ + + if ((!NAME_GROUP(n->nb_flags))) + { + struct subnet_record *d1 = find_subnet(ipgrp); + if (d1) + { + /* remove the name that had been registered with us, + and we're now getting no response when challenging. + see rfc1001.txt 15.5.2 + */ + remove_netbios_name(d1, n->name.name, n->name.name_type, + REGISTER, n->send_ip); + } + } + } + break; } - case NAME_QUERY_MST_CHK: - { - /* if no response received, the master browser must have gone - down on that subnet, without telling anyone. */ - - /* IMPORTANT: see response_netbios_packet() */ - - if (n->num_msgs == 0) - browser_gone(n->name.name, n->send_ip); - break; - } - - case NAME_RELEASE: - { - /* if no response received, it must be OK for us to release the - name. nobody objected (including a potentially dead or deaf - WINS server) */ - - /* IMPORTANT: see response_name_release() */ - - if (ismyip(n->send_ip)) - { - name_unregister_work(d,n->name.name,n->name.name_type); - } - if (!n->bcast) - { - DEBUG(0,("WINS server did not respond to name release!\n")); + case NAME_QUERY_MST_CHK: + { + /* if no response received, the master browser must have gone + down on that subnet, without telling anyone. */ + + /* IMPORTANT: see response_netbios_packet() */ + + if (n->num_msgs == 0) + browser_gone(n->name.name, n->send_ip); + break; + } + + case NAME_RELEASE: + { + /* if no response received, it must be OK for us to release the + name. nobody objected (including a potentially dead or deaf + WINS server) */ + + /* IMPORTANT: see response_name_release() */ + + if (ismyip(n->send_ip)) + { + name_unregister_work(d,n->name.name,n->name.name_type); + } + if (!n->bcast) + { + DEBUG(0,("WINS server did not respond to name release!\n")); /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - case NAME_REGISTER_CHALLENGE: - { - /* name challenge: no reply. we can reply to the person that - 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, - n->reply.nb_flags, GET_TTL(0), - n->reply.ip, False, n->reply.ip); - - if (!n->bcast) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); + } + break; + } + + case NAME_REGISTER_CHALLENGE: + { + /* name challenge: no reply. we can reply to the person that + 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, + n->nb_flags, GET_TTL(0), + n->reply_to_ip, False, n->reply_to_ip); + + if (!n->bcast) + { + DEBUG(1,("WINS server did not respond to name registration!\n")); /* XXXX whoops. we have problems. must deal with this */ - } + } break; - } - - case NAME_REGISTER: - { - /* if no response received, and we are using a broadcast registration - 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 - server must be dead or deaf. - */ - if (n->bcast) - { - /* broadcast method: implicit acceptance of the name registration - by not receiving any objections. */ - - /* IMPORTANT: see response_name_reg() */ - - name_register_work(d,n->token,n->name.name,n->name.name_type, - n->source, &n->reply, n->ttl, n->reply.ip, n->bcast); - } - else - { - /* received no response. rfc1001.txt states that after retrying, - we should assume the WINS server is dead, and fall back to - broadcasting (see bits about M nodes: can't find any right + } + + case NAME_REGISTER: + { + /* if no response received, and we are using a broadcast registration + 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 + server must be dead or deaf. + */ + if (n->bcast) + { + /* broadcast method: implicit acceptance of the name registration + by not receiving any objections. */ + + /* IMPORTANT: see response_name_reg() */ + + name_register_work(d,n->name.name,n->name.name_type, + n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); + } + else + { + /* received no response. rfc1001.txt states that after retrying, + we should assume the WINS server is dead, and fall back to + broadcasting (see bits about M nodes: can't find any right 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 */ - } - break; - } - - default: - { - /* nothing to do but delete the dead expected-response structure */ - /* this is normal. */ - break; - } + } + break; + } + + default: + { + /* nothing to do but delete the dead expected-response structure */ + /* this is normal. */ + break; + } } } @@ -199,52 +184,81 @@ void expire_netbios_response_entries() for (n = d->responselist; n; n = nextn) { - nextn = n->next; + nextn = n->next; if (n->repeat_time <= time(NULL)) - { - if (n->repeat_count > 0) - { - /* resend the entry */ - initiate_netbios_packet(n->response_id, n->fd, n->quest_type, - n->name.name, n->name.name_type, - n->reply.nb_flags, n->bcast, n->recurse, n->send_ip); + { + if (n->repeat_count > 0) + { + /* resend the entry */ + initiate_netbios_packet(&n->response_id, n->fd, n->quest_type, + n->name.name, n->name.name_type, + n->nb_flags, n->bcast, n->recurse, n->send_ip); n->repeat_time += n->repeat_interval; /* XXXX ms needed */ n->repeat_count--; - } - else - { + } + else + { 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))); - 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 */ - 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, - int fd,int quest_type,enum state_type state, - int token, char *name,int name_type, - enum name_source source, int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) +struct response_record *queue_netbios_pkt_wins(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + char *name,int name_type,int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip) { - queue_netbios_packet(d,fd, quest_type, state, - token, name, name_type, source, nb_flags, ttl, + /* XXXX note: please see rfc1001.txt section 10 for details on this + 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, - 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 master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get 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, - int fd,int quest_type,enum state_type state, - int token, char *name, int name_type, - enum name_source source, int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) +struct response_record *queue_netbios_packet(struct subnet_record *d, + int fd,int quest_type,enum state_type state,char *name, + int name_type,int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip) { + struct in_addr wins_ip = ipgrp; struct response_record *n; + uint16 id = 0xffff; /* 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 - 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 - */ + initiate_netbios_packet(&id, fd, quest_type, name, name_type, + nb_flags, bcast, recurse, send_ip); - 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 (id == 0xffff) { + DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip))); + return NULL; } - if (zero_ip(send_ip)) - { - /* doing a netbios query to samba as a WINS server, internally */ - if (lp_wins_support()) /* samba is a WINS server */ - { - DEBUG(4,("queue netbios packet with ourselves...\n")); - bcast = False; - } - else + if ((n = make_response_queue_record(state,id,fd, + quest_type,name,name_type,nb_flags,ttl, + server_type,my_name, my_comment, + bcast,recurse,send_ip,reply_to_ip))) { - return; + add_response_record(d,n); + return n; } - } - - 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; - } + return NULL; } diff --git a/source3/nameserv.c b/source3/nameserv.c index 6bdc95896f..c8bbb52811 100644 --- a/source3/nameserv.c +++ b/source3/nameserv.c @@ -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. ****************************************************************************/ -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 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 */ remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip); - if (ip_equal(d->bcast_ip, ipgrp)) - { - /* use WINS. this function can now be used to _either_ - do the release on samba's own database _or_ release - the name with an arbitrary WINS server */ + if (ip_equal(d->bcast_ip, ipgrp)) { + if (!lp_wins_support()) { + /* not a WINS server: we have to release them on the network */ 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); + } } else { /* local interface: release them on the network */ 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); } } @@ -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). ****************************************************************************/ -void add_my_name_entry(struct subnet_record *d, int token, - char *name,int type,int nb_flags) +void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) { BOOL re_reg = False; 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); 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 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 0 if (lp_wins_support()) { /* we are a WINS server. */ @@ -134,38 +131,26 @@ void add_my_name_entry(struct subnet_record *d, int token, actually be true */ - struct nmb_ip data; - - data.nb_flags = nb_flags; - putip(&data.ip, ipzero); - DEBUG(4,("samba as WINS server adding: ")); /* this will call add_netbios_entry() */ - - name_register_work(d,token,name,type,SELF,&data,GET_TTL(0),ipzero,False); + name_register_work(d, name, type, nb_flags,0, ipzero, False); } 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. */ - queue_netbios_pkt_wins(d,ClientNMB, - re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, - token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL, - False, True, ipzero, ipzero); -#if 0 + queue_netbios_pkt_wins(d,ClientNMB, + re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, + name, type, nb_flags, GET_TTL(0),0,NULL,NULL, + False, True, ipzero, ipzero); } -#endif } else { /* broadcast the packet, but it comes from ipzero */ - queue_netbios_packet(d,ClientNMB, - re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, - token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL, - True, True, d->bcast_ip, ipzero); + queue_netbios_packet(d,ClientNMB, + re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, + name, type, nb_flags, GET_TTL(0),0,NULL,NULL, + 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) { struct subnet_record *d; - int token; - /* each subnet entry, including WINS pseudo-subnet, has SELF names */ /* 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) { - BOOL wins = 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); - } - } + BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp); + 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 refreshed with the WINS server */ - 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__",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); + } } - - /* check becoming a domain master under all browser aliases */ - - if ((d = find_subnet(ipgrp))) + if (lp_domain_master() && (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)) - { - 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); - } - } - } + work->state = MST_DOMAIN_NONE; + become_master(d, work); } } } @@ -246,24 +205,52 @@ void add_my_names(void) **************************************************************************/ void remove_my_names() { - struct subnet_record *d; + struct subnet_record *d; + + 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) + for (d = subnetlist; d; d = d->next) + { + struct name_record *n; + + for (n = d->namelist; n; n = n->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, -1, n->name.name, n->name.name_type); - } - } + /* each SELF name has an individual time to be refreshed */ + if (n->source == SELF && n->refresh_time < time(NULL) && + n->death_time != 0) + { + add_my_name_entry(d,n->name.name,n->name.name_type, + n->ip_flgs[0].nb_flags); + /* they get a new lease on life :-) */ + n->death_time += GET_TTL(0); + n->refresh_time += GET_TTL(0); + } } + } } @@ -278,55 +265,55 @@ void remove_my_names() ******************************************************************/ void query_refresh_names(void) { - struct name_record *n; - struct subnet_record *d = find_subnet(ipgrp); + struct name_record *n; + struct subnet_record *d = find_subnet(ipgrp); - static time_t lasttime = 0; - time_t t = time(NULL); + static time_t lasttime = 0; + time_t t = time(NULL); - int count = 0; - int name_refresh_time = NAME_POLL_REFRESH_TIME; - int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; - if (max_count > 10) max_count = 10; + int count = 0; + int name_refresh_time = NAME_POLL_REFRESH_TIME; + int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; + 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 (t - lasttime < NAME_POLL_INTERVAL) return; + if (t - lasttime < NAME_POLL_INTERVAL) return; lasttime = time(NULL); - for (n = d->namelist; n; n = n->next) - { - /* only do unique, registered names. */ - - if (n->source != REGISTER) continue; - if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; - - if (n->refresh_time < t) - { - DEBUG(3,("Polling name %s\n", namestr(&n->name))); - - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, - -1,n->name.name, n->name.name_type, - n->source,0,0,0,NULL,NULL, - False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); - count++; - } - - if (count >= max_count) - { - /* don't do too many of these at once, but do enough to - cover everyone in the list */ - return; - } - - /* this name will be checked on again, if it's not removed */ - n->refresh_time += name_refresh_time; - } + for (n = d->namelist; n; n = n->next) + { + /* only do unique, registered names */ + + if (n->source != REGISTER) continue; + if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; + + if (n->refresh_time < t) + { + DEBUG(3,("Polling name %s\n", namestr(&n->name))); + + queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, + n->name.name, n->name.name_type, + 0,0,0,NULL,NULL, + False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); + count++; + } + + if (count >= max_count) + { + /* don't do too many of these at once, but do enough to + cover everyone in the list */ + return; + } + + /* this name will be checked on again, if it's not removed */ + n->refresh_time += name_refresh_time; + } } diff --git a/source3/nameservreply.c b/source3/nameservreply.c index f5811925d4..b01c2c25b4 100644 --- a/source3/nameservreply.c +++ b/source3/nameservreply.c @@ -294,8 +294,8 @@ void reply_name_reg(struct packet_struct *p) /* initiate some enquiries to the current owner. */ queue_netbios_packet(d,ClientNMB,NMB_QUERY, NAME_REGISTER_CHALLENGE, - -1,reply_name->name,reply_name->name_type, - n->source, nb_flags,0,0,NULL,NULL, + reply_name->name,reply_name->name_type, + nb_flags,0,0,NULL,NULL, False, False, n->ip_flgs[0].ip, p->ip); } else diff --git a/source3/nameservresp.c b/source3/nameservresp.c index 9676776e81..a4cda7cdfb 100644 --- a/source3/nameservresp.c +++ b/source3/nameservresp.c @@ -46,29 +46,38 @@ extern struct in_addr ipzero; response for a reg release received. samba has asked a WINS server if it could release a name. **************************************************************************/ -static void response_name_release(struct nmb_ip *data, struct nmb_name *name, - struct subnet_record *d) +static void response_name_release(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")); - if (data) + if (nmb->header.rcode == 0 && nmb->answers->rdata) { /* 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 */ - if (ismyip(data->ip)) + if (ismyip(found_ip)) { - name_unregister_work(d, name->name, name->name_type); + name_unregister_work(d,name,type); } else { 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 { - 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? */ @@ -82,25 +91,34 @@ static void response_name_release(struct nmb_ip *data, struct nmb_name *name, /**************************************************************************** response for a reg request received **************************************************************************/ -static void response_name_reg(struct nmb_ip *data, struct nmb_name *name, - time_t ttl, BOOL bcast, struct in_addr source_ip, - struct subnet_record *d, enum name_source source, int token) +static void response_name_reg(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; + BOOL bcast = nmb->header.nm_flags.bcast; + DEBUG(4,("response name registration received!\n")); - if (data) + if (nmb->header.rcode == 0 && nmb->answers->rdata) { /* IMPORTANT: see expire_netbios_response_entries() */ - name_register_work(d, token, name->name,name->name_type, - source, data, ttl, source_ip, bcast); + int nb_flags = nmb->answers->rdata[0]; + 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 { - 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. */ - name_unregister_work(d,name->name,name->name_type); + /* oh dear. we have problems. possibly unbecome a master browser. */ + 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 NAME_QUERY_ANNOUNCE_HOST is dealt with here ****************************************************************************/ -static void response_announce_host(struct nmb_ip *data, - struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) +static void response_announce_host(struct nmb_name *ans_name, + struct nmb_packet *nmb, + struct response_record *n, struct subnet_record *d) { - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - 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 (data) - { - /* 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 */ - - if (data->nb_flags != n->reply.nb_flags) - { - /* someone gave us the wrong nb_flags as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags)); - DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags)); - return; - } - - /* do an announce host */ - do_announce_host(ANN_HostAnnouncement, - n->my_name , 0x00, d->myip, - n->name.name, 0x1d, data->ip, - n->ttl, - n->my_name, n->server_type, - HOST_MAJOR_VERSION, HOST_MINOR_VERSION, - HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE, - n->my_comment); - } - else - { - /* XXXX negative name query response. no master exists. oops */ - } + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + 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) + { + /* 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 */ + + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (nb_flags != n->nb_flags) + { + /* someone gave us the wrong nb_flags as a reply. oops. */ + /* XXXX should say to them 'oi! release that name!' */ + + DEBUG(4,("expected nb_flags: %d\n", n->nb_flags)); + DEBUG(4,("unexpected nb_flags: %d\n", nb_flags)); + return; + } + + /* do an announce host */ + do_announce_host(ANN_HostAnnouncement, + n->my_name , 0x00, d->myip, + n->name.name, 0x1d, found_ip, + n->ttl, + n->my_name, n->server_type, n->my_comment); + } + 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. ****************************************************************************/ 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 */ 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 */ queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, - -1,ans_name->name, ans_name->name_type, - 0,0,0,0,NULL,NULL, - False,False,n->send_ip,n->reply.ip); + ans_name->name, ans_name->name_type, + 0,0,0,NULL,NULL, + 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. ****************************************************************************/ static BOOL interpret_node_status(struct subnet_record *d, - char *p, struct nmb_name *name,int t, - char *serv_name, struct in_addr ip, BOOL bcast) + char *p, struct nmb_name *name,int t, + char *serv_name, struct in_addr ip, BOOL bcast) { int level = t==0x20 ? 4 : 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 */ if (add) - { - struct in_addr nameip; - enum name_source src; - - if (ismyip(ip)) { - nameip = ipzero; - src = SELF; - } else { - nameip = ip; - src = STATUS_QUERY; - } - add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); - } + { + struct in_addr nameip; + enum name_source src; + + if (ismyip(ip)) { + nameip = ipzero; + src = SELF; + } else { + nameip = ip; + src = STATUS_QUERY; + } + add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); + } /* we want the server name */ if (serv_name && !*serv_name && !group && t == 0) - { - StrnCpy(serv_name,qname,15); - serv_name[15] = 0; - } + { + StrnCpy(serv_name,qname,15); + serv_name[15] = 0; + } /* looking for a name and type? */ if (name && !found && (t == type)) - { - /* take a guess at some of the name types we're going to ask for. - evaluate whether they are group names or no... */ - if (((t == 0x1b || t == 0x1d ) && !group) || - ((t == 0x20 || t == 0x1c || t == 0x1e) && group)) - { - found = True; - make_nmb_name(name,qname,type,scope); - } - } + { + /* take a guess at some of the name types we're going to ask for. + evaluate whether they are group names or no... */ + if (((t == 0x1b || t == 0x1d ) && !group) || + ((t == 0x20 || t == 0x1c || t == 0x1e) && group)) + { + found = True; + make_nmb_name(name,qname,type,scope); + } + } DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags)); } 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; } @@ -279,26 +299,28 @@ static BOOL interpret_node_status(struct subnet_record *d, and NAME_STATUS_SRV_CHK dealt with here. ****************************************************************************/ static void response_name_status_check(struct in_addr ip, - char *data, BOOL bcast, - struct response_record *n, struct subnet_record *d) + struct nmb_packet *nmb, BOOL bcast, + 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. */ - struct nmb_name name; - fstring serv_name; - - if (interpret_node_status(d,data,&name,name.name_type,serv_name,ip,bcast)) - { - if (*serv_name) - { - 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")); - } + struct nmb_name name; + fstring serv_name; + + if (interpret_node_status(d,nmb->answers->rdata, + &name,name.name_type,serv_name,ip,bcast)) + { + if (*serv_name) + { + 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")); + } } @@ -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 NAME_REGISTER_CHALLENGE is dealt with here. ****************************************************************************/ -static void response_name_query_register(struct nmb_ip *data, - struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) +static void response_name_query_register(struct nmb_packet *nmb, + struct nmb_name *ans_name, + struct response_record *n, struct subnet_record *d) { - struct in_addr register_ip; - BOOL new_owner; - - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - 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 (data) - { - /* 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 */ - - if (data->nb_flags != n->reply.nb_flags) - { - /* someone gave us the wrong nb_flags as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags)); - DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags)); - return; - } - - if (!ip_equal(n->send_ip, data->ip)) - { - /* someone gave us the wrong ip as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - 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))); - - /* fine: now tell the other host they can't have the name */ - register_ip = n->send_ip; - new_owner = False; - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - /* the owner didn't want the name: the other host can have it */ - register_ip = n->reply.ip; - new_owner = True; - } - - /* register the old or the new owners' ip */ - add_name_respond(d, n->fd, d->myip, n->response_id,&n->name, - n->reply.nb_flags, GET_TTL(0), register_ip, - new_owner, n->reply.ip); + struct in_addr register_ip; + BOOL new_owner; + + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + 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) + { + /* 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 */ + + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (nb_flags != n->nb_flags) + { + /* someone gave us the wrong nb_flags as a reply. oops. */ + /* XXXX should say to them 'oi! release that name!' */ + + DEBUG(4,("expected nb_flags: %d\n", n->nb_flags)); + DEBUG(4,("unexpected nb_flags: %d\n", nb_flags)); + return; + } + + if (!ip_equal(n->send_ip, found_ip)) + { + /* someone gave us the wrong ip as a reply. oops. */ + /* XXXX should say to them 'oi! release that name!' */ + + DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); + DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); + return; + } + + DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + + /* fine: now tell the other host they can't have the name */ + register_ip = n->send_ip; + new_owner = False; + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE!\n")); + + /* the owner didn't want the name: the other host can have it */ + register_ip = n->reply_to_ip; + new_owner = True; + } + + /* register the old or the new owners' ip */ + add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags, + GET_TTL(0), register_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 entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM ****************************************************************************/ -static void response_name_query_sync(struct nmb_ip *data, - struct nmb_name *ans_name, BOOL bcast, - struct response_record *n, struct subnet_record *d) +static void response_name_query_sync(struct nmb_packet *nmb, + struct nmb_name *ans_name, BOOL bcast, + struct response_record *n, struct subnet_record *d) { - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - 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 (data) - { - 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 (n->state == NAME_QUERY_SYNC_LOCAL || - 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! */ - sync_browse_lists(d, work, ans_name->name, ans_name->name_type, - data->ip, local_list_only); - } - } - else - { - /* 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) - { - /* 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 + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + 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) + { + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + 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; + } + + DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + + if (n->state == NAME_QUERY_SYNC_LOCAL || + 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! */ + sync_browse_lists(d, work, ans_name->name, ans_name->name_type, + found_ip, local_list_only); + } + } + 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, - REGISTER,n->send_ip); - } - } + remove_netbios_name(d,n->name.name, n->name.name_type, + REGISTER,n->send_ip); + } + } } @@ -454,9 +486,9 @@ static void debug_rr_type(int rr_type) switch (rr_type) { case NMB_STATUS: DEBUG(3,("Name status ")); break; - case NMB_QUERY : DEBUG(3,("Name query ")); break; - case NMB_REG : DEBUG(3,("Name registration ")); break; - case NMB_REL : DEBUG(3,("Name release ")); break; + case NMB_QUERY : DEBUG(3,("Name query ")); break; + case NMB_REG : DEBUG(3,("Name registration ")); break; + case NMB_REL : DEBUG(3,("Name release ")); 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) ****************************************************************************/ 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) { @@ -524,21 +556,21 @@ static BOOL response_problem_check(struct response_record *n, { if (n->num_msgs > 1) { - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - - if ((!NAME_GROUP(nb_flags))) - { - /* oh dear. more than one person responded to a unique name. - there is either a network problem, a configuration problem - or a server is mis-behaving */ - - /* XXXX mark the name as in conflict, and then let the - person who just responded know that they must also mark it - as in conflict, and therefore must NOT use it. + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + + if ((!NAME_GROUP(nb_flags))) + { + /* oh dear. more than one person responded to a unique name. + there is either a network problem, a configuration problem + or a server is mis-behaving */ + + /* XXXX mark the name as in conflict, and then let the + person who just responded know that they must also mark it + as in conflict, and therefore must NOT use it. see rfc1001.txt 15.1.3.5 */ - + /* this may cause problems for some early versions of nmbd */ 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 */ return False; } - case NAME_QUERY_ANNOUNCE_HOST: - case NAME_QUERY_DOM_SRV_CHK: + case NAME_QUERY_ANNOUNCE_HOST: + case NAME_QUERY_DOM_SRV_CHK: case NAME_QUERY_SRV_CHK: case NAME_QUERY_MST_CHK: { - if (!strequal(qname,n->name.name)) - { - /* one subnet, one master browser per workgroup */ - /* XXXX force an election? */ - - DEBUG(3,("more than one master browser replied!\n")); - return True; - } + if (!strequal(qname,n->name.name)) + { + /* one subnet, one master browser per workgroup */ + /* XXXX force an election? */ + + DEBUG(3,("more than one master browser replied!\n")); + return True; + } break; } default: break; } DEBUG(3,("Unique Name conflict detected!\n")); - return True; - } - } - else - { + return True; + } + } + else + { /* we have received a negative reply, having already received at least one response (pos/neg). something's really wrong! */ - DEBUG(3,("wierd name query problem detected!\n")); - return True; - } + DEBUG(3,("wierd name query problem detected!\n")); + 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 ****************************************************************************/ static BOOL response_compatible(struct response_record *n, - struct nmb_packet *nmb) + struct nmb_packet *nmb) { switch (n->state) { case NAME_RELEASE: { - if (nmb->answers->rr_type != NMB_REL) - { - DEBUG(1,("Name release reply has wrong answer rr_type\n")); - return False; - } + if (nmb->answers->rr_type != NMB_REL) + { + DEBUG(1,("Name release reply has wrong answer rr_type\n")); + return False; + } break; } case NAME_REGISTER: { -/* rfc1002.txt states that nmb->answers->rr_type must equal 0x20 */ -#if 0 - if (nmb->answers->rr_type != NMB_REG) - { - DEBUG(1,("Name register reply has wrong answer rr_type\n")); - return False; - } -#endif + if (nmb->answers->rr_type != NMB_REG) + { + DEBUG(1,("Name register reply has wrong answer rr_type\n")); + return False; + } break; } @@ -624,29 +653,29 @@ static BOOL response_compatible(struct response_record *n, case NAME_QUERY_FIND_MST: case NAME_QUERY_MST_CHK: { - if (nmb->answers->rr_type != NMB_QUERY) - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - return False; - } - break; + if (nmb->answers->rr_type != NMB_QUERY) + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + return False; + } + break; } case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_SRV_CHK: { - if (nmb->answers->rr_type != NMB_STATUS) - { - DEBUG(1,("Name status reply has wrong answer rr_type\n")); - return False; - } - break; + if (nmb->answers->rr_type != NMB_STATUS) + { + DEBUG(1,("Name status reply has wrong answer rr_type\n")); + return False; + } + break; } default: { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - return False; + DEBUG(1,("unknown state type received in response_netbios_packet\n")); + return False; } } return True; @@ -656,62 +685,27 @@ static BOOL response_compatible(struct response_record *n, /**************************************************************************** process the response packet received ****************************************************************************/ -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) +static void response_process(struct subnet_record *d, struct packet_struct *p, + struct response_record *n, struct nmb_packet *nmb, + BOOL bcast, struct nmb_name *ans_name) { switch (n->state) { case NAME_RELEASE: { - struct nmb_ip found; - 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); + response_name_release(d, p); break; } case NAME_REGISTER: { - struct nmb_ip found; - 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); + response_name_reg(d, p); break; } case NAME_REGISTER_CHALLENGE: { - struct nmb_ip found; - 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); + response_name_query_register(nmb, ans_name, n, d); break; } @@ -719,66 +713,44 @@ void response_process(struct in_addr ip, struct subnet_record *d, case NAME_QUERY_SRV_CHK: case NAME_QUERY_FIND_MST: { - response_server_check(ans_name, n, d); - break; + response_server_check(ans_name, n, d); + break; } case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_SRV_CHK: { - response_name_status_check(ip,nmb_data,bcast,n,d); - break; + response_name_status_check(p->ip, nmb, bcast, n, d); + break; } case NAME_QUERY_ANNOUNCE_HOST: { - struct nmb_ip found; - 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_announce_host(data, ans_name, n, d); - break; + response_announce_host(ans_name, nmb, n, d); + break; } case NAME_QUERY_CONFIRM: case NAME_QUERY_SYNC_LOCAL: case NAME_QUERY_SYNC_REMOTE: { - struct nmb_ip found; - 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_sync(data,ans_name,bcast,n,d); - break; + response_name_query_sync(nmb, ans_name, bcast, n, d); + break; } case NAME_QUERY_MST_CHK: { - /* no action required here. it's when NO responses are received - that we need to do something. see expire_name_query_entries() */ - - DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", - namestr(&n->name), inet_ntoa(n->send_ip))); - break; + /* no action required here. it's when NO responses are received + that we need to do something. see expire_name_query_entries() */ + + DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", + namestr(&n->name), inet_ntoa(n->send_ip))); + break; } default: { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - break; + DEBUG(1,("unknown state type received in response_netbios_packet\n")); + break; } } } @@ -808,9 +780,7 @@ void response_netbios_packet(struct packet_struct *p) return; } - DEBUG(4,("response packet received: %s %d\n", - inet_ntoa(p->ip),n->response_id)); - + /* args wrong way round: spotted by ccm@shentel.net */ if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */ { 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! */ DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), BOOLSTR(bcast))); + inet_ntoa(p->ip), BOOLSTR(bcast))); return; } ans_name = &nmb->answers->rr_name; 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); @@ -846,13 +816,7 @@ void response_netbios_packet(struct packet_struct *p) return; /* now deal with the current state */ - response_process(p->ip, d, n, - nmb->header.rcode, - nmb->answers->rdata, - question, - nmb->answers->ttl, bcast, ans_name); - - remove_response_record(d, n); + response_process(d, p, n, nmb, bcast, ans_name); } diff --git a/source3/namework.c b/source3/namework.c index 630f3dea12..0380c1460a 100644 --- a/source3/namework.c +++ b/source3/namework.c @@ -23,9 +23,6 @@ 14 jan 96: lkcl@pires.co.uk added multiple workgroup domain master support - 30 July 96: David.Chappell@mail.trincoll.edu - Expanded multiple workgroup domain master browser support. - */ #include "includes.h" @@ -33,34 +30,41 @@ extern int ClientNMB; extern int ClientDGRAM; +#define TEST_CODE /* want to debug unknown browse packets */ + extern int DEBUGLEVEL; extern pstring scope; extern BOOL CanRecurse; +extern pstring myname; + extern int ClientNMB; extern int ClientDGRAM; extern struct in_addr ipzero; +extern int workgroup_count; /* total number of workgroups we know about */ + /* this is our domain/workgroup/server database */ extern struct subnet_record *subnetlist; 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 BOOL updatedlists; -extern pstring myname; - - /**************************************************************************** tell a server to become a backup browser state - 0x01 become backup instead of master - 0x02 remove all entries in browse list and become non-master - 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 *p; @@ -73,10 +77,10 @@ void reset_server(struct work_record *work, char *name, int state, struct in_add p += 2; 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), - 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; for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - int num_servers = 0; - int num_backups = 0; - - for (s = work->serverlist; s; s = s->next) - { - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - num_servers++; - - if (strequal(conf_browsing_alias(work->token), s->serv.name)) continue; - - if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { - num_backups++; - continue; - } - - if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; - - if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; - - DEBUG(3,("num servers: %d num backups: %d\n", - num_servers, num_backups)); - - /* make first server a backup server. thereafter make every - tenth server a backup server */ - if (num_backups != 0 && (num_servers+9) / num_backups > 10) - { - continue; - } - - DEBUG(2,("sending become backup to %s %s for %s\n", - s->serv.name, inet_ntoa(d->bcast_ip), - work->work_group)); - - /* type 11 request from conf_browsing_alias(work->token)(20) to WG(1e) for SERVER */ - do_announce_request(s->serv.name, s->serv.name, work->work_group, - ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); - } - } + { + struct server_record *s; + int num_servers = 0; + int num_backups = 0; + + for (s = work->serverlist; s; s = s->next) + { + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + num_servers++; + + if (strequal(myname, s->serv.name)) continue; + + if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { + num_backups++; + continue; + } + + if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; + + if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; + + DEBUG(3,("num servers: %d num backups: %d\n", + num_servers, num_backups)); + + /* make first server a backup server. thereafter make every + tenth server a backup server */ + if (num_backups != 0 && (num_servers+9) / num_backups > 10) + { + continue; + } + + DEBUG(2,("sending become backup to %s %s for %s\n", + s->serv.name, inet_ntoa(d->bcast_ip), + work->work_group)); + + /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ + do_announce_request(s->serv.name, work->work_group, + ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); + } + } } } @@ -146,23 +150,8 @@ void tell_become_backup(void) ******************************************************************/ BOOL same_context(struct dgram_packet *dgram) { - if (!strequal(dgram->dest_name .scope,scope )) 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); - } + if (!strequal(dgram->dest_name .scope,scope )) return(True); + if ( strequal(dgram->source_name.name ,myname)) return(True); 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,("%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, - servertype,browse_type,browse_sig,comment)); + namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, + servertype,browse_type,browse_sig,comment)); 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)) { 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; } @@ -276,7 +265,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf) if (command == ANN_LocalMasterAnnouncement) { 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 subnet_record *d = find_subnet(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 *work_name; - int token; + struct work_record *work; 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 (!d || !mydomain) return; - token = conf_alias_to_token(to_name); - - if (token == -1) + if (!lp_domain_master()) return; + + for (work = mydomain->workgrouplist; work; work = work->next) { - DEBUG(4, ("alias %s not known\n", to_name)); - return; + if (AM_MASTER(work)) + { + /* merge browse lists with them */ + add_browser_entry(name,0x1b, work->work_group,30,ip,True); + } } - - /* 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 */ - add_browser_entry(name, 0x1b, work_name,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 in_addr ip = dgram->header.source_ip; int count = CVAL(buf,0); - unsigned int pick; uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */ char *buf1; DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n", - namestr(&dgram->dest_name), inet_ntoa(ip), - count, info)); + namestr(&dgram->dest_name), inet_ntoa(ip), + count, info)); if (same_context(dgram)) return; if (count <= 0) return; - pick = sys_random(count); - /* go through the list of servers attempting to sync browse lists */ for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) { + struct in_addr back_ip; struct subnet_record *d; - if (count != pick) continue; + DEBUG(4,("Searching for backup browser %s at %s...\n", + buf1, inet_ntoa(ip))); + + /* 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 */ - DEBUG(4,("Searching for backup browser %s...\n", buf1)); + back_ip = *interpret_addr2(buf1); - if ((d = find_subnet(ip)) != NULL) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (work->token == 0 /* token */) - { - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, - work->token,work->work_group,0x1d, - 0,0,0,0,NULL,NULL, - False,False,ipzero,ipzero); - return; - } - } - } + if (zero_ip(back_ip)) + { + DEBUG(4,("Failed to find backup browser server using DNS\n")); + continue; + } + + 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. **************************************************************************/ -static void send_backup_list(struct work_record *work, struct nmb_name *src_name, - int token, uint32 info, - int name_type, struct in_addr ip) +static void send_backup_list(char *work_name, struct nmb_name *src_name, + int token, uint32 info, + int name_type, struct in_addr ip) { char outbuf[1024]; 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; DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", - work->work_group, inet_ntoa(ip), - conf_browsing_alias(work->token),0x0,theirname,0x0)); + work_name, inet_ntoa(ip), + myname,0x0,theirname,0x0)); if (name_type == 0x1d) { @@ -431,51 +424,62 @@ static void send_backup_list(struct work_record *work, struct nmb_name *src_name #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) - { - BOOL found = False; - char *n; - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - for (n = nameptr; n < p; n = skip_string(n, 1)) - { - 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)) || - (name_type == 0x1b && (s->serv.type & SV_TYPE_DOMAIN_BROWSER))) - { - DEBUG(4, ("%s ", s->serv.name)); - - count++; - strcpy(p,s->serv.name); - strupper(p); - p = skip_string(p,1); - } + for (work = d->workgrouplist; work; work = work->next) + { + struct server_record *s; + + if (!strequal(work->work_group, work_name)) continue; + + for (s = work->serverlist; s; s = s->next) + { + BOOL found = False; + char *n; + + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + for (n = nameptr; n < p; n = skip_string(n, 1)) + { + 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 & MASTER_TYPE)) || + (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) + { + DEBUG(4, ("%s ", s->serv.name)); + + count++; + strcpy(p,s->serv.name); + strupper(p); + p = skip_string(p,1); + } + } + } } + #endif - count++; - strcpy(p,conf_browsing_alias(work->token)); - strupper(p); - p = skip_string(p,1); + count++; + strcpy(p,myname); + strupper(p); + p = skip_string(p,1); if (count == 0) - { + { DEBUG(4, ("none\n")); - } + } else - { + { DEBUG(4, (" - count %d\n", 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); } 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) { DEBUG(0,("backup request to wrong type %d from %s\n", - name_type,inet_ntoa(ip))); + name_type,inet_ntoa(ip))); return; } for (d = subnetlist; d; d = d->next) { for (work = d->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, dgram->dest_name.name)) - { - DEBUG(2,("sending backup list to %s %s id=%x\n", - namestr(&dgram->dest_name),inet_ntoa(ip),info)); - - send_backup_list(work,&dgram->source_name, - token,info,name_type,ip); - return; - } - } + { + if (strequal(work->work_group, dgram->dest_name.name)) + { + DEBUG(2,("sending backup list to %s %s id=%x\n", + namestr(&dgram->dest_name),inet_ntoa(ip),info)); + + send_backup_list(work->work_group,&dgram->source_name, + token,info,name_type,ip); + return; + } + } } } @@ -552,23 +556,23 @@ static void process_reset_browser(struct packet_struct *p,char *buf) int state = CVAL(buf,0); 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 */ if (state & 0x1) { struct subnet_record *d; for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER); - } - } - } + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + if (AM_MASTER(work)) + { + become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER); + } + } + } } /* 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 */ 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; - for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True)); + struct subnet_record *d; + 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! */ if (state & 0x4) - { + { 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 subnet_record *d = find_subnet(ip); int token = CVAL(buf,0); - int wg_token = 0; char *name = buf+1; - char *samba_alias; - + name[15] = 0; 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 */ - 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; + if (strequal(dgram->source_name.name,myname)) 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. - /* find samba's NetBIOS alias it operates under in this workgroup */ - if ((samba_alias = conf_browsing_alias(wg_token)) == (char*)NULL) return; + if (strequal(dgram->dest_name, lp_workgroup()) 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; - 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) - { - 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 ****************************************************************************/ @@ -660,27 +657,27 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_LocalMasterAnnouncement: { debug_browse_data(buf, len); - process_announce(p,command,buf+1); - break; + process_announce(p,command,buf+1); + break; } case ANN_AnnouncementRequest: { - process_announce_request(p,buf+1); - break; + process_announce_request(p,buf+1); + break; } case ANN_Election: { - process_election(p,buf+1); - break; + process_election(p,buf+1); + break; } case ANN_GetBackupListReq: { debug_browse_data(buf, len); - process_send_backup_list(p,buf+1); - break; + process_send_backup_list(p,buf+1); + break; } case ANN_GetBackupListResp: @@ -692,22 +689,22 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_ResetBrowserState: { - process_reset_browser(p, buf+1); - break; + process_reset_browser(p, buf+1); + break; } case ANN_MasterAnnouncement: { - process_master_announce(p,buf+1); - break; + process_master_announce(p,buf+1); + break; } default: { - struct dgram_packet *dgram = &p->packet.dgram; - DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); + struct dgram_packet *dgram = &p->packet.dgram; + DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", + command, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); } } } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 54f4254d51..5b3fd19491 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -23,10 +23,6 @@ 14 jan 96: lkcl@pires.co.uk added multiple workgroup domain master support - - 30 July 96: David.Chappell@mail.trincoll.edu - Expanded multiple workgroup domain master browser support. - */ #include "includes.h" @@ -169,10 +165,10 @@ static void expire_names_and_servers(void) time_t t = time(NULL); if (!lastrun) lastrun = t; - if (t < lastrun + 15) return; /* give samba time to check its names */ + if (t < lastrun + 5) return; lastrun = t; - check_expire_names(t); /* this checks samba's NetBIOS names */ + expire_names(t); expire_servers(t); } @@ -191,10 +187,10 @@ BOOL reload_services(BOOL test) pstring fname; strcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - strcpy(servicesf,fname); - test = False; - } + { + strcpy(servicesf,fname); + test = False; + } } if (test && !lp_file_list_changed()) @@ -255,32 +251,32 @@ static void load_hosts_file(char *fname) if (count <= 0) continue; if (count > 0 && count < 2) { - DEBUG(0,("Ill formed hosts line [%s]\n",line)); - continue; + DEBUG(0,("Ill formed hosts line [%s]\n",line)); + continue; } if (count >= 4) { - DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); - continue; + DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); + continue; } DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags)); if (strchr(flags,'G') || strchr(flags,'S')) { - DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); - continue; + DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); + continue; } if (strchr(flags,'M')) { - source = SELF; - strcpy(myname,name); + source = SELF; + strcpy(myname,name); } ipaddr = *interpret_addr2(ip); d = find_subnet(ipaddr); if (d) { - 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,0x00,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; while (True) - { + { + time_t t = time(NULL); run_election = check_elections(); listen_for_packets(run_election); @@ -313,11 +310,12 @@ static void process(void) expire_names_and_servers(); expire_netbios_response_entries(); + refresh_my_names(t); write_browse_list(); do_browser_lists(); 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) { switch (opt) - { - case 's': - strcpy(servicesf,optarg); - break; - case 'N': - case 'B': - case 'I': - case 'C': - case 'G': - DEBUG(0,("Obsolete option '%c' used\n",opt)); - break; - case 'H': - strcpy(host_file,optarg); - break; - case 'n': - strcpy(myname,optarg); - strupper(myname); - break; - case 'l': - sprintf(debugf,"%s.nmb",optarg); - break; - case 'i': - strcpy(scope,optarg); - strupper(scope); - break; - case 'D': - is_daemon = True; - break; - case 'd': - DEBUGLEVEL = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - if (!is_a_socket(0)) { - usage(argv[0]); - } - break; - } + { + case 's': + strcpy(servicesf,optarg); + break; + case 'N': + case 'B': + case 'I': + case 'C': + case 'G': + DEBUG(0,("Obsolete option '%c' used\n",opt)); + break; + case 'H': + strcpy(host_file,optarg); + break; + case 'n': + strcpy(myname,optarg); + strupper(myname); + break; + case 'l': + sprintf(debugf,"%s.nmb",optarg); + break; + case 'i': + strcpy(scope,optarg); + strupper(scope); + break; + case 'D': + is_daemon = True; + break; + case 'd': + DEBUGLEVEL = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + default: + if (!is_a_socket(0)) { + usage(argv[0]); + } + break; + } } DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION)); @@ -489,18 +487,10 @@ static void usage(char *pname) get_myname(myhostname,NULL); if (!reload_services(False)) - return(-1); - + return(-1); + 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); 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")); } - add_workgroups_to_subnets(); + add_my_subnets(lp_workgroup()); DEBUG(3,("Checked names\n")); diff --git a/source3/nmbsync.c b/source3/nmbsync.c index 5a4d93f1a0..2efb364bca 100644 --- a/source3/nmbsync.c +++ b/source3/nmbsync.c @@ -48,7 +48,7 @@ fudge for getpass function ****************************************************************************/ 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); if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, - &rprcnt,&rdrcnt, param,NULL, - &rparam,&rdata)) + &rprcnt,&rdrcnt, param,NULL, + &rparam,&rdata)) { int res = SVAL(rparam,0); int converter=SVAL(rparam,2); int i; if (res == 0) - { - count=SVAL(rparam,4); - p = rdata; - - for (i = 0;i < count;i++, p += 26) - { - char *sname = p; - uint32 stype = IVAL(p,18); - int comment_offset = IVAL(p,22) & 0xFFFF; - char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - - struct work_record *w = work; - - DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); - - if (stype & SV_TYPE_DOMAIN_ENUM) - { - /* creates workgroup on remote subnet */ - if ((w = find_workgroupstruct(d,sname,True))) - { - announce_request(w, d->bcast_ip); - } - } - - if (w) - { - add_server_entry(d,w,sname,stype & ~SV_TYPE_LOCAL_LIST_ONLY, - lp_max_ttl(),cmnt,False); - } - } + { + count=SVAL(rparam,4); + p = rdata; + + for (i = 0;i < count;i++, p += 26) + { + char *sname = p; + uint32 stype = IVAL(p,18); + int comment_offset = IVAL(p,22) & 0xFFFF; + char *cmnt = comment_offset?(rdata+comment_offset-converter):""; + + struct work_record *w = work; + + DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); + + if (stype & SV_TYPE_DOMAIN_ENUM) + { + /* creates workgroup on remote subnet */ + if ((w = find_workgroupstruct(d,sname,True))) + { + announce_request(w, d->bcast_ip); + } + } + + if (w) + add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); + } + } } - } if (rparam) free(rparam); 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. ******************************************************************/ 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; @@ -154,7 +151,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, got_pass = True; 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(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_send_login(NULL,NULL,True,True)) - { - 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_DOMAIN_ENUM); + add_info(d, work, local_type|(SV_TYPE_ALL& ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY))); - } + } close_sockets(); } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 2a76ce70f7..87209d1bb7 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -106,34 +106,33 @@ extern int coding_system; */ typedef struct { - char *szAutoServices; - char *szCharacterSet; - char *szConfigFile; + char *szPrintcapname; + char *szLockDir; + char *szRootdir; char *szDefaultService; char *szDfree; - char *szDomainController; - char *szHostsEquiv; - char *szInterfaces; - char *szLockDir; - char *szLogFile; - char *szLogonScript; char *szMsgCommand; - char *szPasswdChat; - char *szPasswdProgram; - char *szPasswordServer; - char *szPrintcapname; - char *szRemoteAnnounce; - char *szRootdir; - char *szServerComment; + char *szHostsEquiv; char *szServerString; - char *szSmbrun; + char *szAutoServices; + char *szPasswdProgram; + char *szPasswdChat; + char *szLogFile; + char *szConfigFile; char *szSMBPasswdFile; - char *szSocketAddress; + char *szPasswordServer; char *szSocketOptions; - char *szUsernameMap; char *szValidChars; - char *szWINSserver; 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 mangled_stack; int max_xmit; @@ -153,7 +152,6 @@ typedef struct BOOL bWINSsupport; BOOL bWINSproxy; BOOL bPreferredMaster; - BOOL bLocalMaster; BOOL bDomainMaster; BOOL bDomainLogons; BOOL bEncryptPasswords; @@ -384,7 +382,6 @@ struct parm_struct {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL}, {"preload", 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}, {"printcap name", 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}, {"preferred 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 logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, 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"); sprintf(s,"Samba %s",VERSION); 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.bUseRhosts = False; Globals.max_packet = 65535; @@ -591,9 +584,8 @@ static void init_globals(void) Globals.bSyslogOnly = False; Globals.os_level = 0; Globals.max_ttl = 60*60*4; /* 2 hours default */ - Globals.bPreferredMaster = True; /* force election on startup */ - Globals.bLocalMaster = True; /* master browser on local subnet */ - Globals.bDomainMaster = False; /* maintain wide area network browse list */ + Globals.bPreferredMaster = True; + Globals.bDomainMaster = False; Globals.bDomainLogons = False; Globals.bBrowseList = 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_smb_passwd_file,&Globals.szSMBPasswdFile) 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_lockdir,&Globals.szLockDir) 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_proxy,&Globals.bWINSproxy) -FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster) FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster) FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons) FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster) diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 580aa446b6..8e81134de5 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -812,7 +812,10 @@ static int get_server_info(uint32 servertype, if (!next_token(&ptr,s->name , NULL)) continue; if (!next_token(&ptr,stype , 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) { 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) { StrnCpy(domain, p, sizeof(fstring)-1); - } - else - { - /* 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); + } else { + StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); } if (lp_browse_list()) @@ -1679,19 +1668,9 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; 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()); - 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