Removed use of 'domain controller' parameter for browsing system
[kai/samba.git] / source / nameannounce.c
index 197548088bbba10a05023d31d1a99936eed309a2..b1d13ce7ac89bfbf9c727995164570d74b4b6a9e 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-1997
    
    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,7 +26,6 @@
 */
 
 #include "includes.h"
-#include "loadparm.h"
 
 #define TEST_CODE
 
@@ -36,23 +35,20 @@ extern BOOL CanRecurse;
 extern struct in_addr ipzero;
 
 extern pstring myname;
+extern fstring myworkgroup;
 
 extern int ClientDGRAM;
 extern int ClientNMB;
 
 /* this is our domain/workgroup/server database */
-extern struct domain_record *domainlist;
-
-/* machine comment for host announcements */
-extern  pstring ServerComment;
+extern struct subnet_record *subnetlist;
 
 extern int  updatecount;
 extern int  workgroup_count;
 
-/* what server type are we currently */
+extern struct in_addr wins_ip;
 
-#define MSBROWSE "\001\002__MSBROWSE__\002"
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+extern pstring scope;
 
 /****************************************************************************
   send a announce request to the local net
@@ -74,13 +70,18 @@ void announce_request(struct work_record *work, struct in_addr ip)
   CVAL(p,0) = ANN_AnnouncementRequest;
   p++;
 
-  CVAL(p,0) = work->token; /* flags?? XXXX probably a token*/
+  CVAL(p,0) = work->token; /* (local) unique workgroup token id */
   p++;
   StrnCpy(p,myname,16);
   strupper(p);
   p = skip_string(p,1);
   
-  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+  /* XXXX note: if we sent the announcement request to 0x1d instead
+     of 0x1e, then we could get the master browser to announce to
+     us instead of the members of the workgroup. wha-hey! */
+
+  send_mailslot_reply(False, BROWSE_MAILSLOT,ClientDGRAM,
+              outbuf,PTR_DIFF(p,outbuf),
                      myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
 }
 
@@ -107,115 +108,225 @@ void do_announce_request(char *info, char *to_name, int announce_type,
   strupper(p);
   p = skip_string(p,1);
   
-  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+  send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+              outbuf,PTR_DIFF(p,outbuf),
                      myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
 }
 
+
 /****************************************************************************
-  construct a host announcement unicast
+  find a server responsible for a workgroup, and sync browse lists
+  control ends up back here via response_name_query.
   **************************************************************************/
-void announce_backup(void)
+void sync_server(enum state_type state, char *serv_name, char *work_name, 
+                int name_type,
+                 struct subnet_record *d,
+                struct in_addr ip)
+{                     
+  /* with a domain master we can get the whole list (not local only list) */
+  BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK);
+
+  add_browser_entry(serv_name, name_type, work_name, 0, d, ip, local_only);
+
+  if (state == NAME_STATUS_DOM_SRV_CHK)
+  {
+    /* announce ourselves as a master browser to serv_name */
+    do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
+                         0x20, 0, ip);
+  }
+}
+
+
+/****************************************************************************
+  send a host announcement packet
+  **************************************************************************/
+void do_announce_host(int command,
+               char *from_name, int from_type, struct in_addr from_ip,
+               char *to_name  , int to_type  , struct in_addr to_ip,
+               time_t announce_interval,
+               char *server_name, int server_type, char *server_comment)
 {
-  static time_t lastrun = 0;
-  time_t t = time(NULL);
-  pstring outbuf;
-  char *p;
-  struct domain_record *d1;
-  int tok;
-  
-  if (!lastrun) lastrun = t;
-  if (t < lastrun + 1*60) return;
-  lastrun = t;
-  
-  for (tok = 0; tok <= workgroup_count; tok++)
-    {
-      for (d1 = domainlist; d1; d1 = d1->next)
-       {
-         struct work_record *work;
-         struct domain_record *d;
-         
-         /* search for unique workgroup: only the name matters */
-         for (work = d1->workgrouplist;
-              work && (tok != work->token);
-              work = work->next);
-         
-         if (!work) continue;
+       pstring outbuf;
+       char *p;
 
-         /* found one: announce it across all domains */
-         for (d = domainlist; d; d = d->next)
-           {
-             int type=0;
-
-             if (AM_DOMCTL(work)) {
-               type = 0x1b;
-             } else if (AM_MASTER(work)) {
-               type = 0x1d;
-             } else {
-               continue;
-             }
-             
-             DEBUG(2,("sending announce backup %s workgroup %s(%d)\n",
-                      inet_ntoa(d->bcast_ip),work->work_group,
-                      work->token));
-             
-             bzero(outbuf,sizeof(outbuf));
-             p = outbuf;
-             CVAL(p,0) = ANN_GetBackupListReq;
-             p++;
-             
-             CVAL(p,0) = 1; /* count? */
-             SIVAL(p,1,work->token); /* workgroup unique key index */
-             p += 5;
-             p++;
-             
-             send_mailslot_reply(BROWSE_MAILSLOT,
-                                 ClientDGRAM,outbuf,
-                                 PTR_DIFF(p,outbuf),
-                                 myname, work->work_group,
-                                 0x0,type,d->bcast_ip,
-                                 *iface_ip(d->bcast_ip));
-           }
+       bzero(outbuf,sizeof(outbuf));
+       p = outbuf+1;
+
+       /* command type */
+       CVAL(outbuf,0) = command;
+
+       /* announcement parameters */
+       CVAL(p,0) = updatecount;
+       SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
+
+       StrnCpy(p+5,server_name,16);
+       strupper(p+5);
+
+       CVAL(p,21) = MAJOR_VERSION; /* major version */
+       CVAL(p,22) = MINOR_VERSION; /* minor version */
+
+       SIVAL(p,23,server_type);
+       /* browse version: got from NT/AS 4.00  - Value defined in smb.h (JHT)*/
+       SSVAL(p,27,BROWSER_ELECTION_VERSION);
+       SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */
+
+       strcpy(p+31,server_comment);
+       p += 31;
+       p = skip_string(p,1);
+
+    debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+       /* send the announcement */
+       send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf,
+                                         PTR_DIFF(p,outbuf),
+                                         from_name, to_name,
+                                         from_type, to_type,
+                                         to_ip, from_ip);
+}
+
+
+/****************************************************************************
+announce all samba's server entries as 'gone'.
+****************************************************************************/
+void announce_my_servers_removed(void)
+{
+       struct subnet_record *d; 
+       for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+       {
+               struct work_record *work;
+               for (work = d->workgrouplist; work; work = work->next)
+               {
+                       struct server_record *s;
+                       for (s = work->serverlist; s; s = s->next)
+                       {
+                               if (!strequal(myname,s->serv.name)) continue;
+                               announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
+                       }
+               }
        }
-    }
 }
 
 
+/****************************************************************************
+  announce a server entry
+  ****************************************************************************/
+void announce_server(struct subnet_record *d, struct work_record *work,
+                    char *name, char *comment, time_t ttl, int server_type)
+{
+    /* domain type cannot have anything in it that might confuse
+       a client into thinking that the domain is in fact a server.
+       (SV_TYPE_SERVER_UNIX, for example)
+     */
+       uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
+       BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip);
+       
+       if (wins_iface && server_type != 0)
+       {
+               /* wins pseudo-ip interface */
+               if (!AM_MASTER(work))
+               {
+                       /* non-master announce by unicast to the domain 
+                          master */
+                       if (!lp_wins_support() && *lp_wins_server())
+                       {
+                               /* look up the domain master with the WINS server */
+                               queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,
+                                        NAME_QUERY_ANNOUNCE_HOST,
+                                        work->work_group,0x1b,0,ttl*1000,
+                                        server_type,name,comment,
+                                        False, False, ipzero, d->bcast_ip);
+                       }
+                       else
+                       {
+                               /* we are the WINS server, but not the domain master.  */
+                               /* XXXX we need to look up the domain master in our
+                                  WINS database list, and do_announce_host(). maybe
+                                  we could do a name query on the unsuspecting domain
+                                  master just to make sure it's awake. */
+                       }
+               }
+
+               /* XXXX any other kinds of announcements we need to consider here?
+                  e.g local master browsers... no. local master browsers do
+                  local master announcements to their domain master. they even
+                  use WINS lookup of the domain master if another wins server
+                  is being used! 
+                */
+       }
+       else
+       {
+               if (AM_MASTER(work))
+               {
+                       DEBUG(3,("sending local master announce to %s for %s(1e)\n",
+                                                       inet_ntoa(d->bcast_ip),work->work_group));
+
+                       do_announce_host(ANN_LocalMasterAnnouncement,
+                                                       name            , 0x00, d->myip,
+                                                       work->work_group, 0x1e, d->bcast_ip,
+                                                       ttl,
+                                                       name, server_type, comment);
+
+                       DEBUG(3,("sending domain announce to %s for %s\n",
+                                                       inet_ntoa(d->bcast_ip),work->work_group));
+
+                       /* XXXX should we do a domain-announce-kill? */
+                       if (server_type != 0)
+                       {
+                               do_announce_host(ANN_DomainAnnouncement,
+                                                       name    , 0x00, d->myip,
+                                                       MSBROWSE, 0x01, d->bcast_ip,
+                                                       ttl,
+                                                       work->work_group, server_type ? domain_type : 0,
+                                                       name);
+                       }
+               }
+               else
+               {
+                       DEBUG(3,("sending host announce to %s for %s(1d)\n",
+                                                       inet_ntoa(d->bcast_ip),work->work_group));
+
+                       do_announce_host(ANN_HostAnnouncement,
+                                                       name            , 0x00, d->myip,
+                                                       work->work_group, 0x1d, d->bcast_ip,
+                                                       ttl,
+                                                       name, server_type, comment);
+               }
+       }
+}
+
 /****************************************************************************
   construct a host announcement unicast
   **************************************************************************/
-void announce_host(void)
+void announce_host(time_t t)
 {
-  time_t t = time(NULL);
-  pstring outbuf;
-  char *p;
-  char *namep;
-  char *stypep;
-  char *commentp;
+  struct subnet_record *d;
   pstring comment;
   char *my_name;
-  struct domain_record *d;
 
-  StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43);
+  StrnCpy(comment, lp_serverstring(), 43);
 
   my_name = *myname ? myname : "NoName";
 
-  for (d = domainlist; d; d = d->next)
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
     {
       struct work_record *work;
       
-      if (!ismybcast(d->bcast_ip))
-       continue;
-
       for (work = d->workgrouplist; work; work = work->next)
        {
          uint32 stype = work->ServerType;
          struct server_record *s;
          BOOL announce = False;
          
+         /* must work on the code that does announcements at up to
+            30 seconds later if a master browser sends us a request
+            announce.
+            */
+
          if (work->needannounce) {
            /* drop back to a max 3 minute announce - this is to prevent a
               single lost packet from stuffing things up for too long */
-           work->announce_interval = MIN(work->announce_interval,3*60);
+           work->announce_interval = MIN(work->announce_interval,
+                                         CHECK_TIME_MIN_HOST_ANNCE*60);
            work->lastannounce_time = t - (work->announce_interval+1);
          }
          
@@ -224,17 +335,11 @@ void announce_host(void)
              (t - work->lastannounce_time) < work->announce_interval)
            continue;
          
-         if (work->announce_interval < 12*60) 
+         if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) 
            work->announce_interval += 60;
          
          work->lastannounce_time = t;
-
-         if (!ismybcast(d->bcast_ip)) {
-           stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER |
-                      SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER |
-                      SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_MEMBER);
-         }
-
+         
          for (s = work->serverlist; s; s = s->next) {
            if (strequal(myname, s->serv.name)) { 
              announce = True; 
@@ -242,77 +347,10 @@ void announce_host(void)
            }
          }
          
-         if (announce)
-           {
-             bzero(outbuf,sizeof(outbuf));
-             p = outbuf+1;
-             
-             CVAL(p,0) = updatecount;
-             /* ms - despite the spec */
-             SIVAL(p,1,work->announce_interval*1000); 
-             namep = p+5;
-             StrnCpy(namep,my_name,16);
-             strupper(namep);
-             CVAL(p,21) = 2; /* major version */
-             CVAL(p,22) = 2; /* minor version */
-             stypep = p+23;
-             SIVAL(p,23,stype);
-             SSVAL(p,27,0xaa55); /* browse signature */
-             SSVAL(p,29,1); /* browse version */
-             commentp = p+31;
-             strcpy(commentp,comment);
-             p = p+31;
-             p = skip_string(p,1);
-             
-             if (ismybcast(d->bcast_ip))
-               {
-                 if (AM_MASTER(work))
-                   {
-                     SIVAL(stypep,0,work->ServerType);
-                     
-                     DEBUG(2,("sending local master announce to %s for %s\n",
-                              inet_ntoa(d->bcast_ip),work->work_group));
-
-                     CVAL(outbuf,0) = ANN_LocalMasterAnnouncement;
-                     
-                     send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
-                                         PTR_DIFF(p,outbuf),
-                                         my_name,work->work_group,0,
-                                         0x1e,d->bcast_ip,
-                                         *iface_ip(d->bcast_ip));
-                     
-                     DEBUG(2,("sending domain announce to %s for %s\n",
-                              inet_ntoa(d->bcast_ip),work->work_group));
-
-                     CVAL(outbuf,0) = ANN_DomainAnnouncement;
-                     
-                     StrnCpy(namep,work->work_group,15);
-                     strupper(namep);
-                     StrnCpy(commentp,myname,15);
-                     strupper(commentp);
-                     
-                     SIVAL(stypep,0,(unsigned)0x80000000);
-                     p = commentp + strlen(commentp) + 1;
-                     
-                     send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
-                                         PTR_DIFF(p,outbuf),
-                                         my_name,MSBROWSE,0,0x01,d->bcast_ip,
-                                         *iface_ip(d->bcast_ip));
-                   }
-                 else
-                   {
-                     DEBUG(2,("sending host announce to %s for %s\n",
-                              inet_ntoa(d->bcast_ip),work->work_group));
-
-                     CVAL(outbuf,0) = ANN_HostAnnouncement;
-                     
-                     send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
-                                         PTR_DIFF(p,outbuf),
-                                         my_name,work->work_group,0,0x1d,
-                                         d->bcast_ip,*iface_ip(d->bcast_ip));
-                   }
-               }
-           }
+         if (announce) {
+           announce_server(d,work,my_name,comment,
+                           work->announce_interval,stype);
+         }
          
          if (work->needannounce)
            {
@@ -324,34 +362,50 @@ void announce_host(void)
     }
 }
 
+/* Announce timer. Moved into global static so it can be reset
+   when a machine becomes a master browser. */
+static time_t announce_timer_last=0;
 
 /****************************************************************************
-  announce myself as a master to all other primary domain conrollers.
+ Reset the announce_timer so that a master browser announce will be done
+ immediately.
+ ****************************************************************************/
+
+void reset_announce_timer()
+{
+  announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
+}
+
+/****************************************************************************
+  announce myself as a master to all other domain master browsers.
 
-  BIG NOTE: this code will remain untested until some kind soul that has access
-  to a couple of windows NT advanced servers runs this version of nmbd for at
-  least 15 minutes.
-  
   this actually gets done in search_and_sync_workgroups() via the
-  MASTER_SERVER_CHECK command, if there is a response from the
+  NAME_QUERY_DOM_SRV_CHK command, if there is a response from the
   name query initiated here.  see response_name_query()
   **************************************************************************/
-void announce_master(void)
+void announce_master(time_t t)
 {
-  struct domain_record *d;
-  static time_t last=0;
-  time_t t = time(NULL);
+  struct subnet_record *d;
+  struct work_record *work;
   BOOL am_master = False; /* are we a master of some sort? :-) */
 
-#ifdef TEST_CODE
-  if (last && (t-last < 2*60)) return;
-#else
-  if (last && (t-last < 15*60)) return; 
-#endif
+  if (!announce_timer_last) announce_timer_last = t;
+  if (t-announce_timer_last < CHECK_TIME_MST_ANNOUNCE * 60)
+    {
+      DEBUG(10,("announce_master: t (%d) - last(%d) < %d\n",
+                 t, announce_timer_last, CHECK_TIME_MST_ANNOUNCE * 60 ));
+      return;
+    }
+
+  if(wins_subnet == NULL)
+    {
+      DEBUG(10,("announce_master: no wins subnet, ignoring.\n"));
+      return;
+    }
 
-  last = t;
+  announce_timer_last = t;
 
-  for (d = domainlist; d; d = d->next)
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
     {
       struct work_record *work;
       for (work = d->workgrouplist; work; work = work->next)
@@ -359,86 +413,151 @@ void announce_master(void)
          if (AM_MASTER(work))
            {
              am_master = True;
+              DEBUG(4,( "announce_master: am_master = %d for \
+workgroup %s\n", am_master, work->work_group));
            }
        }
     }
-  
   if (!am_master) return; /* only proceed if we are a master browser */
   
-  for (d = domainlist; d; d = d->next)
+  /* Note that we don't do this if we are domain master browser
+     and that we *only* do this on the WINS subnet. */
+
+  /* Try and find our workgroup on the WINS subnet */
+  work = find_workgroupstruct(wins_subnet, myworkgroup, False);
+
+  if (work)
     {
-      struct work_record *work;
-      for (work = d->workgrouplist; work; work = work->next)
-       {
-         struct server_record *s;
-         for (s = work->serverlist; s; s = s->next)
-           {
-             if (strequal(s->serv.name, myname)) continue;
-             
-             /* all PDCs (which should also be master browsers) */
-             if (s->serv.type & SV_TYPE_DOMAIN_CTRL)
-               {
-                 /* check the existence of a pdc for this workgroup, and if
-                    one exists at the specified ip, sync with it and announce
-                    ourselves as a master browser to it */
-                 
-                 if (!*lp_domain_controller() ||
-                     !strequal(lp_domain_controller(), s->serv.name))
-                   {
-                     if (!lp_wins_support() && *lp_wins_server())
-                       {
-                         struct in_addr ip;
-                         ip = ipzero;
-                         
-                         queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,
-                                                MASTER_SERVER_CHECK,
-                                                work->work_group,0x1b,0,
-                                                False, False, ip);
-                       }
-                     else
-                       {
-                         struct domain_record *d2;
-                         for (d2 = domainlist; d2; d2 = d2->next)
-                           {
-                             queue_netbios_packet(ClientNMB,NMB_QUERY,
-                                                  MASTER_SERVER_CHECK,
-                                                  work->work_group,0x1b,0,
-                                                  True, False, d2->bcast_ip);
-                           }
-                       }
-                   }
-               }
-           }
-         
-         /* now do primary domain controller - the one that's not
-            necessarily in our browse lists, although it ought to be
-            this pdc is the one that we get TOLD about through smb.conf.
-            basically, if it's on a subnet that we know about, it may end
-            up in our browse lists (which is why it's explicitly excluded
-            in the code above) */
-         
-         if (*lp_domain_controller())
-           {
-             struct in_addr ip;
-             BOOL bcast = False;
-             
-             ip = *interpret_addr2(lp_domain_controller());
-             
-             if (zero_ip(ip)) {
-               ip = *iface_bcast(d->bcast_ip);
-               bcast = True;
-             }
-
-             DEBUG(2, ("Searching for PDC %s at %s\n",
-                       lp_domain_controller(), inet_ntoa(ip)));
-             
-             /* check the existence of a pdc for this workgroup, and if
-                one exists at the specified ip, sync with it and announce
-                ourselves as a master browser to it */
-             queue_netbios_pkt_wins(ClientNMB, NMB_QUERY,MASTER_SERVER_CHECK,
-                                    work->work_group,0x1b, 0,
-                                    bcast, False, ip);
-           }
-       }
+      char *name;
+      int   type;
+
+#if 0 /* I don't think this option should be used for this purpose. 
+         JRA.
+       */
+      if (*lp_domain_controller())
+        {
+          /* the domain controller option is used to manually specify
+             the domain master browser to sync with
+           */
+
+          /* XXXX i'm not sure we should be using the domain controller
+             option for this purpose.
+           */
+
+          name = lp_domain_controller();
+          type = 0x20;
+        }
+      else
+#endif /* REMOVE SUSPECT CODE. */
+        {
+          /* assume that the domain master browser we want to sync
+             with is our own domain.
+           */
+          name = work->work_group;
+          type = 0x1b;
+        }
+
+      /* check the existence of a dmb for this workgroup, and if
+         one exists at the specified ip, sync with it and announce
+         ourselves as a master browser to it
+       */
+
+      if (!lp_wins_support() && *lp_wins_server() )
+        {
+          DEBUG(4, ("Local Announce: find %s<%02x> from WINS server %s\n",
+                     name, type, lp_wins_server()));
+
+          queue_netbios_pkt_wins(ClientNMB,
+                    NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
+                    name, type, 0,0,0,
+                    work->work_group,NULL,
+                    False, False, ipzero, ipzero);
+        }
+      else if(lp_wins_support()) 
+        {
+           /* We are the WINS server - query ourselves for the dmb name. */
+
+           struct nmb_name netb_name;
+           struct subnet_record *d = 0;
+           struct name_record *nr = 0;
+           make_nmb_name(&netb_name, name, type, scope);
+
+           if ((nr = find_name_search(&d, &netb_name, FIND_WINS, ipzero)) == 0)
+             {
+               DEBUG(0, ("announce_master: unable to find domain master browser for workgroup %s \
+in our own WINS database.\n", work->work_group));
+               return;
+             }
+
+           /* Check that this isn't one of our addresses (ie. we are not domain master
+              ourselves) */
+           if(ismyip(nr->ip_flgs[0].ip) || ip_equal(nr->ip_flgs[0].ip, ipzero))
+             {
+               DEBUG(4, ("announce_master: domain master ip found (%s) for workgroup %s \
+is one of our interfaces.\n", work->work_group, inet_ntoa(nr->ip_flgs[0].ip) ));
+               return;
+             }
+
+           /* Issue a NAME_STATUS_DOM_SRV_CHK immediately - short circuit the
+              NAME_QUERY_DOM_SRV_CHK which is done only if we are talking to a 
+              remote WINS server. */
+
+           DEBUG(4, ("announce_master: doing name status for %s<%02x> to domain master ip %s \
+for workgroup %s\n", name, type, inet_ntoa(nr->ip_flgs[0].ip), work->work_group ));
+
+           queue_netbios_packet(wins_subnet, ClientNMB,
+                    NMB_QUERY,NAME_STATUS_DOM_SRV_CHK,
+                    name, type, 0,0,0,
+                    work->work_group,NULL,
+                    False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip);
+         }
+
     }
 }
+
+/****************************************************************************
+  do all the "remote" announcements. These are used to put ourselves
+  on a remote browse list. They are done blind, no checking is done to
+  see if there is actually a browse master at the other end.
+  **************************************************************************/
+void announce_remote(time_t t)
+{
+  char *s,*ptr;
+  static time_t last_time = 0;
+  pstring s2;
+  struct in_addr addr;
+  char *comment,*workgroup;
+  int stype = DFLT_SERVER_TYPE;
+
+  if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL)
+    return;
+
+  last_time = t;
+
+  s = lp_remote_announce();
+  if (!*s) return;
+
+  comment = lp_serverstring();
+  workgroup = myworkgroup;
+
+  for (ptr=s; next_token(&ptr,s2,NULL); ) {
+    /* the entries are of the form a.b.c.d/WORKGROUP with 
+       WORKGROUP being optional */
+    char *wgroup;
+
+    wgroup = strchr(s2,'/');
+    if (wgroup) *wgroup++ = 0;
+    if (!wgroup || !*wgroup)
+      wgroup = workgroup;
+
+    addr = *interpret_addr2(s2);
+    
+    do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr),
+                    wgroup,0x1e,addr,
+                    REMOTE_ANNOUNCE_INTERVAL,
+                    myname,stype,comment);    
+  }
+
+}