summaryrefslogtreecommitdiff
path: root/source3/nameannounce.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nameannounce.c')
-rw-r--r--source3/nameannounce.c486
1 files changed, 264 insertions, 222 deletions
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index ff2c89df85..c7a52473b6 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -23,19 +23,18 @@
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;
@@ -43,14 +42,17 @@ 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
+ Send a announce request to the local net.
+
+ This is called by become_master(). This purpose of this action is to
+ encourage servers to send us host announcements right away.
**************************************************************************/
void announce_request(struct work_record *work, struct in_addr ip)
{
@@ -62,7 +64,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;
@@ -71,8 +73,7 @@ void announce_request(struct work_record *work, struct in_addr ip)
CVAL(p,0) = work->token; /* (local) unique workgroup token id */
p++;
- StrnCpy(p,myname,16);
- strupper(p);
+ StrnCpy(p,conf_browsing_alias(work->token),16);
p = skip_string(p,1);
/* XXXX note: if we sent the announcement request to 0x1d instead
@@ -80,16 +81,17 @@ 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),
- myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
+ conf_browsing_alias(work->token),work->work_group,
+ 0x20, 0x1e,
+ ip,*iface_ip(ip));
}
/****************************************************************************
request an announcement
**************************************************************************/
-void do_announce_request(char *info, char *to_name, int announce_type,
- int from,
- int to, struct in_addr dest_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)
{
pstring outbuf;
char *p;
@@ -100,14 +102,15 @@ void do_announce_request(char *info, char *to_name, int announce_type,
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),
- myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
+ from_name,to_name,from,to,
+ dest_ip,*iface_ip(dest_ip));
}
@@ -116,19 +119,23 @@ void do_announce_request(char *info, char *to_name, int announce_type,
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 name_type,
+ struct in_addr ip)
+{
+ int token = conf_workgroup_name_to_token(work_name, myname);
+
/* with a domain master we can get the whole list (not local only list) */
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)
+ if (state == NAME_STATUS_DOM_SRV_CHK && conf_should_local_master(token))
{
/* announce ourselves as a master browser to serv_name */
- do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
- 0x20, 0, ip);
+ do_announce_request(conf_browsing_alias(token), /* info */
+ conf_browsing_alias(token), /* from */
+ serv_name, /* to */
+ ANN_MasterAnnouncement, 0x20, 0,ip);
}
}
@@ -137,46 +144,50 @@ 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 *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 major_version, char minor_version,
+ uint16 browse_version, uint16 browse_sig,
+ 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) = 0x02; /* major version */
- CVAL(p,22) = 0x02; /* minor version */
+ CVAL(p,21) = major_version;
+ CVAL(p,22) = minor_version;
- SIVAL(p,23,server_type);
- SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */
- SSVAL(p,29,0xaa55); /* browse signature */
+ SIVAL(p,23,server_type);
- strcpy(p+31,server_comment);
- p += 31;
- p = skip_string(p,1);
+ SSVAL(p,27,browse_version);
+ SSVAL(p,29,browse_sig);
+
+ 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);
}
@@ -185,20 +196,23 @@ 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(myname,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(conf_browsing_alias(work->token),s->serv.name))
+ {
+ continue;
+ }
+ announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
+ }
+ }
+ }
}
@@ -206,9 +220,14 @@ 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)
{
- uint32 domain_type = SV_TYPE_DOMAIN_ENUM|DFLT_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)
@@ -216,14 +235,13 @@ 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->work_group,0x1b,0,ttl*1000,
+ work->token,work->work_group,0x1b,0,0,ttl*1000,
server_type,name,comment,
False, False, ipzero, d->bcast_ip);
}
@@ -239,9 +257,7 @@ 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. they even
- use WINS lookup of the domain master if another wins server
- is being used!
+ local master announcements to their domain master.
*/
}
else
@@ -252,10 +268,13 @@ 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, comment);
+ 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);
DEBUG(3,("sending domain announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
@@ -264,11 +283,13 @@ 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,
- name);
+ 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);
}
}
else
@@ -277,10 +298,13 @@ 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, comment);
+ 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);
}
}
}
@@ -293,11 +317,6 @@ 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)
{
@@ -306,62 +325,63 @@ 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;
- BOOL announce = False;
-
+ {
+ 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);
+
/* 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(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 */
- }
- }
+ 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 */
+ }
+ }
}
}
/****************************************************************************
- announce myself as a master to all other primary domain conrollers.
+ announce samba 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 command, if there is a response from the
+ NAME_QUERY_DOM_SRV_CHK state, if there is a response from the
name query initiated here. see response_name_query()
**************************************************************************/
void announce_master(void)
@@ -373,97 +393,108 @@ 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)
{
- struct work_record *work;
- for (work = d->workgrouplist; work; work = work->next)
- {
- if (AM_MASTER(work))
- {
- am_master = True;
- }
- }
+ if (AM_MASTER(work) || AM_DMBRSE(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 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);
- }
- }
+ 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);
+ }
}
+ }
}
@@ -481,6 +512,7 @@ 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)
@@ -491,13 +523,16 @@ void announce_remote(void)
s = lp_remote_announce();
if (!*s) return;
- comment = lp_serverstring();
- workgroup = lp_workgroup();
+ comment = lp_serverstring(); /* default comment */
+ workgroup = lp_workgroup(); /* default workgroup name */
- 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;
@@ -506,10 +541,17 @@ void announce_remote(void)
addr = *interpret_addr2(s2);
- do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr),
- wgroup,0x1e,addr,
- REMOTE_ANNOUNCE_INTERVAL,
- myname,stype,comment);
+ 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);
}
-
}