updated comments in announce_server() to indicate that future work needs
[kai/samba.git] / source3 / nameannounce.c
index f0de4d0a27f6257433a9154e2c72c4e2e095fa25..e619ef1c4b624a382e7b865a82cc33fe76e82dd3 100644 (file)
 */
 
 #include "includes.h"
-#include "loadparm.h"
 
 #define TEST_CODE
 
 extern int DEBUGLEVEL;
 extern BOOL CanRecurse;
 
-extern struct in_addr myip;
-extern struct in_addr bcast_ip;
-extern struct in_addr Netmask;
 extern struct in_addr ipzero;
 
 extern pstring myname;
@@ -44,7 +40,7 @@ extern int ClientDGRAM;
 extern int ClientNMB;
 
 /* 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;
@@ -52,14 +48,7 @@ extern  pstring ServerComment;
 extern int  updatecount;
 extern int  workgroup_count;
 
-/* what server type are we currently */
-
-#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)
-
-#define MSBROWSE "\001\002__MSBROWSE__\002"
-#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+extern struct in_addr ipgrp;
 
 /****************************************************************************
   send a announce request to the local net
@@ -73,254 +62,411 @@ void announce_request(struct work_record *work, struct in_addr ip)
 
   work->needannounce = True;
 
-  DEBUG(2,("Sending announce request to %s for workgroup %s\n",
+  DEBUG(2,("sending announce request to %s for workgroup %s\n",
           inet_ntoa(ip),work->work_group));
 
   bzero(outbuf,sizeof(outbuf));
   p = outbuf;
-  CVAL(p,0) = 2; /* announce request */
+  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);
   
+  /* 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(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
-                     myname,work->work_group,0x20,0x0,ip,myip);
+                     myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
 }
 
 
 /****************************************************************************
   request an announcement
   **************************************************************************/
-void do_announce_request(char *info, char *to_name, int announce_type, int from,
+void do_announce_request(char *info, char *to_name, int announce_type, 
+                        int from,
                         int to, struct in_addr dest_ip)
 {
-       pstring outbuf;
-       char *p;
-
-       bzero(outbuf,sizeof(outbuf));
-       p = outbuf;
-       CVAL(p,0) = announce_type; /* announce request */
-       p++;
-
-       DEBUG(2,("Sending announce type %d: info %s to %s - server %s(%x)\n",
-                 announce_type, info, inet_ntoa(dest_ip),to_name,to));
+  pstring outbuf;
+  char *p;
+  
+  bzero(outbuf,sizeof(outbuf));
+  p = outbuf;
+  CVAL(p,0) = announce_type; 
+  p++;
+  
+  DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n",
+          announce_type, info, inet_ntoa(dest_ip),to_name,to));
+  
+  StrnCpy(p,info,16);
+  strupper(p);
+  p = skip_string(p,1);
+  
+  send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+                     myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
+}
 
-       StrnCpy(p,info,16);
-       strupper(p);
-       p = skip_string(p,1);
 
-       send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
-                myname,to_name,from,to,dest_ip,myip);
+/****************************************************************************
+  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)
+{                     
+  /* 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, 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);
+  }
 }
 
+
 /****************************************************************************
   construct a host announcement unicast
+
+  this function should not be used heavily, and only when we are _not_
+  a master browser and _not_ a primary domain controller.
+
   **************************************************************************/
 void announce_backup(void)
 {
-       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;
+  static time_t lastrun = 0;
+  time_t t = time(NULL);
+  pstring outbuf;
+  char *p;
+  struct subnet_record *d1;
+  int tok;
+  static uint32 id_count = 0;
+  
+  if (!lastrun) lastrun = t;
+#if 1
+  if (t < lastrun + 1 * 60)
+#else
+  if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60)
+#endif
+       return;
+  lastrun = t;
+  
+  DEBUG(4,("checking backups...\n"));
 
-       for (tok = 0; tok <= workgroup_count; tok++)
+  for (tok = 0; tok <= workgroup_count; tok++)
+    {
+      for (d1 = subnetlist; d1; d1 = d1->next)
        {
-               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)
-                       {
-                               /* found one: announce it across all domains */
-                               for (d = domainlist; d; d = d->next)
-                               {
-                                       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) = 9; /* backup list response */
-                                       p++;
-
-                                       CVAL(p,0) = 1; /* count? */
-                                       SIVAL(p,1,work->token); /* workgroup unique key index */
-                                       p += 5;
-                                       p++;
-
-                                       if (AM_DOMCTL(work))
-                                       {
-                                               send_mailslot_reply(BROWSE_MAILSLOT,
-                                                          ClientDGRAM,outbuf,
-                                                          PTR_DIFF(p,outbuf),
-                                                          myname, work->work_group,
-                                                          0x0,0x1b,d->bcast_ip,myip);
-                                       }
-                                       else if (AM_MASTER(work))
-                                       {
-                                               send_mailslot_reply(BROWSE_MAILSLOT,
-                                                          ClientDGRAM,outbuf,
-                                                          PTR_DIFF(p,outbuf),
-                                                          myname, work->work_group,
-                                                          0x0,0x1d,d->bcast_ip,myip);
-                                       }
-                               }
-                       }
-               }
+         struct work_record *work;
+         struct subnet_record *d;
+         
+         /* search for unique workgroup: only the name matters */
+         for (work = d1->workgrouplist;
+              work && (tok != work->token);
+              work = work->next);
+         
+         if (!work) continue;
+
+      if (AM_MASTER(work) && AM_DOMCTL(work)) continue;
+
+         /* found one: announce it across all domains */
+         for (d = subnetlist; d; d = d->next)
+           {
+             
+             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;
+             CVAL(p,1) = work->token; /* workgroup unique key index */
+             SIVAL(p,2,++id_count); /* unique count. not that we use it! */
+
+             p += 6;
+             
+          debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+             if (!AM_DOMCTL(work))
+          {
+            /* only ask for a list of backup domain controllers
+               if we are not a domain controller ourselves */
+                       
+               send_mailslot_reply(BROWSE_MAILSLOT,
+                                 ClientDGRAM,outbuf,
+                                 PTR_DIFF(p,outbuf),
+                                 myname, work->work_group,
+                                 0x0,0x1b,d->bcast_ip,
+                                 *iface_ip(d->bcast_ip));
+          }
+
+          debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+             if (!AM_MASTER(work))
+          {
+            /* only ask for a list of master browsers if we
+               are not a master browser ourselves */
+
+               send_mailslot_reply(BROWSE_MAILSLOT,
+                                 ClientDGRAM,outbuf,
+                                 PTR_DIFF(p,outbuf),
+                                 myname, work->work_group,
+                                 0x0,0x1d,d->bcast_ip,
+                                 *iface_ip(d->bcast_ip));
+          }
+           }
        }
+    }
 }
 
 
 /****************************************************************************
-  construct a host announcement unicast
+  send a host announcement packet
   **************************************************************************/
-void announce_host(void)
+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)
 {
-       time_t t = time(NULL);
        pstring outbuf;
        char *p;
-       char *namep;
-       char *stypep;
-       char *commentp;
-       pstring comment;
-       char *my_name;
-       struct domain_record *d;
 
-       StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43);
+       bzero(outbuf,sizeof(outbuf));
+       p = outbuf+1;
 
-       my_name = *myname ? myname : "NoName";
+       /* command type */
+       CVAL(outbuf,0) = command;
 
-       for (d = domainlist; d; d = d->next)
-       {
-               struct work_record *work;
+       /* announcement parameters */
+       CVAL(p,0) = updatecount;
+       SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
 
-               if (!ip_equal(bcast_ip,d->bcast_ip))
-               {
-                       continue;
-               }
+       StrnCpy(p+5,server_name,16);
+       strupper(p+5);
+
+       CVAL(p,21) = 0x02; /* major version */
+       CVAL(p,22) = 0x02; /* minor version */
+
+       SIVAL(p,23,server_type);
+       SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */
+       SSVAL(p,29,0xaa55); /* 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(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
+                                         PTR_DIFF(p,outbuf),
+                                         from_name, to_name,
+                                         from_type, to_type,
+                                         to_ip, from_ip);
+}
 
+
+/****************************************************************************
+  remove all samba's server entries
+  ****************************************************************************/
+void remove_my_servers(void)
+{
+       struct subnet_record *d; 
+       for (d = subnetlist; d; d = d->next)
+       {
+               struct work_record *work;
                for (work = d->workgrouplist; work; work = work->next)
                {
-                       uint32 stype = work->ServerType;
                        struct server_record *s;
-                       BOOL announce = False;
-
-                       if (work->needannounce)
+                       for (s = work->serverlist; s; s = s->next)
                        {
-                               /* 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->lastannounce_time = t - (work->announce_interval+1);
+                               if (!strequal(myname,s->serv.name)) continue;
+                               announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
                        }
+               }
+       }
+}
+
 
-                       /* announce every minute at first then progress to every 12 mins */
-                       if (work->lastannounce_time && 
-                          (t - work->lastannounce_time) < work->announce_interval)
+/****************************************************************************
+  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)
+{
+       uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_SERVER_UNIX;
+       BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
+       
+       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(d,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
                        {
-                               continue;
+                               /* 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. */
                        }
+               }
 
-                       if (work->announce_interval < 12*60) work->announce_interval += 60;
+               if (AM_DOMCTL(work))
+               {
+                       /* XXXX announce to backup domain masters? */
+               }
 
-                       work->lastannounce_time = t;
+               /* 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));
 
-                       DEBUG(2,("Sending announcement to subnet %s for workgroup %s\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*1000,
+                                                       name, server_type, comment);
 
-                       if (!ip_equal(bcast_ip,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);
-                       }
+                       DEBUG(3,("sending domain announce to %s for %s\n",
+                                                       inet_ntoa(d->bcast_ip),work->work_group));
 
-                       for (s = work->serverlist; s; s = s->next)
-                       {
-                               if (strequal(myname, s->serv.name)) { announce = True; break; }
-                       }
-
-                       if (announce)
+                       /* XXXX should we do a domain-announce-kill? */
+                       if (server_type != 0)
                        {
-                               bzero(outbuf,sizeof(outbuf));
-                               p = outbuf+1;
-
-                               CVAL(p,0) = updatecount;
-                               SIVAL(p,1,work->announce_interval*1000); /* ms - despite the spec */
-                               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 (ip_equal(bcast_ip,d->bcast_ip))
+                               if (AM_DOMCTL(work))
                                {
-                                       if (AM_MASTER(work))
-                                       {
-                                               SIVAL(stypep,0,work->ServerType);
-
-                                               CVAL(outbuf,0) = 15; /* local member announce */
-
-                                               send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
-                                                          PTR_DIFF(p,outbuf),
-                                                          my_name,work->work_group,0,0x1e,d->bcast_ip,myip);
-
-                                               CVAL(outbuf,0) = 12; /* domain announce */
-
-                                               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,myip);
-                                       }
-                                       else
-                                       {
-                                               CVAL(outbuf,0) = 1; /* host announce */
-
-                                               send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
-                                                        PTR_DIFF(p,outbuf),
-                                                        my_name,work->work_group,0,0x1d,d->bcast_ip,myip);
-                                       }
+                                       domain_type |= SV_TYPE_DOMAIN_CTRL;
                                }
+                               do_announce_host(ANN_DomainAnnouncement,
+                                                       name    , 0x00, d->myip,
+                                                       MSBROWSE, 0x01, d->bcast_ip,
+                                                       ttl*1000,
+                                                       work->work_group, server_type ? domain_type : 0,
+                                                       name);
                        }
-
-                       if (work->needannounce)
-                       {
-                               work->needannounce = False;
-                               break;
-                               /* sorry: can't do too many announces. do some more later */
-                       }
                }
+               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*1000,
+                                                       name, server_type, comment);
+               }
+       }
+}
+
+/****************************************************************************
+  construct a host announcement unicast
+  **************************************************************************/
+void announce_host(void)
+{
+  time_t t = time(NULL);
+  struct subnet_record *d;
+  pstring comment;
+  char *my_name;
+
+  StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43);
+
+  my_name = *myname ? myname : "NoName";
+
+  for (d = subnetlist; d; d = d->next)
+    {
+      struct work_record *work;
+      
+      if (ip_equal(d->bcast_ip, ipgrp)) 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,
+                                               CHECK_TIME_MIN_HOST_ANNCE*60);
+           work->lastannounce_time = t - (work->announce_interval+1);
+         }
+         
+         /* announce every minute at first then progress to every 12 mins */
+         if (work->lastannounce_time && 
+             (t - work->lastannounce_time) < work->announce_interval)
+           continue;
+         
+         if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) 
+           work->announce_interval += 60;
+         
+         work->lastannounce_time = t;
+
+         /*
+         if (!d->my_interface) {
+           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; 
+             break; 
+           }
+         }
+         
+         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 */
+         }
        }
+  }
 }
 
 
@@ -332,113 +478,107 @@ void announce_host(void)
   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)
 {
-       struct domain_record *d;
-       static time_t last=0;
-       time_t t = time(NULL);
-       BOOL am_master = False; /* are we a master of some sort? :-) */
+  struct subnet_record *d;
+  static time_t last=0;
+  time_t t = time(NULL);
+  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 (!last) last = t;
+  if (t-last < CHECK_TIME_MST_ANNOUNCE * 60)
+       return;
 
-       last = t;
+  last = t;
 
-       for (d = domainlist; d; d = d->next)
+  for (d = subnetlist; d; d = d->next)
+    {
+      struct work_record *work;
+      for (work = d->workgrouplist; work; work = work->next)
        {
-               struct work_record *work;
-               for (work = d->workgrouplist; work; work = work->next)
-               {
-                       if (AM_MASTER(work))
-                       {
-                               am_master = True;
-                       }
-               }
+         if (AM_MASTER(work))
+           {
+             am_master = True;
+           }
        }
-
-       if (!am_master) return; /* only proceed if we are a master browser */
-
-       for (d = domainlist; d; d = d->next)
+    }
+  
+  if (!am_master) return; /* only proceed if we are a master browser */
+  
+  for (d = subnetlist; d; d = d->next)
+    {
+      struct work_record *work;
+      for (work = d->workgrouplist; work; work = work->next)
        {
-               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 DOMs (which should also be master browsers) */
+             if (s->serv.type & SV_TYPE_DOMAIN_CTRL)
                {
-                       struct server_record *s;
-                       for (s = work->serverlist; s; s = s->next)
+                 /* 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())
                        {
-                               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);
-                                                       }
-                                               }
-                                       }
-                               }
+                         queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
+                                                NAME_QUERY_DOM_SRV_CHK,
+                                                work->work_group,0x1b,0,0,0,NULL,NULL,
+                                                False, False, ipzero, ipzero);
                        }
-
-                       /* 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())
+                     else
                        {
-                               struct in_addr ip;
-                               BOOL bcast = False;
-
-                               ip = *interpret_addr2(lp_domain_controller());
-
-                               if (zero_ip(ip))
-                               {
-                                       ip = 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);
+                         struct subnet_record *d2;
+                         for (d2 = subnetlist; d2; d2 = d2->next)
+                           {
+                             queue_netbios_packet(d,ClientNMB,NMB_QUERY,
+                                                  NAME_QUERY_DOM_SRV_CHK,
+                                                  work->work_group,0x1b,0,0,0,NULL,NULL,
+                                                  True, False, d2->bcast_ip, 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 = d->bcast_ip;
+               bcast = True;
+             }
+
+             DEBUG(2, ("Searching for DOM %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(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
+                                    work->work_group,0x1b,0,0,0,NULL,NULL,
+                                    bcast, False, ip, ip);
+           }
        }
+    }
 }