summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/nameserv.h23
-rw-r--r--source3/nameannounce.c40
-rw-r--r--source3/namebrowse.c215
-rw-r--r--source3/namedb.c169
-rw-r--r--source3/nameelect.c14
-rw-r--r--source3/namelogon.c119
-rw-r--r--source3/nameresp.c20
-rw-r--r--source3/nameserv.c51
-rw-r--r--source3/namework.c516
9 files changed, 646 insertions, 521 deletions
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index 03bb521558..9e4145213b 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -24,7 +24,7 @@
#define MAINTAIN_LIST 2
#define ELECTION_VERSION 1
-#define MAX_DGRAM_SIZE (80*18+64)
+#define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */
#define MIN_DGRAM_SIZE 12
#define NMB_QUERY 0x20
@@ -36,6 +36,7 @@
#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.17 */
/* XXXX what about all the other types?? 0x1, 0x2, 0x3, 0x4, 0x8? */
+/* NetBIOS flags */
#define NB_GROUP 0x80
#define NB_PERM 0x02
#define NB_ACTIVE 0x04
@@ -51,6 +52,7 @@
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
+/* NetBIOS flag identifier */
#define NAME_PERMANENT(p) ((p) & NB_PERM)
#define NAME_ACTIVE(p) ((p) & NB_ACTIVE)
#define NAME_CONFLICT(p) ((p) & NB_CONFL)
@@ -62,12 +64,22 @@
#define NAME_MFLAG(p) (((p) & NB_FLGMSK) == NB_MFLAG)
#define NAME__FLAG(p) (((p) & NB_FLGMSK) == NB__FLAG)
+/* server type identifiers */
+#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
+#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
+#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL)
+
+/* microsoft browser NetBIOS name */
#define MSBROWSE "\001\002__MSBROWSE__\002"
+/* mail slots */
+#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+#define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON"
+
enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL};
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
-enum cmd_type
+enum state_type
{
NAME_STATUS_MASTER_CHECK,
NAME_STATUS_CHECK,
@@ -161,7 +173,7 @@ struct response_record
struct response_record *prev;
uint16 response_id;
- enum cmd_type cmd_type;
+ enum state_type state;
int fd;
int quest_type;
@@ -301,11 +313,6 @@ struct packet_struct
};
-#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
-#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
-#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL)
-
-
/* ids for netbios packet types */
#define ANN_HostAnnouncement 1
#define ANN_AnnouncementRequest 2
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index 5163c4aea9..0fad2fe7ec 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -50,8 +50,6 @@ extern int workgroup_count;
/* what server type are we currently */
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
-
/****************************************************************************
send a announce request to the local net
**************************************************************************/
@@ -109,6 +107,26 @@ void do_announce_request(char *info, char *to_name, int announce_type,
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)
+{
+ add_browser_entry(serv_name, name_type, work_name, 0, ip);
+
+ if (state == 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);
+ }
+}
+
+
/****************************************************************************
construct a host announcement unicast
**************************************************************************/
@@ -294,8 +312,8 @@ void announce_host(void)
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);
}
@@ -323,18 +341,18 @@ void announce_host(void)
}
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 */
- }
+ }
}
- }
+ }
}
@@ -356,8 +374,8 @@ void announce_master(void)
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 && (t-last < CHECK_TIME_MST_ANNOUNCE * 60))
+ return;
last = t;
diff --git a/source3/namebrowse.c b/source3/namebrowse.c
new file mode 100644
index 0000000000..31ee9347ec
--- /dev/null
+++ b/source3/namebrowse.c
@@ -0,0 +1,215 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1995
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+/* this is our browse master/backup cache database */
+static struct browse_cache_record *browserlist = NULL;
+
+
+/***************************************************************************
+ add a browser into the list
+ **************************************************************************/
+static void add_browse_cache(struct browse_cache_record *b)
+{
+ struct browse_cache_record *b2;
+
+ if (!browserlist)
+ {
+ browserlist = b;
+ b->prev = NULL;
+ b->next = NULL;
+ return;
+ }
+
+ for (b2 = browserlist; b2->next; b2 = b2->next) ;
+
+ b2->next = b;
+ b->next = NULL;
+ b->prev = b2;
+}
+
+
+/*******************************************************************
+ remove old browse entries
+ ******************************************************************/
+void expire_browse_cache(time_t t)
+{
+ struct browse_cache_record *b;
+ struct browse_cache_record *nextb;
+
+ /* expire old entries in the serverlist */
+ 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);
+ }
+ else
+ {
+ nextb = b->next;
+ }
+ }
+}
+
+
+/****************************************************************************
+ 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 newentry=False;
+
+ struct browse_cache_record *b;
+
+ /* search for the entry: if it's already in the cache, update that entry */
+ for (b = browserlist; b; b = b->next)
+ {
+ if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
+ }
+
+ if (b && b->synced)
+ {
+ /* entries get left in the cache for a while. this stops sync'ing too
+ 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));
+ return NULL;
+ }
+
+ if (!b)
+ {
+ newentry = True;
+ b = (struct browse_cache_record *)malloc(sizeof(*b));
+
+ if (!b) return(NULL);
+
+ bzero((char *)b,sizeof(*b));
+ }
+
+ /* update the entry */
+ ttl = time(NULL)+ttl;
+
+ StrnCpy(b->name ,name,sizeof(b->name )-1);
+ StrnCpy(b->group,wg ,sizeof(b->group)-1);
+ strupper(b->name);
+ strupper(b->group);
+
+ b->ip = ip;
+ b->type = type;
+
+ if (newentry || ttl < b->sync_time)
+ b->sync_time = ttl;
+
+ if (newentry)
+ {
+ b->synced = False;
+ add_browse_cache(b);
+
+ DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
+ 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));
+ }
+
+ return(b);
+}
+
+
+/****************************************************************************
+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);
+ }
+
+}
+
diff --git a/source3/namedb.c b/source3/namedb.c
index a1442c0f03..1855103c99 100644
--- a/source3/namedb.c
+++ b/source3/namedb.c
@@ -40,9 +40,6 @@ extern pstring scope;
extern struct in_addr ipgrp;
extern struct in_addr ipzero;
-/* this is our browse master/backup cache database */
-struct browse_cache_record *browserlist = NULL;
-
/* local interfaces structure */
extern struct interface *local_interfaces;
@@ -230,29 +227,6 @@ static void add_subnet(struct subnet_record *d)
}
/***************************************************************************
- add a browser into the list
- **************************************************************************/
-static void add_browse_cache(struct browse_cache_record *b)
-{
- struct browse_cache_record *b2;
-
- if (!browserlist)
- {
- browserlist = b;
- b->prev = NULL;
- b->next = NULL;
- return;
- }
-
- for (b2 = browserlist; b2->next; b2 = b2->next) ;
-
- b2->next = b;
- b->next = NULL;
- b->prev = b2;
-}
-
-
-/***************************************************************************
add a server into the list
**************************************************************************/
static void add_server(struct work_record *work,struct server_record *s)
@@ -274,37 +248,6 @@ static void add_server(struct work_record *work,struct server_record *s)
}
-/*******************************************************************
- remove old browse entries
- ******************************************************************/
-void expire_browse_cache(time_t t)
-{
- struct browse_cache_record *b;
- struct browse_cache_record *nextb;
-
- /* expire old entries in the serverlist */
- 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);
- }
- else
- {
- nextb = b->next;
- }
- }
-}
-
-
/****************************************************************************
find a workgroup in the workgrouplist
only create it if the domain allows it, or the parameter 'add' insists
@@ -387,8 +330,8 @@ struct subnet_record *find_subnet(struct in_addr bcast_ip)
}
else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
{
- return(d);
- }
+ return(d);
+ }
}
return (NULL);
@@ -447,7 +390,7 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr
d->mask_ip = mask_ip;
d->workgrouplist = NULL;
d->my_interface = False; /* True iff the interface is on the samba host */
-
+
add_subnet(d);
return d;
@@ -506,7 +449,7 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
char *name, BOOL add, BOOL lmhosts)
{
struct subnet_record *d;
-
+
/* 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.
@@ -514,7 +457,7 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
struct in_addr ip = ipgrp;
*/
-
+
if (zero_ip(bcast_ip))
bcast_ip = *iface_bcast(bcast_ip);
@@ -536,9 +479,9 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
}
/* add samba server name to workgroup list */
if ((strequal(lp_workgroup(), name) && d->my_interface) || lmhosts)
- {
- add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True);
- }
+ {
+ add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True);
+ }
DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(bcast_ip)));
return d;
@@ -547,73 +490,6 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
}
/****************************************************************************
- 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 newentry=False;
-
- struct browse_cache_record *b;
-
- /* search for the entry: if it's already in the cache, update that entry */
- for (b = browserlist; b; b = b->next)
- {
- if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
- }
-
- if (b && b->synced)
- {
- /* entries get left in the cache for a while. this stops sync'ing too
- 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));
- return NULL;
- }
-
- if (!b)
- {
- newentry = True;
- b = (struct browse_cache_record *)malloc(sizeof(*b));
-
- if (!b) return(NULL);
-
- bzero((char *)b,sizeof(*b));
- }
-
- /* update the entry */
- ttl = time(NULL)+ttl;
-
- StrnCpy(b->name ,name,sizeof(b->name )-1);
- StrnCpy(b->group,wg ,sizeof(b->group)-1);
- strupper(b->name);
- strupper(b->group);
-
- b->ip = ip;
- b->type = type;
-
- if (newentry || ttl < b->sync_time)
- b->sync_time = ttl;
-
- if (newentry)
- {
- b->synced = False;
- add_browse_cache(b);
-
- DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
- 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));
- }
-
- return(b);
-}
-
-
-/****************************************************************************
remove all samba's server entries
****************************************************************************/
void remove_my_servers(void)
@@ -664,8 +540,8 @@ struct server_record *add_server_entry(struct subnet_record *d,
}
if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
- updatedlists=True;
-
+ updatedlists=True;
+
if (!s)
{
newentry = True;
@@ -679,8 +555,8 @@ struct server_record *add_server_entry(struct subnet_record *d,
if (d->my_interface && strequal(lp_workgroup(),work->work_group))
{
- if (servertype)
- servertype |= SV_TYPE_LOCAL_LIST_ONLY;
+ if (servertype)
+ servertype |= SV_TYPE_LOCAL_LIST_ONLY;
}
else
{
@@ -717,6 +593,27 @@ struct server_record *add_server_entry(struct subnet_record *d,
}
+/****************************************************************************
+ 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);
+ }
+}
+
+
/*******************************************************************
write out browse.dat
******************************************************************/
diff --git a/source3/nameelect.c b/source3/nameelect.c
index c841d9b7a6..855ea26348 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -42,8 +42,6 @@ extern pstring ServerComment;
extern time_t StartupTime;
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
-
extern struct subnet_record *subnetlist;
@@ -57,7 +55,7 @@ void check_master_browser(void)
struct subnet_record *d;
if (!lastrun) lastrun = t;
- if (t < lastrun + CHECK_TIME_MST_BROWSE * 60)
+ if (t < lastrun + CHECK_TIME_MST_BROWSE * 60)
return;
lastrun = t;
@@ -215,7 +213,7 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
/* unbecome a master browser; unbecome a domain master, too :-( */
if (remove_type & SV_TYPE_MASTER_BROWSER)
remove_type |= SV_TYPE_DOMAIN_MASTER;
-
+
new_server_type &= ~remove_type;
if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)))
@@ -223,8 +221,8 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
/* no longer a master browser of any sort */
work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
- work->ElectionCriterion &= ~0x4;
-
+ work->ElectionCriterion &= ~0x4;
+
/* 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);
@@ -356,10 +354,10 @@ void process_election(struct packet_struct *p,char *buf)
/* 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);
- }
+ }
}
}
}
diff --git a/source3/namelogon.c b/source3/namelogon.c
new file mode 100644
index 0000000000..8a7fe87965
--- /dev/null
+++ b/source3/namelogon.c
@@ -0,0 +1,119 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1995
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+
+extern int ClientDGRAM;
+
+#define TEST_CODE /* want to debug unknown browse packets */
+
+extern int DEBUGLEVEL;
+
+extern pstring myname;
+
+
+/****************************************************************************
+ 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));
+}
diff --git a/source3/nameresp.c b/source3/nameresp.c
index 14b9956186..8484cb4fd1 100644
--- a/source3/nameresp.c
+++ b/source3/nameresp.c
@@ -86,7 +86,7 @@ static void dead_netbios_entry(struct subnet_record *d,
DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
- switch (n->cmd_type)
+ switch (n->state)
{
case NAME_QUERY_CONFIRM:
{
@@ -384,10 +384,16 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
WINS server specified, the packet will NOT be sent.
****************************************************************************/
void queue_netbios_pkt_wins(struct subnet_record *d,
- int fd,int quest_type,enum cmd_type cmd,
+ int fd,int quest_type,enum state_type state,
char *name,int name_type,int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse,struct in_addr to_ip)
{
+ /* 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 */
@@ -409,7 +415,7 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
if (zero_ip(to_ip)) return;
- queue_netbios_packet(d,fd, quest_type, cmd,
+ queue_netbios_packet(d,fd, quest_type, state,
name, name_type, nb_flags, ttl,
bcast, recurse, to_ip);
}
@@ -418,7 +424,7 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
create a name query response record
**************************************************************************/
static struct response_record *
-make_response_queue_record(enum cmd_type cmd,int id,int fd,
+make_response_queue_record(enum state_type state,int id,int fd,
int quest_type, char *name,int type, int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse, struct in_addr ip)
{
@@ -430,7 +436,7 @@ make_response_queue_record(enum cmd_type cmd,int id,int fd,
return(NULL);
n->response_id = id;
- n->cmd_type = cmd;
+ n->state = state;
n->fd = fd;
n->quest_type = quest_type;
make_nmb_name(&n->name, name, type, scope);
@@ -459,7 +465,7 @@ make_response_queue_record(enum cmd_type cmd,int id,int fd,
complete lists across a wide area network
****************************************************************************/
void queue_netbios_packet(struct subnet_record *d,
- int fd,int quest_type,enum cmd_type cmd,char *name,
+ int fd,int quest_type,enum state_type state,char *name,
int name_type,int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse, struct in_addr to_ip)
{
@@ -475,7 +481,7 @@ void queue_netbios_packet(struct subnet_record *d,
if (id == 0xffff) return;
- if ((n = make_response_queue_record(cmd,id,fd,
+ if ((n = make_response_queue_record(state,id,fd,
quest_type,name,name_type,nb_flags,ttl,
bcast,recurse,to_ip)))
{
diff --git a/source3/nameserv.c b/source3/nameserv.c
index 557bad73c3..9025b66429 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -64,6 +64,7 @@ static struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast)
return find_subnet(ipgrp);
}
+
/****************************************************************************
true if two netbios names are equal
****************************************************************************/
@@ -74,6 +75,7 @@ static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
}
+
/****************************************************************************
add a netbios name into the namelist
**************************************************************************/
@@ -98,6 +100,7 @@ static void add_name(struct subnet_record *d, struct name_record *n)
n->prev = n2;
}
+
/****************************************************************************
remove a name from the namelist. The pointer must be an element just
retrieved
@@ -1360,15 +1363,15 @@ void reply_name_query(struct packet_struct *p)
/****************************************************************************
- response from a name query server check. commands of type NAME_QUERY_MST_SRV_CHK,
+ response from a name query server check. states of type NAME_QUERY_MST_SRV_CHK,
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)
{
- /* issue another command: this time to do a name status check */
+ /* issue another state: this time to do a name status check */
- enum cmd_type cmd = (n->cmd_type == NAME_QUERY_MST_SRV_CHK) ?
+ enum state_type cmd = (n->state == NAME_QUERY_MST_SRV_CHK) ?
NAME_STATUS_MASTER_CHECK : NAME_STATUS_CHECK;
/* initiate a name status check on the server that replied */
@@ -1379,7 +1382,7 @@ static void response_server_check(struct nmb_name *ans_name,
}
/****************************************************************************
- response from a name status check. commands of type NAME_STATUS_MASTER_CHECK
+ response from a name status check. states of type NAME_STATUS_MASTER_CHECK
and NAME_STATUS_CHECK dealt with here.
****************************************************************************/
static void response_name_status_check(struct in_addr ip,
@@ -1397,7 +1400,7 @@ static void response_name_status_check(struct in_addr ip,
{
if (*serv_name)
{
- sync_server(n->cmd_type,serv_name,
+ sync_server(n->state,serv_name,
name.name,name.name_type, n->to_ip);
}
}
@@ -1410,7 +1413,7 @@ static void response_name_status_check(struct in_addr ip,
/****************************************************************************
response from a name query to sync browse lists or to update our netbios
- entry. commands of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
+ entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
****************************************************************************/
static void response_name_query_sync(struct nmb_packet *nmb,
struct nmb_name *ans_name, BOOL bcast,
@@ -1419,7 +1422,7 @@ static void response_name_query_sync(struct nmb_packet *nmb,
DEBUG(4, ("Name query at %s ip %s - ",
namestr(&n->name), inet_ntoa(n->to_ip)));
- if (!name_equal(n->name, ans_name))
+ if (!name_equal(&n->name, ans_name))
{
/* someone gave us the wrong name as a reply. oops. */
DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
@@ -1433,17 +1436,17 @@ static void response_name_query_sync(struct nmb_packet *nmb,
putip((char*)&found_ip,&nmb->answers->rdata[2]);
- if (!ip_equal(n->ip, found_ip))
+ if (!ip_equal(n->to_ip, found_ip))
{
/* someone gave us the wrong ip as a reply. oops. */
- DEBUG(4,("expected ip: %s\n", inet_ntoa(n->ip)));
+ DEBUG(4,("expected ip: %s\n", inet_ntoa(n->to_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
return;
}
DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
- if (n->cmd_type == NAME_QUERY_SYNC)
+ if (n->state == NAME_QUERY_SYNC)
{
struct work_record *work = NULL;
if ((work = find_workgroupstruct(d, ans_name->name, False)))
@@ -1465,7 +1468,7 @@ static void response_name_query_sync(struct nmb_packet *nmb,
{
DEBUG(4, (" NEGATIVE RESPONSE!\n"));
- if (n->cmd_type == NAME_QUERY_CONFIRM)
+ if (n->state == NAME_QUERY_CONFIRM)
{
/* XXXX remove_netbios_entry()? */
/* lots of things we ought to do, here. if we get here,
@@ -1473,7 +1476,7 @@ static void response_name_query_sync(struct nmb_packet *nmb,
reality. sort it out
*/
remove_netbios_name(d,n->name.name, n->name.name_type,
- REGISTER,n->ip);
+ REGISTER,n->to_ip);
}
}
}
@@ -1494,12 +1497,12 @@ static void debug_rr_type(int rr_type)
}
/****************************************************************************
- report the response record nmbd command type
+ report the response record nmbd state
****************************************************************************/
-static void debug_cmd_type(int cmd_type)
+static void debug_state_type(int state)
{
- /* report the command type to help debugging */
- switch (cmd_type)
+ /* report the state type to help debugging */
+ switch (state)
{
case NAME_QUERY_MST_SRV_CHK : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
@@ -1566,7 +1569,7 @@ static BOOL response_problem_check(struct response_record *n,
/* this may cause problems for some early versions of nmbd */
- switch (n->cmd_type)
+ switch (n->state)
{
case NAME_QUERY_MST_SRV_CHK:
case NAME_QUERY_SRV_CHK:
@@ -1609,7 +1612,7 @@ static BOOL response_problem_check(struct response_record *n,
static BOOL response_compatible(struct response_record *n,
struct nmb_packet *nmb)
{
- switch (n->cmd_type)
+ switch (n->state)
{
case NAME_RELEASE:
{
@@ -1659,7 +1662,7 @@ static BOOL response_compatible(struct response_record *n,
default:
{
- DEBUG(0,("unknown command received in response_netbios_packet\n"));
+ DEBUG(0,("unknown state type received in response_netbios_packet\n"));
break;
}
}
@@ -1674,7 +1677,7 @@ 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->cmd_type)
+ switch (n->state)
{
case NAME_RELEASE:
{
@@ -1721,7 +1724,7 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
default:
{
- DEBUG(0,("unknown command received in response_netbios_packet\n"));
+ DEBUG(0,("unknown state type received in response_netbios_packet\n"));
break;
}
}
@@ -1776,17 +1779,17 @@ static void response_netbios_packet(struct packet_struct *p)
n->num_msgs++; /* count number of responses received */
n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */
- debug_cmd_type(n->cmd_type);
+ debug_state_type(n->state);
/* problem checking: multiple responses etc */
if (response_problem_check(n, nmb, qname))
return;
- /* now check whether the command has received the correct type of response*/
+ /* now check whether the state has received the correct type of response */
if (!response_compatible(n, nmb))
return;
- /* now deal with the command */
+ /* now deal with the current state */
response_process(d, p, n, nmb, bcast, ans_name);
}
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;
}
}