removed the remote interfaces stuff.
[kai/samba.git] / source3 / namework.c
index 9697be23ef6becaeaeeaaebf99df1d18451c73dd..1a7a48aa9a74f08d8308fc43bb808701b645da17 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    NBT netbios routines and daemon - version 2
-   Copyright (C) Andrew Tridgell 1994-1995
+   Copyright (C) Andrew Tridgell 1994-1996
    
    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
@@ -26,8 +26,9 @@
 */
 
 #include "includes.h"
-#include "loadparm.h"
-#include "localnet.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
 
 #define TEST_CODE /* want to debug unknown browse packets */
 
@@ -35,22 +36,17 @@ extern int DEBUGLEVEL;
 extern pstring scope;
 extern BOOL CanRecurse;
 
-extern struct in_addr myip;
-extern struct in_addr bcast_ip;
-extern struct in_addr Netmask;
-
 extern pstring myname;
 
 extern int ClientNMB;
 extern int ClientDGRAM;
 
-extern int workgroup_count; /* total number of workgroups we know about */
+extern struct in_addr ipzero;
 
-/* this is our browse cache database */
-extern struct browse_cache_record *browserlist;
+extern int workgroup_count; /* total number of workgroups we know about */
 
 /* this is our domain/workgroup/server database */
-extern struct domain_record *domainlist;
+extern struct subnet_record *subnetlist;
 
 /* machine comment for host announcements */
 extern  pstring ServerComment;
@@ -68,14 +64,7 @@ extern int  updatecount;
 
 extern time_t StartupTime;
 
-#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
-#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
-
-#define MSBROWSE "\001\002__MSBROWSE__\002"
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
-
-#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
-
+extern BOOL updatedlists;
 
 /****************************************************************************
 tell a server to become a backup browser
@@ -99,7 +88,7 @@ void reset_server(char *name, int state, struct in_addr ip)
           name,inet_ntoa(ip),state));
 
   send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
-                     myname,name,0x20,0x1d,ip,myip);
+                     myname,name,0x20,0x1d,ip,*iface_ip(ip));
 }
 
 
@@ -108,8 +97,13 @@ tell a server to become a backup browser
 **************************************************************************/
 void tell_become_backup(void)
 {
-  struct domain_record *d;
-  for (d = domainlist; d; d = d->next)
+  /* 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)
     {
       struct work_record *work;
       for (work = d->workgrouplist; work; work = work->next)
@@ -157,261 +151,6 @@ void tell_become_backup(void)
     }
 }
 
-/****************************************************************************
-find a server responsible for a workgroup, and sync browse lists
-**************************************************************************/
-static BOOL sync_browse_entry(struct browse_cache_record *b)
-{                     
-  struct domain_record *d;
-  struct work_record *work;
-  /*
-    if (!strequal(serv_name, b->name))
-    {
-    DEBUG(0, ("browser's netbios name (%s) does not match %s (%s)",
-    b->name, inet_ntoa(b->ip), serv_name));
-    }
-    */
-  if (!(d = find_domain(b->ip))) return False;
-  if (!(work = find_workgroupstruct(d, b->group, False))) return False;
-  
-  if (AM_MASTER(work)) {
-    /* only try to sync browse lists if we are the master, otherwise
-       the net could get a little bit too busy */
-    sync_browse_lists(work,b->name,0x20,b->ip);
-  }
-  b->synced = True;
-  
-  return 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 < 4) return; /* don't do too many of these at once! */
-  
-  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_browse_entry(b))
-    {
-      /* leave entries (even ones already sync'd) for up to a minute.
-        this stops them getting re-sync'd too often */
-      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 == MASTER_SERVER_CHECK)
-    {
-      /* announce ourselves as a master browser to serv_name */
-      do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
-                         0x20, 0, ip);
-    }
-}
-
-
-/****************************************************************************
-update workgroup database from a name registration
-**************************************************************************/
-void update_from_reg(char *name, int type, struct in_addr ip)
-{                     
-  /* default server type: minimum guess at requirement XXXX */
-
-  DEBUG(3,("update from registration: host %s ip %s type %0x\n",
-           name, inet_ntoa(ip), type));
-
-  /* workgroup types, but not a chat type */
-  if (type >= 0x1b && type <= 0x1e)
-    {
-      struct work_record *work;
-      struct domain_record *d;
-      
-      if (!(d    = find_domain(ip))) return;
-      if (!(work = find_workgroupstruct(d, name, False))) return;
-      
-      /* request the server to announce if on our subnet */
-      if (ip_equal(bcast_ip, d->bcast_ip)) announce_request(work, ip);
-      
-      /* domain master type or master browser type */
-      if (type == 0x1b || type == 0x1d)
-       {
-         struct hostent *hp = gethostbyaddr((char*)&ip, sizeof(ip), AF_INET);
-         if (hp) {
-           /* gethostbyaddr name may not match netbios name but who cares */
-           add_browser_entry(hp->h_name, type, work->work_group, 120, ip);
-         }
-       }
-    }
-}
-
-
-/****************************************************************************
-  add the default workgroup into my domain
-  **************************************************************************/
-void add_my_domains(void)
-{
-  /* add or find domain on our local subnet, in the default workgroup */
-  
-  if (*lp_workgroup() != '*')
-    {
-      add_domain_entry(bcast_ip,Netmask,lp_workgroup(), True);
-    }
-}
-
-
-/****************************************************************************
-  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 domain_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 = domainlist; 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,myip);
-}
-
 
 /*******************************************************************
   same context: scope. should check name_type as well, and makes sure
@@ -457,29 +196,33 @@ BOOL listening_name(struct work_record *work, struct nmb_name *n)
   resources. We just have to pass it to smbd (via browser.dat) and let
   the client choose using bit masks.
   ******************************************************************/
-static void process_announce(struct packet_struct *p,int command,char *buf)
+static void process_announce(struct packet_struct *p,uint16 command,char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
   struct in_addr ip = dgram->header.source_ip;
-  struct domain_record *d = find_domain(ip);
-  
+  struct subnet_record *d = find_subnet(ip); 
   int update_count = CVAL(buf,0);
+
   int ttl = IVAL(buf,1)/1000;
   char *name = buf+5;
   int osmajor=CVAL(buf,21);
   int osminor=CVAL(buf,22);
   uint32 servertype = IVAL(buf,23);
+  uint32 browse_type= CVAL(buf,27);
+  uint32 browse_sig = CVAL(buf,29);
   char *comment = buf+31;
+
   struct work_record *work;
   char *work_name;
   char *serv_name = dgram->source_name.name;
-  
+  BOOL add = False;
+
   comment[43] = 0;
   
   DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
-  DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
+  DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n",
           namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
-          servertype,comment));
+          servertype,browse_type,browse_sig,comment));
   
   name[15] = 0;  
   
@@ -498,29 +241,57 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
       return;
     }
   
-  if (same_context(dgram)) return;
+  if (!strequal(dgram->dest_name.scope,scope )) 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;
+    add = True;
   } else {
     work_name = dgram->dest_name.name;
   }
+
+  /* we need some way of finding out about new workgroups
+     that appear to be sending packets to us. The name_type checks make
+     sure we don't add host names as workgroups */
+  if (command == ANN_HostAnnouncement &&
+      (dgram->dest_name.name_type == 0x1d ||
+       dgram->dest_name.name_type == 0x1e))
+    add = True;
   
-  if (!(work = find_workgroupstruct(d, work_name, False))) return;
+  if (!(work = find_workgroupstruct(d, work_name,add)))
+    return;
   
   DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
   
   ttl = GET_TTL(ttl);
   
-  /* add them to our browse list */
+  /* add them to our browse list, and update the browse.dat file */
   add_server_entry(d,work,name,servertype,ttl,comment,True);
-  
+  updatedlists = True;
+
 #if 0
   /* the tell become backup code is broken, no great harm is done by
      disabling it */
   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);
@@ -533,8 +304,8 @@ static void process_master_announce(struct packet_struct *p,char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
   struct in_addr ip = dgram->header.source_ip;
-  struct domain_record *d = find_domain(ip);
-  struct domain_record *mydomain = find_domain(bcast_ip);
+  struct subnet_record *d = find_subnet(ip);
+  struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
   char *name = buf;
   struct work_record *work;
   name[15] = 0;
@@ -563,18 +334,24 @@ 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)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
   struct in_addr ip = dgram->header.source_ip;
   int count = CVAL(buf,0);
-  int Index = IVAL(buf,1); /* caller's index representing workgroup */
+  uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
   char *buf1;
   
-  DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n",
+  DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
           namestr(&dgram->dest_name), inet_ntoa(ip),
-          count, Index));
+          count, info));
   
   if (same_context(dgram)) return;
   
@@ -582,50 +359,170 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
   
   /* go through the list of servers attempting to sync browse lists */
   for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
-    {
-      struct in_addr back_ip;
-      struct domain_record *d;
+  {
+    struct in_addr back_ip;
+    struct subnet_record *d;
       
-      DEBUG(4,("Searching for backup browser %s at %s...\n",
+    DEBUG(4,("Searching for backup browser %s at %s...\n",
               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 */
-      back_ip = *interpret_addr2(buf1);
+    /* 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 */
+
+    back_ip = *interpret_addr2(buf1);
       
-      if (zero_ip(back_ip))
+    if (zero_ip(back_ip))
        {
          DEBUG(4,("Failed to find backup browser server using DNS\n"));
          continue;
        }
       
       DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
+      DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
       
-      if ((d = find_domain(back_ip)))
+      /* XXXX function needs work */
+         continue;
+
+    if ((d = find_subnet(back_ip)))
        {
-         struct domain_record *d1;
-         for (d1 = domainlist; d1; d1 = d1->next)
-           {
+         struct subnet_record *d1;
+         for (d1 = subnetlist; d1; d1 = d1->next)
+         {
              struct work_record *work;
              for (work = d1->workgrouplist; work; work = work->next)
                {
-                 if (work->token == Index)
-                   {
-                     queue_netbios_packet(ClientNMB,NMB_QUERY,SERVER_CHECK,
-                                          work->work_group,0x1d,0,
-                                          False,False,back_ip);
+                 if (work->token == 0 /* token */)
+                 {
+                     queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
+                                          work->work_group,0x1d,0,0,
+                                          False,False,back_ip,back_ip);
                      return;
-                   }
+                 }
                }
-           }
+         }
+       }
+  }
+}
+
+
+/****************************************************************************
+  send a backup list response.
+  **************************************************************************/
+static void send_backup_list(char *work_name, struct nmb_name *src_name,
+                            int token, uint32 info,
+                            int name_type, struct in_addr ip)
+{                     
+  char outbuf[1024];
+  char *p, *countptr, *nameptr;
+  int count = 0;
+  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,0x0,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;
+
+  SIVAL(p,1,info); /* the sender's unique info */
+
+  p += 5;
+  
+  nameptr = p;
+
+#if 0
+
+  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);
+               }
+        }
        }
+  }
+
+#endif
+
+       count++;
+       strcpy(p,myname);
+       strupper(p);
+       p = skip_string(p,1);
+
+  if (count == 0)
+    {
+      DEBUG(4, ("none\n"));
+    }
+  else
+    {
+      DEBUG(4, (" - count %d\n", count));
     }
+  
+  CVAL(countptr, 0) = count;
+
+  {
+    int len = PTR_DIFF(p, outbuf);
+    debug_browse_data(outbuf, len);
+  }
+  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+                     myname,theirname,0x0,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.
@@ -638,35 +535,32 @@ 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 domain_record *d; /* = find_domain(ip); */
+  struct subnet_record *d;
   struct work_record *work;
 
-  int count = CVAL(buf,0);
-  int token = SVAL(buf,1); /* sender's key index for the workgroup? */
-  int info  = SVAL(buf,3); /* XXXX don't know: some sort of info */
+  int    token = CVAL(buf,0); /* sender's key index for the workgroup */
+  uint32 info  = IVAL(buf,1); /* XXXX don't know: some sort of info */
   int name_type = dgram->dest_name.name_type;
 
   if (same_context(dgram)) return;
   
-  if (count <= 0) return;
-  
   if (name_type != 0x1b && name_type != 0x1d) {
     DEBUG(0,("backup request to wrong type %d from %s\n",
              name_type,inet_ntoa(ip)));
     return;
   }
   
-  for (d = domainlist; d; d = d->next)
+  for (d = subnetlist; d; d = d->next)
     {
       for (work = d->workgrouplist; work; work = work->next)
        {
          if (strequal(work->work_group, dgram->dest_name.name))
            {
-             DEBUG(2,("sending backup list to %s %s count=%d\n",
-                      namestr(&dgram->dest_name),inet_ntoa(ip),count));
+             DEBUG(2,("sending backup list to %s %s id=%x\n",
+                      namestr(&dgram->dest_name),inet_ntoa(ip),info));
   
              send_backup_list(work->work_group,&dgram->source_name,
-                              count,token,info,name_type,ip);
+                              token,info,name_type,ip);
              return;
            }
        } 
@@ -678,7 +572,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.
          
@@ -694,30 +588,34 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
   /* stop being a master but still deal with being a backup browser */
   if (state & 0x1)
     {
-      struct domain_record *d;
-      for (d = domainlist; d; d = d->next)
+      struct subnet_record *d;
+      for (d = subnetlist; d; d = d->next)
        {
          struct work_record *work;
          for (work = d->workgrouplist; work; work = work->next)
            {
              if (AM_MASTER(work))
                {
-                 become_nonmaster(d,work);
+                 become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
                }
            }
        }
     }
   
+  /* 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)
     {
-      struct domain_record *d;
-      for (d = domainlist; d; d = d->next)
+      struct subnet_record *d;
+      for (d = subnetlist; d; d = d->next)
        {
          struct work_record *work;
-         for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
+         for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
        }
-      add_my_domains();
+      add_my_subnets(lp_workgroup());
     }
   
   /* stop browsing altogether. i don't think this is a good idea! */
@@ -727,7 +625,6 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
     }
 }
 
-
 /*******************************************************************
   process a announcement request
 
@@ -739,7 +636,7 @@ static void process_announce_request(struct packet_struct *p,char *buf)
   struct dgram_packet *dgram = &p->packet.dgram;
   struct work_record *work;
   struct in_addr ip = dgram->header.source_ip;
-  struct domain_record *d = find_domain(ip);
+  struct subnet_record *d = find_subnet(ip);
   int token = CVAL(buf,0);
   char *name = buf+1;
   
@@ -750,12 +647,21 @@ 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 (!ip_equal(bcast_ip, d->bcast_ip)) 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;
@@ -764,88 +670,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 domain_record *d = find_domain(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,myip);  
- }
-
 /****************************************************************************
 depending on what announce has been made, we are only going to
 accept certain types of name announce. XXXX untested code
@@ -923,6 +747,7 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
     case ANN_DomainAnnouncement:
     case ANN_LocalMasterAnnouncement:
       {
+        debug_browse_data(buf, len);
        process_announce(p,command,buf+1);
        break;
       }
@@ -941,15 +766,17 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
       
     case ANN_GetBackupListReq:
       {
+        debug_browse_data(buf, len);
        process_send_backup_list(p,buf+1);
        break;
       }
       
     case ANN_GetBackupListResp:
-      {
-       process_rcv_backup_list(p, buf+1);
-       break;
-      }
+    {
+        debug_browse_data(buf, len);
+        process_rcv_backup_list(p, buf+1);
+        break;
+    }
       
     case ANN_ResetBrowserState:
       {
@@ -974,44 +801,3 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len)
 }
 
 
-/****************************************************************************
-process udp 138 datagrams
-****************************************************************************/
-void process_dgram(struct packet_struct *p)
-{
-  char *buf;
-  char *buf2;
-  int len;
-  struct dgram_packet *dgram = &p->packet.dgram;
-
-  if (dgram->header.msg_type != 0x10 &&
-      dgram->header.msg_type != 0x11 &&
-      dgram->header.msg_type != 0x12) {
-    /* don't process error packets etc yet */
-    return;
-  }
-
-  buf = &dgram->data[0];
-  buf -= 4; /* XXXX for the pseudo tcp length - 
-              someday I need to get rid of this */
-
-  if (CVAL(buf,smb_com) != SMBtrans) return;
-
-  len = SVAL(buf,smb_vwv11);
-  buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
-
-  DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
-          namestr(&dgram->source_name),namestr(&dgram->dest_name),
-          smb_buf(buf),CVAL(buf2,0),len));
-
-  if (len <= 0) return;
-
-   if (strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
-   {
-     process_browse_packet(p,buf2,len);
-   } else if (strequal(smb_buf(buf),"\\MAILSLOT\\NET\\NETLOGON")) {
-     process_logon_packet(p,buf2,len);
-   }
-}
-