2 more consultants.
[kai/samba.git] / source3 / nameelect.c
index e1f36ae2503311bc8add9b489f0a3d3f04aeeeb4..2ec3f505f87177ef14966c94fbe335c280171a4a 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-1996
+   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
@@ -40,8 +40,9 @@ extern int DEBUGLEVEL;
 extern pstring scope;
 
 extern pstring myname;
+extern fstring myworkgroup;
 extern struct in_addr ipzero;
-extern struct in_addr ipgrp;
+extern struct in_addr wins_ip;
 
 /* here are my election parameters */
 
@@ -57,55 +58,59 @@ extern uint16 nb_type; /* samba's NetBIOS name type */
   ******************************************************************/
 void check_master_browser(time_t t)
 {
-       static time_t lastrun=0;
-       struct subnet_record *d;
-
-       if (!lastrun) lastrun = t;
-       if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
+  static time_t lastrun=0;
+  struct subnet_record *d;
 
-       lastrun = t;
+  if (!lastrun) lastrun = t;
+  if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
 
-       dump_workgroups();
+  lastrun = t;
 
-       for (d = subnetlist; d; d = d->next)
-       {
-               struct work_record *work;
+  dump_workgroups();
 
-               for (work = d->workgrouplist; work; work = work->next)
-               {
-                       if (!AM_MASTER(work))
-                       {
-                               if (lp_preferred_master())
-                               {
-                                       /* preferred master - not a master browser.  force
-                                          becoming a master browser, hence the log message.
-                                        */
-
-                                       DEBUG(0,("%s preferred master for %s %s - force election\n",
-                                                 timestring(), work->work_group,
-                                                 inet_ntoa(d->bcast_ip)));
+  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+  {
+    struct work_record *work;
 
-                                       browser_gone(work->work_group, d->bcast_ip);
-                               }
-                               else
-                               {
-                                       /* if we are not the browse master of a workgroup,
-                                          and we can't find a browser on the subnet, do
-                                          something about it.
-                                        */
-
-                                       queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
-                                                    work->work_group,0x1d,0,0,0,NULL,NULL,
-                                                    True,False,d->bcast_ip,d->bcast_ip);
-                               }
-                       }
-               }
-       }
+    for (work = d->workgrouplist; work; work = work->next)
+    {
+      if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work))
+      {
+        if (lp_local_master() && lp_preferred_master())
+        {
+          /* potential master browser - not a master browser.  force
+             becoming a master browser, hence the log message.
+           */
+
+          DEBUG(2,("%s potential master for %s %s - force election\n",
+                   timestring(), work->work_group,
+                   inet_ntoa(d->bcast_ip)));
+
+          browser_gone(work->work_group, d->bcast_ip);
+        }
+        else
+        {
+          /* if we are not the browse master of a workgroup,
+             and we can't find a browser on the subnet, do
+             something about it.
+           */
+
+          queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
+                    work->work_group,0x1d,0,0,0,NULL,NULL,
+                    True,False,d->bcast_ip,d->bcast_ip);
+        }
+      }
+    }
+  }
 }
 
 
 /*******************************************************************
-  what to do if a master browser DOESN't exist
+  what to do if a master browser DOESN't exist.
+
+  option 1: force an election, and participate in it
+  option 2: force an election, and let everyone else participate.
+
   ******************************************************************/
 void browser_gone(char *work_name, struct in_addr ip)
 {
@@ -116,27 +121,40 @@ void browser_gone(char *work_name, struct in_addr ip)
   if (!work || !d) return;
 
   /* don't do election stuff on the WINS subnet */
-  if (ip_equal(d->bcast_ip,ipgrp)) 
+  if (ip_equal(d->bcast_ip,wins_ip)) 
     return;
 
-  if (strequal(work->work_group, lp_workgroup()))
+  if (strequal(work->work_group, myworkgroup))
   {
 
+    if (lp_local_master())
+    {
+      /* we have discovered that there is no local master
+         browser, and we are configured to initiate
+         an election under exactly such circumstances.
+       */
       DEBUG(2,("Forcing election on %s %s\n",
               work->work_group,inet_ntoa(d->bcast_ip)));
 
       /* we can attempt to become master browser */
       work->needelection = True;
-  }
-  else
-  {
-     /* local interfaces: force an election */
-    send_election(d, work->work_group, 0, 0, myname);
-
-     /* only removes workgroup completely on a local interface 
-        persistent lmhosts entries on a local interface _will_ be removed).
-      */
-     remove_workgroup(d, work,True);
+    }
+    else
+    {
+      /* we need to force an election, because we are configured
+         not to _become_ the local master, but we still _need_ one,
+         having detected that one doesn't exist.
+       */
+
+      /* local interfaces: force an election */
+      send_election(d, work->work_group, 0, 0, myname);
+
+      /* only removes workgroup completely on a local interface 
+         persistent lmhosts entries on a local interface _will_ be removed).
+       */
+      remove_workgroup(d, work,True);
+      add_workgroup_to_subnet(d, work->work_group);
+    }
   }
 }
 
@@ -199,18 +217,15 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
     {
       remove_type_local |= SV_TYPE_MASTER_BROWSER;
     }
-    if (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
-         name_type == 0x1d)
+    if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d)
     {
       remove_type_local |= SV_TYPE_MASTER_BROWSER;
     }
-    if (AM_DOMMST(work) && strequal(name, lp_workgroup()) == 0 &&
-         name_type == 0x1b)
+    if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b)
     {
       remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
     }
-    if (AM_DOMMEM(work) && strequal(name, lp_workgroup()) == 0 &&
-         name_type == 0x1c)
+    if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c)
     {
       remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
     }
@@ -231,45 +246,48 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
 void name_register_work(struct subnet_record *d, char *name, int name_type,
                                int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
 {
-       enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
+  enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
                                  SELF : REGISTER;
 
-       if (source == SELF)
-       {
-               struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
-
-               add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
-
-               if (work)
-               {
-                       int add_type_local  = False;
-                       int add_type_domain = False;
-                       int add_type_logon  = False;
+  if (source == SELF)
+    {
+      struct work_record *work = find_workgroupstruct(d, 
+                                  myworkgroup, False);
 
-                       /* work out what to become, from the name type being added */
+      add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
 
-                       if (ms_browser_name(name, name_type))
-                       {
-                               add_type_local = True;
-                       }
-                       if (strequal(name, lp_workgroup()) == 0 && name_type == 0x1d)
-                       {
-                               add_type_local = True;
-                       }
-                       if (strequal(name, lp_workgroup()) == 0 && name_type == 0x1b)
-                       {
-                               add_type_domain = True;
-                       }
-                       if (strequal(name, lp_workgroup()) == 0 && name_type == 0x1c)
-                       {
-                               add_type_logon = True;
-                       }
-
-                       if (add_type_local ) become_local_master (d, work);
-                       if (add_type_domain) become_domain_master(d, work);
-                       if (add_type_logon ) become_logon_server (d, work);
-               }
-       }
+      if (work)
+      {
+        int add_type_local  = False;
+        int add_type_domain = False;
+        int add_type_logon  = False;
+
+        DEBUG(4,("checking next stage: name_register_work %s\n", name));
+
+        /* work out what to become, from the name type being added */
+
+        if (ms_browser_name(name, name_type))
+        {
+          add_type_local = True;
+        }
+        if (strequal(name, myworkgroup) && name_type == 0x1d)
+        {
+          add_type_local = True;
+        }
+        if (strequal(name, myworkgroup) && name_type == 0x1b)
+        {
+          add_type_domain = True;
+        }
+        if (strequal(name, myworkgroup) && name_type == 0x1c)
+        {
+          add_type_logon = True;
+        }
+
+        if (add_type_local ) become_local_master (d, work);
+        if (add_type_domain) become_domain_master(d, work);
+        if (add_type_logon ) become_logon_server (d, work);
+      }
+    }
 }
 
 
@@ -304,26 +322,34 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
    */
   uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
 
-  if (!work || !d) return;
+  if (!work || !d) 
+    return;
   
+  if (!lp_local_master())
+  { 
+    DEBUG(0,("Samba not configured as a local master browser.\n"));
+    return;
+  }
+
   DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
-                                       work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
+           work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
   
   switch (work->mst_state)
   {
     case MST_POTENTIAL: /* while we were nothing but a server... */
     {
       DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
-      work->mst_state = MST_BACK; /* ... an election win was successful */
+      work->mst_state = MST_BACK; /* an election win was successful */
 
       work->ElectionCriterion |= 0x5;
 
       /* update our server status */
       work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
-      add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,lp_serverstring(),True);
 
       /* add special browser name */
-      add_my_name_entry(d,MSBROWSE        ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
+      add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
 
       /* DON'T do anything else after calling add_my_name_entry() */
       break;
@@ -332,10 +358,11 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
     case MST_BACK: /* while nothing had happened except we won an election... */
     {
       DEBUG(3,("go to second stage: register as master browser\n"));
-      work->mst_state = MST_MSB; /* ... registering MSBROWSE was successful */
+      work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
 
       /* add server entry on successful registration of MSBROWSE */
-      add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
+      add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,myname,True);
 
       /* add master name */
       add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
@@ -346,19 +373,42 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
 
     case MST_MSB: /* while we were still only registered MSBROWSE state... */
     {
-      DEBUG(3,("2nd stage complete: registered as master browser\n"));
-      work->mst_state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
+      int i = 0;
+      struct server_record *sl;
+
+      DEBUG(3,("2nd stage complete: registered as master browser for workgroup %s \
+on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip)));
+      work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
 
       /* update our server status */
       work->ServerType |= SV_TYPE_MASTER_BROWSER;
-      add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
 
-      if (work->serverlist == NULL) /* no servers! */
+      DEBUG(3,("become_local_master: updating our server %s to type %x\n", 
+                myname, work->ServerType));
+
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,lp_serverstring(),True);
+
+      /* Count the number of servers we have on our list. If it's
+         less than 10 (just a heuristic) request the servers
+         to announce themselves.
+       */
+      for( sl = work->serverlist; sl != NULL; sl = sl->next)
+        i++;
+
+      if (i < 10)
       {
         /* ask all servers on our local net to announce to us */
-        /* XXXX OOPS! add_server_entry will always add one entry - our own. */
         announce_request(work, d->bcast_ip);
       }
+
+      /* Reset the announce master timer so that we do an announce as soon as possible
+         now we are a master. */
+      reset_announce_timer();
+
+      DEBUG(0,("Samba is now a local master browser for workgroup %s on subnet %s\n", 
+                work->work_group, inet_ntoa(d->bcast_ip)));
+
       break;
     }
 
@@ -366,7 +416,6 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
     {
       /* don't have to do anything: just report success */
       DEBUG(3,("3rd stage: become master browser!\n"));
-
       break;
     }
   }
@@ -395,71 +444,78 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
   ******************************************************************/
 void become_domain_master(struct subnet_record *d, struct work_record *work)
 {
-  /* domain type must be limited to domain enum + server type. it must
-     not have SV_TYPE_SERVER or anything else with SERVER in it, else
-     clients get confused and start thinking this entry is a server
-     not a workgroup
-   */
+       /* domain type must be limited to domain enum + server type. it must
+       not have SV_TYPE_SERVER or anything else with SERVER in it, else
+       clients get confused and start thinking this entry is a server
+       not a workgroup
+       */
+
+       if (!work || !d) return;
+
+       if (!lp_domain_master())
+       { 
+               DEBUG(0,("Samba not configured as a domain master browser.\n"));
+               return;
+       }
 
-  if (!work || !d) return;
-  
-  DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
-                                       work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
-  
-  switch (work->dom_state)
-  {
-    case DOMAIN_NONE: /* while we were nothing but a server... */
-    {
-      if (lp_domain_master())
-      {
-                 DEBUG(3,("go to first stage: register <1b> name\n"));
-                 work->dom_state = DOMAIN_WAIT;
+       DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
+       work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
 
-                 /* XXXX the 0x1b is domain master browser name */
-                 add_my_name_entry(d, lp_workgroup(),0x1b,nb_type|NB_ACTIVE|NB_GROUP);
+       switch (work->dom_state)
+       {
+               case DOMAIN_NONE: /* while we were nothing but a server... */
+               {
+                       DEBUG(3,("become_domain_master: go to first stage: register <1b> name\n"));
+                       work->dom_state = DOMAIN_WAIT;
 
-                 /* DON'T do anything else after calling add_my_name_entry() */
-                 break;
-      }
-      else
-      {
-        DEBUG(4,("samba not configured as a domain master.\n"));
-      }
-  
-      break;
-    }
+                       /* XXXX the 0x1b is domain master browser name */
+                       add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE);
 
-   case DOMAIN_WAIT:
-   {
-      if (lp_domain_master())
-      {
-        work->dom_state = DOMAIN_MST; /* ... become domain master */
-        DEBUG(3,("domain first stage: register as domain member\n"));
-        /* update our server status */
-        work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
-        add_server_entry(d,work,myname,work->ServerType,0,
-                         lp_serverstring(),True);
+                       /* DON'T do anything else after calling add_my_name_entry() */
+                       break;
+               }
 
-        DEBUG(4,("samba is now a domain master\n"));
+               case DOMAIN_WAIT:
+               {
+                       work->dom_state = DOMAIN_MST; /* ... become domain master */
+                       DEBUG(3,("become_domain_master: first stage - register as domain member\n"));
 
-        break;
-      }
-      else
-      {
-        DEBUG(4,("samba not configured as a domain master.\n"));
-      }
-  
-      break;
-   }
+                       /* update our server status */
+                       work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
+                       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                                        0, lp_serverstring(),True);
 
-    case DOMAIN_MST:
-    {
-      /* don't have to do anything: just report success */
-      DEBUG(3,("domain second stage: there isn't one!\n"));
-      break;
-    }
-  }
+                       DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n", 
+                       work->work_group, inet_ntoa(d->bcast_ip)));
+
+                       if (d == wins_subnet)
+                       {
+                               /* ok! we successfully registered by unicast with the
+                                  WINS server.  we now expect to become the domain
+                                  master on the local subnets.  if this fails, it's
+                                  probably a 1.9.16p2 to 1.9.16p11 server's fault.
+
+                                  this is a configuration issue that should be addressed
+                                  by the network administrator - you shouldn't have
+                                  several machines configured as a domain master browser
+                                  for the same WINS scope (except if they are 1.9.17 or
+                                  greater, and you know what you're doing.
+
+                                  see DOMAIN.txt.
+
+                                */
+                               add_domain_master_bcast();
+                       }
+                       break;
+               }
+
+               case DOMAIN_MST:
+               {
+                       /* don't have to do anything: just report success */
+                       DEBUG(3,("domain second stage: there isn't one!\n"));
+                       break;
+               }
+       }
 }
 
 
@@ -470,60 +526,48 @@ void become_logon_server(struct subnet_record *d, struct work_record *work)
 {
   if (!work || !d) return;
   
+  if (!lp_domain_logons())
+  {
+    DEBUG(0,("samba not configured as a logon master.\n"));
+    return;
+  }
+
   DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
-                                       work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
+       work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
   
   switch (work->log_state)
   {
     case LOGON_NONE: /* while we were nothing but a server... */
     {
-      if (lp_domain_logons())
-      {
-                 DEBUG(3,("go to first stage: register <1c> name\n"));
-                 work->log_state = LOGON_WAIT;
+      DEBUG(3,("go to first stage: register <1c> name\n"));
+            work->log_state = LOGON_WAIT;
 
-          /* XXXX the 0x1c is apparently something to do with domain logons */
-          add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+     /* XXXX the 0x1c is apparently something to do with domain logons */
+     add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
 
-                 /* DON'T do anything else after calling add_my_name_entry() */
-                 break;
-      }
-      {
-        DEBUG(4,("samba not configured as a logon master.\n"));
-      }
-  
+      /* DON'T do anything else after calling add_my_name_entry() */
       break;
     }
 
-   case LOGON_WAIT:
-   {
-      if (lp_domain_logons())
-      {
-        work->log_state = LOGON_SRV; /* ... become logon server */
-        DEBUG(3,("logon second stage: register \n"));
+    case LOGON_WAIT:
+    {
+      work->log_state = LOGON_SRV; /* ... become logon server */
+      DEBUG(3,("logon second stage: register \n"));
  
-        /* update our server status */
-        work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
-        add_server_entry(d,work,myname,work->ServerType,0,
-                         lp_serverstring(),True);
+      /* update our server status */
+      work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY
+                                       ,0, lp_serverstring(),True);
 
-        /* DON'T do anything else after calling add_my_name_entry() */
-        break;
-      }
-      else
-      {
-        DEBUG(4,("samba not configured as a logon server.\n"));
-      }
-  
+      /* DON'T do anything else after calling add_my_name_entry() */
       break;
-   }
+    }
 
-   case LOGON_SRV:
-   {
+    case LOGON_SRV:
+    {
       DEBUG(3,("logon third stage: there isn't one!\n"));
       break;
-   }
-
+    }
   }
 }
 
@@ -586,9 +630,20 @@ void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
 
     work->dom_state = DOMAIN_NONE;
 
-       /* announce ourselves as no longer active as a master browser. */
-    announce_server(d, work, work->work_group, myname, 0, 0);
-    remove_name_entry(d,work->work_group,0x1b);    
+    /* announce ourselves as no longer active as a master browser on
+       all our local subnets. */
+    for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+    {
+      work = find_workgroupstruct(d, myworkgroup, False);
+
+      /* Remove the name entry without any NetBIOS traffic as that's
+         how it was registered. */
+      remove_name_entry(d,work->work_group,0x1b);    
+    }
+
+    /* Unregister the 1b name from the WINS server. */
+    if(wins_subnet != NULL)
+      remove_name_entry(wins_subnet, myworkgroup, 0x1b);
   }
 }
 
@@ -615,8 +670,6 @@ void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
 
     work->log_state = LOGON_NONE;
 
-       /* announce ourselves as no longer active as a master browser. */
-    announce_server(d, work, work->work_group, myname, 0, 0);
     remove_name_entry(d,work->work_group,0x1c);    
   }
 }
@@ -636,9 +689,10 @@ void run_elections(time_t t)
   
   lastime = t;
   
-  for (d = subnetlist; 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)
        {
          if (work->RunningElection)
@@ -672,6 +726,14 @@ static BOOL win_election(struct work_record *work,int version,uint32 criterion,
   int mytimeup = time(NULL) - StartupTime;
   uint32 mycriterion = work->ElectionCriterion;
 
+  /* If local master is false then never win
+     in election broadcasts. */
+  if(!lp_local_master())
+  {
+    DEBUG(3,("win_election: Losing election as local master == False\n"));
+    return False;
+  }
   DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
           version,ELECTION_VERSION,
           criterion,mycriterion,
@@ -700,53 +762,61 @@ static BOOL win_election(struct work_record *work,int version,uint32 criterion,
   ******************************************************************/
 void process_election(struct packet_struct *p,char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  struct in_addr ip = dgram->header.source_ip;
-  struct subnet_record *d = find_subnet(ip);
-  int version = CVAL(buf,0);
-  uint32 criterion = IVAL(buf,1);
-  int timeup = IVAL(buf,5)/1000;
-  char *name = buf+13;
-  struct work_record *work;
+       struct dgram_packet *dgram = &p->packet.dgram;
+       struct in_addr ip = dgram->header.source_ip;
+       struct subnet_record *d = find_subnet(ip);
+       int version = CVAL(buf,0);
+       uint32 criterion = IVAL(buf,1);
+       int timeup = IVAL(buf,5)/1000;
+       char *name = buf+13;
+       struct work_record *work;
+
+       if (!d) return;
+
+       if (ip_equal(d->bcast_ip,wins_ip))
+       {
+               DEBUG(0,("Unexpected election request from %s %s on WINS net\n",
+                         name, inet_ntoa(p->ip)));
+               return;
+       }
 
-  if (!d) return;
+       name[15] = 0;  
 
-  if (ip_equal(d->bcast_ip,ipgrp)) {
-    DEBUG(3,("Unexpected election request from %s %s on WINS net\n",
-            name, inet_ntoa(p->ip)));
-    return;
-  }
-  
-  name[15] = 0;  
+       DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
+                 name,inet_ntoa(p->ip),version,criterion,timeup));
 
-  DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
-          name,inet_ntoa(p->ip),version,criterion,timeup));
-  
-  if (same_context(dgram)) return;
-  
-  for (work = d->workgrouplist; work; work = work->next)
-    {
-      if (!strequal(work->work_group, lp_workgroup()))
-       continue;
-
-      if (win_election(work, version,criterion,timeup,name)) {
-       if (!work->RunningElection) {
-         work->needelection = True;
-         work->ElectionCount=0;
-         work->mst_state = MST_POTENTIAL;
-       }
-      } else {
-       work->needelection = False;
-         
-       if (work->RunningElection || AM_MASTER(work)) {
-         work->RunningElection = False;
-         DEBUG(3,(">>> Lost election on %s %s <<<\n",
-                  work->work_group,inet_ntoa(d->bcast_ip)));
-         if (AM_MASTER(work))
-           unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
+       if (same_context(dgram)) return;
+
+       for (work = d->workgrouplist; work; work = work->next)
+       {
+               if (!strequal(work->work_group, myworkgroup))
+               continue;
+
+               if (win_election(work, version,criterion,timeup,name))
+               {
+                       if (!work->RunningElection)
+                       {
+                               work->needelection = True;
+                               work->ElectionCount=0;
+                               work->mst_state = MST_POTENTIAL;
+                       }
+               }
+               else
+               {
+                       work->needelection = False;
+
+                       if (work->RunningElection || AM_MASTER(work))
+                       {
+                               work->RunningElection = False;
+                               DEBUG(3,(">>> Lost election on %s %s <<<\n",
+                                                 work->work_group,inet_ntoa(d->bcast_ip)));
+                               if (AM_MASTER(work))
+                               {
+                                       unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
+                               }
+                       }
+               }
        }
-      }
-    }
 }
 
 
@@ -763,7 +833,7 @@ BOOL check_elections(void)
   struct subnet_record *d;
   BOOL run_any_election = False;
 
-  for (d = subnetlist; 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)