coding standards issue: should never compare a boolean expression == False
[kai/samba.git] / source3 / nameelect.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Module name: nameelect.c
22
23    Revision History:
24
25    14 jan 96: lkcl@pires.co.uk
26    added multiple workgroup domain master support
27
28    04 jul 96: lkcl@pires.co.uk
29    added system to become a master browser by stages.
30
31
32 */
33
34 #include "includes.h"
35
36 extern int ClientNMB;
37 extern int ClientDGRAM;
38
39 extern int DEBUGLEVEL;
40 extern pstring scope;
41
42 extern pstring myname;
43 extern fstring myworkgroup;
44 extern struct in_addr ipzero;
45 extern struct in_addr wins_ip;
46
47 /* here are my election parameters */
48
49 extern time_t StartupTime;
50
51 extern struct subnet_record *subnetlist;
52
53 extern uint16 nb_type; /* samba's NetBIOS name type */
54
55
56 /*******************************************************************
57   occasionally check to see if the master browser is around
58   ******************************************************************/
59 void check_master_browser(time_t t)
60 {
61   static time_t lastrun=0;
62   struct subnet_record *d;
63
64   if (!lastrun) lastrun = t;
65   if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
66
67   lastrun = t;
68
69   dump_workgroups();
70
71   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
72   {
73     struct work_record *work;
74
75     for (work = d->workgrouplist; work; work = work->next)
76     {
77       if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work))
78       {
79         if (lp_local_master())
80         {
81           /* potential master browser - not a master browser.  force
82              becoming a master browser, hence the log message.
83            */
84
85           DEBUG(0,("%s potential master for %s %s - force election\n",
86                    timestring(), work->work_group,
87                    inet_ntoa(d->bcast_ip)));
88
89           browser_gone(work->work_group, d->bcast_ip);
90         }
91         else
92         {
93           /* if we are not the browse master of a workgroup,
94              and we can't find a browser on the subnet, do
95              something about it.
96            */
97
98           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
99                     work->work_group,0x1d,0,0,0,NULL,NULL,
100                     True,False,d->bcast_ip,d->bcast_ip);
101         }
102       }
103     }
104   }
105 }
106
107
108 /*******************************************************************
109   what to do if a master browser DOESN't exist.
110
111   option 1: force an election, and participate in it
112   option 2: force an election, and let everyone else participate.
113
114   ******************************************************************/
115 void browser_gone(char *work_name, struct in_addr ip)
116 {
117   struct subnet_record *d = find_subnet(ip);
118   struct work_record *work = find_workgroupstruct(d, work_name, False);
119
120   /* i don't know about this workgroup, therefore i don't care */
121   if (!work || !d) return;
122
123   /* don't do election stuff on the WINS subnet */
124   if (ip_equal(d->bcast_ip,wins_ip)) 
125     return;
126
127   if (strequal(work->work_group, myworkgroup))
128   {
129
130     if (lp_local_master())
131     {
132       /* we have discovered that there is no local master
133          browser, and we are configured to initiate
134          an election under exactly such circumstances.
135        */
136       DEBUG(2,("Forcing election on %s %s\n",
137                work->work_group,inet_ntoa(d->bcast_ip)));
138
139       /* we can attempt to become master browser */
140       work->needelection = True;
141     }
142     else
143     {
144       /* we need to force an election, because we are configured
145          not to _become_ the local master, but we still _need_ one,
146          having detected that one doesn't exist.
147        */
148
149       /* local interfaces: force an election */
150       send_election(d, work->work_group, 0, 0, myname);
151
152       /* only removes workgroup completely on a local interface 
153          persistent lmhosts entries on a local interface _will_ be removed).
154        */
155       remove_workgroup(d, work,True);
156       add_workgroup_to_subnet(d, work->work_group);
157     }
158   }
159 }
160
161
162 /****************************************************************************
163   send an election packet
164   **************************************************************************/
165 void send_election(struct subnet_record *d, char *group,uint32 criterion,
166                    int timeup,char *name)
167 {
168   pstring outbuf;
169   char *p;
170
171   if (!d) return;
172   
173   DEBUG(2,("Sending election to %s for workgroup %s\n",
174            inet_ntoa(d->bcast_ip),group));         
175
176   bzero(outbuf,sizeof(outbuf));
177   p = outbuf;
178   CVAL(p,0) = ANN_Election; /* election */
179   p++;
180
181   CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
182   SIVAL(p,1,criterion);
183   SIVAL(p,5,timeup*1000); /* ms - despite the spec */
184   p += 13;
185   strcpy(p,name);
186   strupper(p);
187   p = skip_string(p,1);
188   
189   send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
190               outbuf,PTR_DIFF(p,outbuf),
191                       name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
192 }
193
194
195 /****************************************************************************
196   un-register a SELF name that got rejected.
197
198   if this name happens to be rejected when samba is in the process
199   of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
200   or WORKGROUP(1b)) then we must stop being a master browser. sad.
201
202   **************************************************************************/
203 void name_unregister_work(struct subnet_record *d, char *name, int name_type)
204 {
205     struct work_record *work;
206     int remove_type_local  = 0;
207     int remove_type_domain = 0;
208     int remove_type_logon  = 0;
209
210     remove_netbios_name(d,name,name_type,SELF,ipzero);
211
212     if (!(work = find_workgroupstruct(d, name, False))) return;
213
214     /* work out what to unbecome, from the name type being removed */
215
216     if (ms_browser_name(name, name_type))
217     {
218       remove_type_local |= SV_TYPE_MASTER_BROWSER;
219     }
220     if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d)
221     {
222       remove_type_local |= SV_TYPE_MASTER_BROWSER;
223     }
224     if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b)
225     {
226       remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
227     }
228     if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c)
229     {
230       remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
231     }
232
233     if (remove_type_local ) unbecome_local_master (d, work, remove_type_local );
234     if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain);
235     if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon );
236 }
237
238
239 /****************************************************************************
240   registers a name.
241
242   if the name being added is a SELF name, we must additionally check
243   whether to proceed to the next stage in samba becoming a master browser.
244
245   **************************************************************************/
246 void name_register_work(struct subnet_record *d, char *name, int name_type,
247                                 int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
248 {
249   enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
250                                   SELF : REGISTER;
251
252   if (source == SELF)
253     {
254       struct work_record *work = find_workgroupstruct(d, 
255                                   myworkgroup, False);
256
257       add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
258
259       if (work)
260       {
261         int add_type_local  = False;
262         int add_type_domain = False;
263         int add_type_logon  = False;
264
265         DEBUG(4,("checking next stage: name_register_work %s\n", name));
266
267         /* work out what to become, from the name type being added */
268
269         if (ms_browser_name(name, name_type))
270         {
271           add_type_local = True;
272         }
273         if (strequal(name, myworkgroup) && name_type == 0x1d)
274         {
275           add_type_local = True;
276         }
277         if (strequal(name, myworkgroup) && name_type == 0x1b)
278         {
279           add_type_domain = True;
280         }
281         if (strequal(name, myworkgroup) && name_type == 0x1c)
282         {
283           add_type_logon = True;
284         }
285
286         if (add_type_local ) become_local_master (d, work);
287         if (add_type_domain) become_domain_master(d, work);
288         if (add_type_logon ) become_logon_server (d, work);
289       }
290     }
291 }
292
293
294 /*******************************************************************
295   become the local master browser.
296
297   this is done in stages. note that this could take a while, 
298   particularly on a broadcast subnet, as we have to wait for
299   the implicit registration of each name to be accepted.
300
301   as each name is successfully registered, become_local_master() is
302   called again, in order to initiate the next stage. see
303   dead_netbios_entry() - deals with implicit name registration
304   and response_name_reg() - deals with explicit registration
305   with a WINS server.
306
307   stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
308   stage 2: was MST_BACK  - go to MST_MSB  and register WORKGROUP(0x1d)
309   stage 3: was MST_MSB  - go to MST_BROWSER and stay there 
310
311   XXXX note: this code still does not cope with the distinction
312   between different types of nodes, particularly between M and P
313   nodes. that comes later.
314
315   ******************************************************************/
316 void become_local_master(struct subnet_record *d, struct work_record *work)
317 {
318   /* domain type must be limited to domain enum + server type. it must
319      not have SV_TYPE_SERVER or anything else with SERVER in it, else
320      clients get confused and start thinking this entry is a server
321      not a workgroup
322    */
323   uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
324
325   if (!work || !d) 
326     return;
327   
328   DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
329            work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
330   
331   switch (work->mst_state)
332   {
333     case MST_POTENTIAL: /* while we were nothing but a server... */
334     {
335       DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
336       work->mst_state = MST_BACK; /* an election win was successful */
337
338       work->ElectionCriterion |= 0x5;
339
340       /* update our server status */
341       work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
342       add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
343
344       /* add special browser name */
345       add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
346
347       /* DON'T do anything else after calling add_my_name_entry() */
348       break;
349     }
350
351     case MST_BACK: /* while nothing had happened except we won an election... */
352     {
353       DEBUG(3,("go to second stage: register as master browser\n"));
354       work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
355
356       /* add server entry on successful registration of MSBROWSE */
357       add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
358
359       /* add master name */
360       add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
361   
362       /* DON'T do anything else after calling add_my_name_entry() */
363       break;
364     }
365
366     case MST_MSB: /* while we were still only registered MSBROWSE state... */
367     {
368       DEBUG(3,("2nd stage complete: registered as master browser\n"));
369       work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
370
371       /* update our server status */
372       work->ServerType |= SV_TYPE_MASTER_BROWSER;
373
374       DEBUG(3,("become_local_master: updating our server %s to type %x\n", 
375                 myname, work->ServerType));
376
377       add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
378
379       if (work->serverlist == NULL) /* no servers! */
380       {
381         /* ask all servers on our local net to announce to us */
382         /* XXXX OOPS! add_server_entry always adds one entry - ours. */
383         announce_request(work, d->bcast_ip);
384       }
385
386       /* Reset the announce master timer so that we do an announce as soon as possible
387          now we are a master. */
388       reset_announce_timer();
389       break;
390     }
391
392     case MST_BROWSER:
393     {
394       /* don't have to do anything: just report success */
395       DEBUG(3,("3rd stage: become master browser!\n"));
396       break;
397     }
398   }
399 }
400
401
402 /*******************************************************************
403   become the domain master browser.
404
405   this is done in stages. note that this could take a while, 
406   particularly on a broadcast subnet, as we have to wait for
407   the implicit registration of each name to be accepted.
408
409   as each name is successfully registered, become_domain_master() is
410   called again, in order to initiate the next stage. see
411   dead_netbios_entry() - deals with implicit name registration
412   and response_name_reg() - deals with explicit registration
413   with a WINS server.
414
415   stage 1: was DOMAIN_NONE - go to DOMAIN_MST 
416
417   XXXX note: this code still does not cope with the distinction
418   between different types of nodes, particularly between M and P
419   nodes. that comes later.
420
421   ******************************************************************/
422 void become_domain_master(struct subnet_record *d, struct work_record *work)
423 {
424   /* domain type must be limited to domain enum + server type. it must
425      not have SV_TYPE_SERVER or anything else with SERVER in it, else
426      clients get confused and start thinking this entry is a server
427      not a workgroup
428    */
429
430   if (!work || !d) return;
431   
432   DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
433                                         work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
434   
435   switch (work->dom_state)
436   {
437     case DOMAIN_NONE: /* while we were nothing but a server... */
438     {
439       if (lp_domain_master())
440       {
441                   DEBUG(3,("go to first stage: register <1b> name\n"));
442                   work->dom_state = DOMAIN_WAIT;
443
444                   /* XXXX the 0x1b is domain master browser name */
445                   add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE|NB_GROUP);
446
447                   /* DON'T do anything else after calling add_my_name_entry() */
448                   break;
449       }
450       else
451       {
452         DEBUG(4,("samba not configured as a domain master.\n"));
453       }
454   
455       break;
456     }
457
458    case DOMAIN_WAIT:
459    {
460       if (lp_domain_master())
461       {
462         work->dom_state = DOMAIN_MST; /* ... become domain master */
463         DEBUG(3,("domain first stage: register as domain member\n"));
464  
465         /* update our server status */
466         work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
467         add_server_entry(d,work,myname,work->ServerType,0,
468                          lp_serverstring(),True);
469
470         DEBUG(4,("samba is now a domain master\n"));
471
472         break;
473       }
474       else
475       {
476         DEBUG(4,("samba not configured as a domain master.\n"));
477       }
478   
479       break;
480    }
481
482     case DOMAIN_MST:
483     {
484       /* don't have to do anything: just report success */
485       DEBUG(3,("domain second stage: there isn't one!\n"));
486       break;
487     }
488   }
489 }
490
491
492 /*******************************************************************
493   become a logon server.
494   ******************************************************************/
495 void become_logon_server(struct subnet_record *d, struct work_record *work)
496 {
497   if (!work || !d) return;
498   
499   DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
500                                         work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
501   
502   switch (work->log_state)
503   {
504     case LOGON_NONE: /* while we were nothing but a server... */
505     {
506       if (lp_domain_logons())
507       {
508                   DEBUG(3,("go to first stage: register <1c> name\n"));
509                   work->log_state = LOGON_WAIT;
510
511           /* XXXX the 0x1c is apparently something to do with domain logons */
512           add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
513
514                   /* DON'T do anything else after calling add_my_name_entry() */
515                   break;
516       }
517       {
518         DEBUG(4,("samba not configured as a logon master.\n"));
519       }
520   
521       break;
522     }
523
524    case LOGON_WAIT:
525    {
526       if (lp_domain_logons())
527       {
528         work->log_state = LOGON_SRV; /* ... become logon server */
529         DEBUG(3,("logon second stage: register \n"));
530  
531         /* update our server status */
532         work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
533         add_server_entry(d,work,myname,work->ServerType,0,
534                          lp_serverstring(),True);
535
536         /* DON'T do anything else after calling add_my_name_entry() */
537         break;
538       }
539       else
540       {
541         DEBUG(4,("samba not configured as a logon server.\n"));
542       }
543   
544       break;
545    }
546
547    case LOGON_SRV:
548    {
549       DEBUG(3,("logon third stage: there isn't one!\n"));
550       break;
551    }
552
553   }
554 }
555
556
557 /*******************************************************************
558   unbecome the local master browser. initates removal of necessary netbios 
559   names, and tells the world that we are no longer a master browser.
560
561   XXXX this _should_ be used to demote to a backup master browser, without
562   going straight to non-master browser.  another time.
563
564   ******************************************************************/
565 void unbecome_local_master(struct subnet_record *d, struct work_record *work,
566                                 int remove_type)
567 {
568   int new_server_type = work->ServerType;
569
570   /* can only remove master types with this function */
571   remove_type &= SV_TYPE_MASTER_BROWSER;
572
573   new_server_type &= ~remove_type;
574
575   if (remove_type)
576   {
577     DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
578   
579     /* no longer a master browser of any sort */
580
581     work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
582     work->ElectionCriterion &= ~0x4;
583     work->mst_state = MST_POTENTIAL;
584
585         /* announce ourselves as no longer active as a master browser. */
586     announce_server(d, work, work->work_group, myname, 0, 0);
587     remove_name_entry(d,MSBROWSE        ,0x01);
588     remove_name_entry(d,work->work_group,0x1d);
589   }
590 }
591
592
593 /*******************************************************************
594   unbecome the domain master browser. initates removal of necessary netbios 
595   names, and tells the world that we are no longer a domain browser.
596   ******************************************************************/
597 void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
598                                 int remove_type)
599 {
600   int new_server_type = work->ServerType;
601
602   DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
603   
604   /* can only remove master or domain types with this function */
605   remove_type &= SV_TYPE_DOMAIN_MASTER;
606
607   new_server_type &= ~remove_type;
608
609   if (remove_type)
610   {
611     /* no longer a domain master browser of any sort */
612
613     work->dom_state = DOMAIN_NONE;
614
615         /* announce ourselves as no longer active as a master browser. */
616     announce_server(d, work, work->work_group, myname, 0, 0);
617     remove_name_entry(d,work->work_group,0x1b);    
618   }
619 }
620
621
622 /*******************************************************************
623   unbecome the logon server. initates removal of necessary netbios 
624   names, and tells the world that we are no longer a logon server.
625   ******************************************************************/
626 void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
627                                 int remove_type)
628 {
629   int new_server_type = work->ServerType;
630
631   DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
632   
633   /* can only remove master or domain types with this function */
634   remove_type &= SV_TYPE_DOMAIN_MEMBER;
635
636   new_server_type &= ~remove_type;
637
638   if (remove_type)
639   {
640     /* no longer a master browser of any sort */
641
642     work->log_state = LOGON_NONE;
643
644         /* announce ourselves as no longer active as a master browser. */
645     announce_server(d, work, work->work_group, myname, 0, 0);
646     remove_name_entry(d,work->work_group,0x1c);    
647   }
648 }
649
650
651 /*******************************************************************
652   run the election
653   ******************************************************************/
654 void run_elections(time_t t)
655 {
656   static time_t lastime = 0;
657   
658   struct subnet_record *d;
659   
660   /* send election packets once a second */
661   if (lastime && t-lastime <= 0) return;
662   
663   lastime = t;
664   
665   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
666   {
667     struct work_record *work;
668
669     for (work = d->workgrouplist; work; work = work->next)
670         {
671           if (work->RunningElection)
672           {
673             send_election(d,work->work_group, work->ElectionCriterion,
674                             t-StartupTime,myname);
675               
676             if (work->ElectionCount++ >= 4)
677                 {
678                   /* I won! now what :-) */
679                   DEBUG(2,(">>> Won election on %s %s <<<\n",
680                            work->work_group,inet_ntoa(d->bcast_ip)));
681                   
682                   work->RunningElection = False;
683                   work->mst_state = MST_POTENTIAL;
684
685                   become_local_master(d, work);
686                 }
687           }
688         }
689   }
690 }
691
692
693 /*******************************************************************
694   work out if I win an election
695   ******************************************************************/
696 static BOOL win_election(struct work_record *work,int version,uint32 criterion,
697                          int timeup,char *name)
698 {  
699   int mytimeup = time(NULL) - StartupTime;
700   uint32 mycriterion = work->ElectionCriterion;
701
702   /* If local master is false then never win
703      in election broadcasts. */
704   if(!lp_local_master())
705   {
706     DEBUG(3,("win_election: Losing election as local master == False\n"));
707     return False;
708   }
709  
710   DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
711            version,ELECTION_VERSION,
712            criterion,mycriterion,
713            timeup,mytimeup,
714            name,myname));
715
716   if (version > ELECTION_VERSION) return(False);
717   if (version < ELECTION_VERSION) return(True);
718   
719   if (criterion > mycriterion) return(False);
720   if (criterion < mycriterion) return(True);
721
722   if (timeup > mytimeup) return(False);
723   if (timeup < mytimeup) return(True);
724
725   if (strcasecmp(myname,name) > 0) return(False);
726   
727   return(True);
728 }
729
730
731 /*******************************************************************
732   process a election packet
733
734   An election dynamically decides who will be the master. 
735   ******************************************************************/
736 void process_election(struct packet_struct *p,char *buf)
737 {
738         struct dgram_packet *dgram = &p->packet.dgram;
739         struct in_addr ip = dgram->header.source_ip;
740         struct subnet_record *d = find_subnet(ip);
741         int version = CVAL(buf,0);
742         uint32 criterion = IVAL(buf,1);
743         int timeup = IVAL(buf,5)/1000;
744         char *name = buf+13;
745         struct work_record *work;
746
747         if (!d) return;
748
749         if (ip_equal(d->bcast_ip,wins_ip))
750         {
751                 DEBUG(3,("Unexpected election request from %s %s on WINS net\n",
752                           name, inet_ntoa(p->ip)));
753                 return;
754         }
755
756         name[15] = 0;  
757
758         DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
759                   name,inet_ntoa(p->ip),version,criterion,timeup));
760
761         if (same_context(dgram)) return;
762
763         for (work = d->workgrouplist; work; work = work->next)
764         {
765                 if (!strequal(work->work_group, myworkgroup))
766                 continue;
767
768                 if (win_election(work, version,criterion,timeup,name))
769                 {
770                         if (!work->RunningElection)
771                         {
772                                 work->needelection = True;
773                                 work->ElectionCount=0;
774                                 work->mst_state = MST_POTENTIAL;
775                         }
776                 }
777                 else
778                 {
779                         work->needelection = False;
780
781                         if (work->RunningElection || AM_MASTER(work))
782                         {
783                                 work->RunningElection = False;
784                                 DEBUG(3,(">>> Lost election on %s %s <<<\n",
785                                                   work->work_group,inet_ntoa(d->bcast_ip)));
786                                 if (AM_MASTER(work))
787                                 {
788                                         unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
789                                 }
790                         }
791                 }
792         }
793 }
794
795
796 /****************************************************************************
797   checks whether a browser election is to be run on any workgroup
798
799   this function really ought to return the time between election
800   packets (which depends on whether samba intends to be a domain
801   master or a master browser) in milliseconds.
802
803   ***************************************************************************/
804 BOOL check_elections(void)
805 {
806   struct subnet_record *d;
807   BOOL run_any_election = False;
808
809   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
810     {
811       struct work_record *work;
812       for (work = d->workgrouplist; work; work = work->next)
813         {
814           run_any_election |= work->RunningElection;
815           
816           if (work->needelection && !work->RunningElection)
817             {
818               DEBUG(3,(">>> Starting election on %s %s <<<\n",
819                        work->work_group,inet_ntoa(d->bcast_ip)));
820               work->ElectionCount = 0;
821               work->RunningElection = True;
822               work->needelection = False;
823             }
824         }
825     }
826   return run_any_election;
827 }
828