as a result of the writing of namework.doc, namework.c has been tidied up,
authorSamba Release Account <samba-bugs@samba.org>
Tue, 2 Jul 1996 15:31:33 +0000 (15:31 +0000)
committerSamba Release Account <samba-bugs@samba.org>
Tue, 2 Jul 1996 15:31:33 +0000 (15:31 +0000)
some bugs fixed / documented and some discrepancies noted down (in
namework.c as well as namework.doc)

namebrowse.c and namelogon.c contain functions that were inappropriately
placed in namework.c. namebrowse.c contains browse sync queue management
functions that were inappropriately placed in namedb.c

the 'cmd_type' member of response_record has been renamed to 'state'
because that more accurately reflects it purpose (not entirely. sigh).

fixed a bug in nameserv.c that meant the previous version wouldn't
compile.

there's probably a bit more...

lkcl
(This used to be commit a66417ebe871a1c1366c395ea4c7099852975e65)

source3/include/nameserv.h
source3/nameannounce.c
source3/namebrowse.c [new file with mode: 0644]
source3/namedb.c
source3/nameelect.c
source3/namelogon.c [new file with mode: 0644]
source3/nameresp.c
source3/nameserv.c
source3/namework.c

index 03bb5215586f94c0e14f2d678462117548931f00..9e4145213b7cf6abdbcc867dedb989314e917188 100644 (file)
@@ -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)
 #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
index 5163c4aea9ad1c627cde2cb7eeb5a7ff8e4e976d..0fad2fe7ecc8356ad85bd2e232dcd25f506f4b72 100644 (file)
@@ -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 (file)
index 0000000..31ee934
--- /dev/null
@@ -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);
+  }
+
+}
+
index a1442c0f03bed62f348a6f357dbe81f4d3fd2396..1855103c99c671c6fa96549dc7c27b4ffc57ad46 100644 (file)
@@ -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;
 
@@ -229,29 +226,6 @@ static void add_subnet(struct subnet_record *d)
   d->prev = d2;
 }
 
-/***************************************************************************
-  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
   **************************************************************************/
@@ -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;
@@ -546,73 +489,6 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
   return NULL;
 }
 
-/****************************************************************************
-  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
   ****************************************************************************/
@@ -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
   ******************************************************************/
index c841d9b7a60a9dddd67900335cf1e8581190fd47..855ea263484c546b3c6af71d96a1d4ed390b7116 100644 (file)
@@ -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 (file)
index 0000000..8a7fe87
--- /dev/null
@@ -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));  
+}
index 14b995618630d33c26519f9de192588d736de4ad..8484cb4fd12916e6c65652b3cf07377aea68bc43 100644 (file)
@@ -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)))
     {
index 557bad73c3cc900d9d1aacef6a7c50b16daf4e26..9025b66429fdc80c27294d332e76de5332d2816c 100644 (file)
@@ -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);
 }
 
index f0fca0071e3bc2d7f1b31ace9a60d15ce45b2976..7307ddce04f8b996fc2990e610e1a83a13e3d4de 100644 (file)
@@ -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;
@@ -744,89 +684,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;
    }
 }