*/
#include "includes.h"
-#include "loadparm.h"
#define TEST_CODE
extern int ClientNMB;
/* this is our domain/workgroup/server database */
-extern struct domain_record *domainlist;
+extern struct subnet_record *subnetlist;
/* machine comment for host announcements */
extern pstring ServerComment;
extern int updatecount;
extern int workgroup_count;
-/* what server type are we currently */
-
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+extern struct in_addr ipgrp;
/****************************************************************************
send a announce request to the local net
CVAL(p,0) = ANN_AnnouncementRequest;
p++;
- CVAL(p,0) = work->token; /* flags?? XXXX probably a token*/
+ CVAL(p,0) = work->token; /* (local) unique workgroup token id */
p++;
StrnCpy(p,myname,16);
strupper(p);
p = skip_string(p,1);
+ /* XXXX note: if we sent the announcement request to 0x1d instead
+ of 0x1e, then we could get the master browser to announce to
+ 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));
}
myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
}
+
+/****************************************************************************
+ find a server responsible for a workgroup, and sync browse lists
+ 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)
+{
+ /* 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)
+ {
+ /* announce ourselves as a master browser to serv_name */
+ do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
+ 0x20, 0, ip);
+ }
+}
+
+
/****************************************************************************
construct a host announcement unicast
+
+ this function should not be used heavily, and only when we are _not_
+ a master browser and _not_ a primary domain controller.
+
**************************************************************************/
void announce_backup(void)
{
time_t t = time(NULL);
pstring outbuf;
char *p;
- struct domain_record *d1;
+ struct subnet_record *d1;
int tok;
+ static uint32 id_count = 0;
if (!lastrun) lastrun = t;
- if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60) return;
+#if 1
+ if (t < lastrun + 1 * 60)
+#else
+ if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60)
+#endif
+ return;
lastrun = t;
+ DEBUG(4,("checking backups...\n"));
+
for (tok = 0; tok <= workgroup_count; tok++)
{
- for (d1 = domainlist; d1; d1 = d1->next)
+ for (d1 = subnetlist; d1; d1 = d1->next)
{
struct work_record *work;
- struct domain_record *d;
+ struct subnet_record *d;
/* search for unique workgroup: only the name matters */
for (work = d1->workgrouplist;
if (!work) continue;
+ if (AM_MASTER(work) && AM_DOMCTL(work)) continue;
+
/* found one: announce it across all domains */
- for (d = domainlist; d; d = d->next)
+ for (d = subnetlist; d; d = d->next)
{
- int type=0;
-
- if (AM_DOMCTL(work)) {
- type = 0x1b;
- } else if (AM_MASTER(work)) {
- type = 0x1d;
- } else {
- continue;
- }
DEBUG(2,("sending announce backup %s workgroup %s(%d)\n",
inet_ntoa(d->bcast_ip),work->work_group,
bzero(outbuf,sizeof(outbuf));
p = outbuf;
+
CVAL(p,0) = ANN_GetBackupListReq;
- p++;
-
- CVAL(p,0) = 1; /* count? */
- SIVAL(p,1,work->token); /* workgroup unique key index */
- p += 5;
- p++;
+ CVAL(p,1) = work->token; /* workgroup unique key index */
+ SIVAL(p,2,++id_count); /* unique count. not that we use it! */
+
+ p += 6;
- send_mailslot_reply(BROWSE_MAILSLOT,
+ debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+ if (!AM_DOMCTL(work))
+ {
+ /* only ask for a list of backup domain controllers
+ if we are not a domain controller ourselves */
+
+ send_mailslot_reply(BROWSE_MAILSLOT,
ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf),
myname, work->work_group,
- 0x0,type,d->bcast_ip,
+ 0x0,0x1b,d->bcast_ip,
*iface_ip(d->bcast_ip));
+ }
+
+ debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+ if (!AM_MASTER(work))
+ {
+ /* only ask for a list of master browsers if we
+ are not a master browser ourselves */
+
+ send_mailslot_reply(BROWSE_MAILSLOT,
+ ClientDGRAM,outbuf,
+ PTR_DIFF(p,outbuf),
+ myname, work->work_group,
+ 0x0,0x1d,d->bcast_ip,
+ *iface_ip(d->bcast_ip));
+ }
}
}
}
}
+/****************************************************************************
+ 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)
+{
+ pstring outbuf;
+ char *p;
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf+1;
+
+ /* command type */
+ CVAL(outbuf,0) = command;
+
+ /* 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);
+
+ CVAL(p,21) = 0x02; /* major version */
+ CVAL(p,22) = 0x02; /* 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 */
+
+ 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);
+}
+
+
+/****************************************************************************
+ remove all samba's server entries
+ ****************************************************************************/
+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);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ 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)
+{
+ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_SERVER_UNIX;
+ BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
+
+ if (wins_iface && server_type != 0)
+ {
+ /* wins pseudo-ip interface */
+ if (!AM_MASTER(work))
+ {
+ /* 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,
+ server_type,name,comment,
+ False, False, ipzero, d->bcast_ip);
+ }
+ else
+ {
+ /* we are the WINS server, but not the domain master. */
+ /* XXXX we need to look up the domain master in our
+ WINS database list, and do_announce_host(). maybe
+ we could do a name query on the unsuspecting domain
+ master just to make sure it's awake. */
+ }
+ }
+
+ if (AM_DOMCTL(work))
+ {
+ /* XXXX announce to backup domain masters? */
+ }
+
+ /* 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!
+ */
+ }
+ else
+ {
+ if (AM_MASTER(work))
+ {
+ DEBUG(3,("sending local master announce to %s for %s(1e)\n",
+ 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);
+
+ DEBUG(3,("sending domain announce to %s for %s\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
+
+ /* XXXX should we do a domain-announce-kill? */
+ if (server_type != 0)
+ {
+ if (AM_DOMCTL(work))
+ {
+ domain_type |= SV_TYPE_DOMAIN_CTRL;
+ }
+ 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);
+ }
+ }
+ else
+ {
+ DEBUG(3,("sending host announce to %s for %s(1d)\n",
+ 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);
+ }
+ }
+}
+
/****************************************************************************
construct a host announcement unicast
**************************************************************************/
void announce_host(void)
{
time_t t = time(NULL);
- pstring outbuf;
- char *p;
- char *namep;
- char *stypep;
- char *commentp;
+ struct subnet_record *d;
pstring comment;
char *my_name;
- struct domain_record *d;
StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43);
my_name = *myname ? myname : "NoName";
- for (d = domainlist; d; d = d->next)
+ for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
- if (!ismybcast(d->bcast_ip))
- continue;
+ if (ip_equal(d->bcast_ip, ipgrp)) continue;
for (work = d->workgrouplist; work; work = work->next)
{
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->announce_interval = MIN(work->announce_interval,
+ CHECK_TIME_MIN_HOST_ANNCE*60);
work->lastannounce_time = t - (work->announce_interval+1);
}
work->lastannounce_time = t;
- if (!ismybcast(d->bcast_ip)) {
+ /*
+ if (!d->my_interface) {
stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER |
SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER |
SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_MEMBER);
}
+ */
for (s = work->serverlist; s; s = s->next) {
if (strequal(myname, s->serv.name)) {
}
if (announce)
- {
- bzero(outbuf,sizeof(outbuf));
- p = outbuf+1;
-
- CVAL(p,0) = updatecount;
- /* ms - despite the spec */
- SIVAL(p,1,work->announce_interval*1000);
- namep = p+5;
- StrnCpy(namep,my_name,16);
- strupper(namep);
- CVAL(p,21) = 2; /* major version */
- CVAL(p,22) = 2; /* minor version */
- stypep = p+23;
- SIVAL(p,23,stype);
- SSVAL(p,27,0xaa55); /* browse signature */
- SSVAL(p,29,1); /* browse version */
- commentp = p+31;
- strcpy(commentp,comment);
- p = p+31;
- p = skip_string(p,1);
-
- if (ismybcast(d->bcast_ip))
- {
- if (AM_MASTER(work))
- {
- SIVAL(stypep,0,work->ServerType);
-
- DEBUG(2,("sending local master announce to %s for %s\n",
- inet_ntoa(d->bcast_ip),work->work_group));
-
- CVAL(outbuf,0) = ANN_LocalMasterAnnouncement;
-
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
- PTR_DIFF(p,outbuf),
- my_name,work->work_group,0,
- 0x1e,d->bcast_ip,
- *iface_ip(d->bcast_ip));
-
- DEBUG(2,("sending domain announce to %s for %s\n",
- inet_ntoa(d->bcast_ip),work->work_group));
-
- CVAL(outbuf,0) = ANN_DomainAnnouncement;
-
- StrnCpy(namep,work->work_group,15);
- strupper(namep);
- StrnCpy(commentp,myname,15);
- strupper(commentp);
-
- SIVAL(stypep,0,(unsigned)0x80000000);
- p = commentp + strlen(commentp) + 1;
-
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
- PTR_DIFF(p,outbuf),
- my_name,MSBROWSE,0,0x01,d->bcast_ip,
- *iface_ip(d->bcast_ip));
- }
- else
- {
- DEBUG(2,("sending host announce to %s for %s\n",
- inet_ntoa(d->bcast_ip),work->work_group));
-
- CVAL(outbuf,0) = ANN_HostAnnouncement;
-
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
- PTR_DIFF(p,outbuf),
- my_name,work->work_group,0,0x1d,
- d->bcast_ip,*iface_ip(d->bcast_ip));
- }
- }
- }
+ {
+ 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 myself as a master to all other primary domain conrollers.
- BIG NOTE: this code will remain untested until some kind soul that has access
- to a couple of windows NT advanced servers runs this version of nmbd for at
- least 15 minutes.
-
this actually gets done in search_and_sync_workgroups() via the
- MASTER_SERVER_CHECK command, 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)
{
- struct domain_record *d;
+ struct subnet_record *d;
static time_t last=0;
time_t t = time(NULL);
BOOL am_master = False; /* are we a master of some sort? :-) */
- if (last && (t-last < CHECK_TIME_MST_ANNOUNCE * 60))
- return;
+ if (!last) last = t;
+ if (t-last < CHECK_TIME_MST_ANNOUNCE * 60)
+ return;
last = t;
- for (d = domainlist; d; d = d->next)
+ for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
if (!am_master) return; /* only proceed if we are a master browser */
- for (d = domainlist; d; d = d->next)
+ for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{
if (strequal(s->serv.name, myname)) continue;
- /* all PDCs (which should also be master browsers) */
+ /* 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
{
if (!lp_wins_support() && *lp_wins_server())
{
- struct in_addr ip;
- ip = ipzero;
-
- queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,
- MASTER_SERVER_CHECK,
- work->work_group,0x1b,0,
- False, False, ip);
+ 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 domain_record *d2;
- for (d2 = domainlist; d2; d2 = d2->next)
+ struct subnet_record *d2;
+ for (d2 = subnetlist; d2; d2 = d2->next)
{
- queue_netbios_packet(ClientNMB,NMB_QUERY,
- MASTER_SERVER_CHECK,
- work->work_group,0x1b,0,
- True, False, d2->bcast_ip);
+ 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);
}
}
}
bcast = True;
}
- DEBUG(2, ("Searching for PDC %s at %s\n",
+ 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(ClientNMB, NMB_QUERY,MASTER_SERVER_CHECK,
- work->work_group,0x1b, 0,
- bcast, False, ip);
+ 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);
}
}
}