summaryrefslogtreecommitdiff
path: root/source3/namework.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/namework.c')
-rw-r--r--source3/namework.c516
1 files changed, 189 insertions, 327 deletions
diff --git a/source3/namework.c b/source3/namework.c
index f0fca0071e..7307ddce04 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -45,12 +45,6 @@ extern struct in_addr ipzero;
extern int workgroup_count; /* total number of workgroups we know about */
-/* this is our browse cache database */
-extern struct browse_cache_record *browserlist;
-
-/* this is our domain/workgroup/server database */
-extern struct interface *local_interfaces;
-
/* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist;
@@ -70,8 +64,6 @@ extern int updatecount;
extern time_t StartupTime;
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
-
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
@@ -106,6 +98,11 @@ tell a server to become a backup browser
**************************************************************************/
void tell_become_backup(void)
{
+ /* XXXX note: this function is currently unsuitable for use, as it
+ does not properly check that a server is in a fit state to become
+ a backup browser before asking it to be one.
+ */
+
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{
@@ -155,234 +152,6 @@ void tell_become_backup(void)
}
}
-/****************************************************************************
-find a server responsible for a workgroup, and sync browse lists
-**************************************************************************/
-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))) 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,NAME_QUERY_SYNC,
- b->group,0x20,0,0,
- False,False,b->ip);
- }
-
- b->synced = True;
-}
-
-
-/****************************************************************************
-search through browser list for an entry to sync with
-**************************************************************************/
-void do_browser_lists(void)
-{
- struct browse_cache_record *b;
- static time_t last = 0;
- time_t t = time(NULL);
-
- if (t-last < 20) return; /* don't do too many of these at once! */
- /* XXXX equally this period should not be too long
- the server may die in the intervening gap */
-
- last = t;
-
- /* pick any entry in the list, preferably one whose time is up */
- for (b = browserlist; b && b->next; b = b->next)
- {
- if (b->sync_time < t && b->synced == False) break;
- }
-
- if (b && !b->synced)
- {
- /* sync with the selected entry then remove some dead entries */
- start_sync_browse_entry(b);
- expire_browse_cache(t - 60);
- }
-
-}
-
-
-/****************************************************************************
-find a server responsible for a workgroup, and sync browse lists
-control ends up back here via response_name_query.
-**************************************************************************/
-void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
- int name_type,
- struct in_addr ip)
-{
- add_browser_entry(serv_name, name_type, work_name, 0, ip);
-
- if (cmd == NAME_QUERY_MST_SRV_CHK)
- {
- /* announce ourselves as a master browser to serv_name */
- do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
- 0x20, 0, ip);
- }
-}
-
-
-/****************************************************************************
- add the default workgroup into my domain
- **************************************************************************/
-void add_my_subnets(char *group)
-{
- struct interface *i;
-
- /* add or find domain on our local subnet, in the default workgroup */
-
- if (*group == '*') return;
-
- /* 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_subnet_entry(i->bcast,i->nmask,group, True, False);
- }
-}
-
-
-/****************************************************************************
- send a backup list response.
- **************************************************************************/
-static void send_backup_list(char *work_name, struct nmb_name *src_name,
- int info_count, int token, int info,
- int name_type, struct in_addr ip)
-{
- struct subnet_record *d;
- char outbuf[1024];
- char *p, *countptr, *nameptr;
- int count = 0;
- int i, j;
- char *theirname = src_name->name;
-
- DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
- work_name, inet_ntoa(ip),
- myname,0x20,theirname,0x0));
-
- if (name_type == 0x1d)
- {
- DEBUG(4,("master browsers: "));
- }
- else if (name_type == 0x1b)
- {
- DEBUG(4,("domain controllers: "));
- }
- else
- {
- DEBUG(0,("backup request for unknown type %0x\n", name_type));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
-
- CVAL(p,0) = 10; /* backup list response */
- p++;
-
- countptr = p; /* count pointer */
-
- SSVAL(p,1,token); /* sender's workgroup index representation */
- SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
- p += 5;
-
- nameptr = p;
-
- for (d = subnetlist; d; d = d->next)
- {
- struct work_record *work;
-
- 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);
- }
- }
- }
- }
-
- if (count == 0)
- {
- DEBUG(4, ("none\n"));
- return;
- }
- else
- {
- DEBUG(4, (" - count %d\n", count));
- }
-
- CVAL(countptr,0) = count; /* total number of backup browsers found */
-
- {
- int len = PTR_DIFF(p, outbuf);
-
- 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", outbuf[i+j]));
- }
-
- DEBUG(4, ("\n"));
- }
-
- }
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- myname,theirname,0x20,0,ip,*iface_ip(ip));
-}
-
/*******************************************************************
same context: scope. should check name_type as well, and makes sure
@@ -471,7 +240,16 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
if (same_context(dgram)) return;
- if (command == ANN_DomainAnnouncement) {
+ if (command == ANN_DomainAnnouncement) {
+ /* XXXX if we are a master browser for the workgroup work_name,
+ then there is a local subnet configuration problem. only
+ we should be sending out such domain announcements, because
+ as the master browser, that is our job.
+
+ stop being a master browser, and force an election. this will
+ sort out the network problem. hopefully.
+ */
+
work_name = name;
} else {
work_name = dgram->dest_name.name;
@@ -501,6 +279,14 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
tell_become_backup();
#endif
+ /* XXXX over-kill: i don't think we should really be doing this,
+ but it doesn't do much harm other than to add extra network
+ traffic. to be more precise, we should (possibly) only
+ sync browse lists with a host that sends an
+ ANN_LocalMasterAnnouncement or an ANN_DomainAnnouncement.
+ possibly.
+ */
+
/* get their browse list from them and add it to ours. */
add_browser_entry(serv_name,dgram->dest_name.name_type,
work->work_group,30,ip);
@@ -543,6 +329,12 @@ static void process_master_announce(struct packet_struct *p,char *buf)
we receive a list of servers, and we attempt to locate them all on
our local subnet, and sync browse lists with them on the workgroup
they are said to be in.
+
+ XXXX NOTE: this function is in overdrive. it should not really do
+ half of what it actually does (it should pick _one_ name from the
+ list received and sync with it at regular intervals, rather than
+ sync with them all only once!)
+
******************************************************************/
static void process_rcv_backup_list(struct packet_struct *p,char *buf)
{
@@ -570,7 +362,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
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 */
+ approach is to use reply_name_query functionality to find the name */
back_ip = *interpret_addr2(buf1);
if (zero_ip(back_ip))
@@ -602,10 +394,143 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
}
}
+
+/****************************************************************************
+ send a backup list response.
+ **************************************************************************/
+static void send_backup_list(char *work_name, struct nmb_name *src_name,
+ int info_count, int token, int info,
+ int name_type, struct in_addr ip)
+{
+ struct subnet_record *d;
+ char outbuf[1024];
+ char *p, *countptr, *nameptr;
+ int count = 0;
+ int i, j;
+ char *theirname = src_name->name;
+
+ DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
+ work_name, inet_ntoa(ip),
+ myname,0x20,theirname,0x0));
+
+ if (name_type == 0x1d)
+ {
+ DEBUG(4,("master browsers: "));
+ }
+ else if (name_type == 0x1b)
+ {
+ DEBUG(4,("domain controllers: "));
+ }
+ else
+ {
+ DEBUG(0,("backup request for unknown type %0x\n", name_type));
+ return;
+ }
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+
+ CVAL(p,0) = ANN_GetBackupListResp; /* backup list response */
+ p++;
+
+ countptr = p; /* count pointer */
+
+ SSVAL(p,1,token); /* sender's workgroup index representation */
+ SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
+ p += 5;
+
+ nameptr = p;
+
+ for (d = subnetlist; d; d = d->next)
+ {
+ struct work_record *work;
+
+ 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);
+ }
+ }
+ }
+ }
+
+ if (count == 0)
+ {
+ DEBUG(4, ("none\n"));
+ return;
+ }
+ else
+ {
+ DEBUG(4, (" - count %d\n", count));
+ }
+
+ CVAL(countptr,0) = count; /* total number of backup browsers found */
+
+ {
+ int len = PTR_DIFF(p, outbuf);
+
+ 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", outbuf[i+j]));
+ }
+
+ DEBUG(4, ("\n"));
+ }
+
+ }
+ send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ myname,theirname,0x20,0x0,ip,*iface_ip(ip));
+}
+
+
/*******************************************************************
process a send backup list request
- A client send a backup list request to ask for a list of servers on
+ A client sends a backup list request to ask for a list of servers on
the net that maintain server lists for a domain. A server is then
chosen from this list to send NetServerEnum commands to to list
available servers.
@@ -618,7 +543,7 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d;
+ struct subnet_record *d;
struct work_record *work;
int count = CVAL(buf,0);
@@ -658,7 +583,7 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
process a reset browser state
diagnostic packet:
- 0x1 - stop being a master browser
+ 0x1 - stop being a master browser and become a backup browser.
0x2 - discard browse lists, stop being a master browser, try again.
0x4 - stop being a master browser forever. no way. ain't gonna.
@@ -688,6 +613,10 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
}
}
+ /* XXXX documentation inconsistency: the above description does not
+ exactly tally with what is implemented for state & 0x2
+ */
+
/* totally delete all servers and start afresh */
if (state & 0x2)
{
@@ -730,12 +659,23 @@ static void process_announce_request(struct packet_struct *p,char *buf)
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.
+
+ if (strequal(dgram->dest_name, lp_workgroup()) return; ???
+ */
+
if (!d) return;
if (!d->my_interface) return;
for (work = d->workgrouplist; work; work = work->next)
{
+ /* 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;
@@ -745,89 +685,6 @@ static void process_announce_request(struct packet_struct *p,char *buf)
/****************************************************************************
- process a domain logon packet
- **************************************************************************/
-void process_logon_packet(struct packet_struct *p,char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d = find_subnet(ip);
- char *logname,*q;
- char *reply_name;
- BOOL add_slashes = False;
- pstring outbuf;
- int code,reply_code;
- struct work_record *work;
-
- if (!d) return;
-
- if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
- return;
-
- if (!lp_domain_logons()) {
- DEBUG(3,("No domain logons\n"));
- return;
- }
- if (!listening_name(work, &dgram->dest_name))
- {
- DEBUG(4,("Not listening to that domain\n"));
- return;
- }
-
- code = SVAL(buf,0);
- switch (code) {
- case 0:
- {
- char *machine = buf+2;
- char *user = skip_string(machine,1);
- logname = skip_string(user,1);
- reply_code = 6;
- reply_name = myname;
- add_slashes = True;
- DEBUG(3,("Domain login request from %s(%s) user=%s\n",
- machine,inet_ntoa(p->ip),user));
- }
- break;
- case 7:
- {
- char *machine = buf+2;
- logname = skip_string(machine,1);
- reply_code = 7;
- reply_name = lp_domain_controller();
- if (!*reply_name) {
- DEBUG(3,("No domain controller configured\n"));
- return;
- }
- DEBUG(3,("GETDC request from %s(%s)\n",
- machine,inet_ntoa(p->ip)));
- }
- break;
- default:
- DEBUG(3,("Unknown domain request %d\n",code));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- q = outbuf;
- SSVAL(q,0,reply_code);
- q += 2;
- if (add_slashes) {
- strcpy(q,"\\\\");
- q += 2;
- }
- StrnCpy(q,reply_name,16);
- strupper(q);
- q = skip_string(q,1);
- SSVAL(q,0,0xFFFF);
- q += 2;
-
- send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
- myname,&dgram->source_name.name[0],0x20,0,p->ip,
- *iface_ip(p->ip));
-}
-
-
-/****************************************************************************
depending on what announce has been made, we are only going to
accept certain types of name announce. XXXX untested code
@@ -988,11 +845,16 @@ void process_dgram(struct packet_struct *p)
if (len <= 0) return;
- if (strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
- {
+ /* datagram packet received for the browser mailslot */
+ if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
process_browse_packet(p,buf2,len);
- } else if (strequal(smb_buf(buf),"\\MAILSLOT\\NET\\NETLOGON")) {
+ return;
+ }
+
+ /* datagram packet received for the domain log on mailslot */
+ if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
process_logon_packet(p,buf2,len);
+ return;
}
}