nameserv.c: split add_domain_names() into three functions:
[samba.git] / source / 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(2,("%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   if (!lp_local_master())
329   { 
330     DEBUG(0,("Samba not configured as a local master browser.\n"));
331     return;
332   }
333
334   DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
335            work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
336   
337   switch (work->mst_state)
338   {
339     case MST_POTENTIAL: /* while we were nothing but a server... */
340     {
341       DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
342       work->mst_state = MST_BACK; /* an election win was successful */
343
344       work->ElectionCriterion |= 0x5;
345
346       /* update our server status */
347       work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
348       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
349                                 0,lp_serverstring(),True);
350
351       /* add special browser name */
352       add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
353
354       /* DON'T do anything else after calling add_my_name_entry() */
355       break;
356     }
357
358     case MST_BACK: /* while nothing had happened except we won an election... */
359     {
360       DEBUG(3,("go to second stage: register as master browser\n"));
361       work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
362
363       /* add server entry on successful registration of MSBROWSE */
364       add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY,
365                                 0,myname,True);
366
367       /* add master name */
368       add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
369   
370       /* DON'T do anything else after calling add_my_name_entry() */
371       break;
372     }
373
374     case MST_MSB: /* while we were still only registered MSBROWSE state... */
375     {
376       int i = 0;
377       struct server_record *sl;
378
379       DEBUG(3,("2nd stage complete: registered as master browser for workgroup %s \
380 on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip)));
381       work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
382
383       /* update our server status */
384       work->ServerType |= SV_TYPE_MASTER_BROWSER;
385
386       DEBUG(3,("become_local_master: updating our server %s to type %x\n", 
387                 myname, work->ServerType));
388
389       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
390                                 0,lp_serverstring(),True);
391
392       /* Count the number of servers we have on our list. If it's
393          less than 10 (just a heuristic) request the servers
394          to announce themselves.
395        */
396       for( sl = work->serverlist; sl != NULL; sl = sl->next)
397         i++;
398
399       if (i < 10)
400       {
401         /* ask all servers on our local net to announce to us */
402         announce_request(work, d->bcast_ip);
403       }
404
405       /* Reset the announce master timer so that we do an announce as soon as possible
406          now we are a master. */
407       reset_announce_timer();
408
409       DEBUG(0,("Samba is now a local master browser for workgroup %s on subnet %s\n", 
410                 work->work_group, inet_ntoa(d->bcast_ip)));
411
412       break;
413     }
414
415     case MST_BROWSER:
416     {
417       /* don't have to do anything: just report success */
418       DEBUG(3,("3rd stage: become master browser!\n"));
419       break;
420     }
421   }
422 }
423
424
425 /*******************************************************************
426   become the domain master browser.
427
428   this is done in stages. note that this could take a while, 
429   particularly on a broadcast subnet, as we have to wait for
430   the implicit registration of each name to be accepted.
431
432   as each name is successfully registered, become_domain_master() is
433   called again, in order to initiate the next stage. see
434   dead_netbios_entry() - deals with implicit name registration
435   and response_name_reg() - deals with explicit registration
436   with a WINS server.
437
438   stage 1: was DOMAIN_NONE - go to DOMAIN_MST 
439
440   XXXX note: this code still does not cope with the distinction
441   between different types of nodes, particularly between M and P
442   nodes. that comes later.
443
444   ******************************************************************/
445 void become_domain_master(struct subnet_record *d, struct work_record *work)
446 {
447         /* domain type must be limited to domain enum + server type. it must
448         not have SV_TYPE_SERVER or anything else with SERVER in it, else
449         clients get confused and start thinking this entry is a server
450         not a workgroup
451         */
452
453         if (!work || !d) return;
454
455         if (!lp_domain_master())
456         { 
457                 DEBUG(0,("Samba not configured as a domain master browser.\n"));
458                 return;
459         }
460
461         DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
462         work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
463
464         switch (work->dom_state)
465         {
466                 case DOMAIN_NONE: /* while we were nothing but a server... */
467                 {
468                         DEBUG(3,("become_domain_master: go to first stage: register <1b> name\n"));
469                         work->dom_state = DOMAIN_WAIT;
470
471                         /* Registering the DOMAIN<1b> name is very tricky. We need to
472                         do this on all our subnets, but don't want to bradcast it
473                         on locally connected subnets (WinNT doesn't do this). Also,
474                         previous versions of Samba screw up royally when we do this.
475                         We need to register it immediatly on our local subnet, but
476                         also actually check with the WINS server if it exists. If the name
477                         has already been claimed by someone else in the WINS server
478                         then we need to back out all our local registrations and
479                         fail. Thus we only directly enter the name on local subnets,
480                         on the WINS subnet we actually check...
481                         */
482                         /* XXXX the 0x1b is domain master browser name */
483                         add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE);
484
485                         /* DON'T do anything else after calling add_my_name_entry() */
486                         break;
487                 }
488
489                 case DOMAIN_WAIT:
490                 {
491                         work->dom_state = DOMAIN_MST; /* ... become domain master */
492                         DEBUG(3,("become_domain_master: first stage - register as domain member\n"));
493
494                         /* update our server status */
495                         work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
496                         add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
497                         0, lp_serverstring(),True);
498
499                         DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n", 
500                         work->work_group, inet_ntoa(d->bcast_ip)));
501
502                         if (d == wins_subnet)
503                         {
504                                 /* ok! we successfully registered by unicast with the
505                                    WINS server.  we now expect to become the domain
506                                    master on the local subnets.  if this fails, it's
507                                    probably a 1.9.16p2 to 1.9.16p11 server's fault
508                                  */
509                                 add_domain_master_bcast();
510                         }
511                         break;
512                 }
513
514                 case DOMAIN_MST:
515                 {
516                         /* don't have to do anything: just report success */
517                         DEBUG(3,("domain second stage: there isn't one!\n"));
518                         break;
519                 }
520         }
521 }
522
523
524 /*******************************************************************
525   become a logon server.
526   ******************************************************************/
527 void become_logon_server(struct subnet_record *d, struct work_record *work)
528 {
529   if (!work || !d) return;
530   
531   if (!lp_domain_logons())
532   {
533     DEBUG(0,("samba not configured as a logon master.\n"));
534     return;
535   }
536
537   DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
538         work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
539   
540   switch (work->log_state)
541   {
542     case LOGON_NONE: /* while we were nothing but a server... */
543     {
544       DEBUG(3,("go to first stage: register <1c> name\n"));
545             work->log_state = LOGON_WAIT;
546
547      /* XXXX the 0x1c is apparently something to do with domain logons */
548      add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
549
550       /* DON'T do anything else after calling add_my_name_entry() */
551       break;
552     }
553
554     case LOGON_WAIT:
555     {
556       work->log_state = LOGON_SRV; /* ... become logon server */
557       DEBUG(3,("logon second stage: register \n"));
558  
559       /* update our server status */
560       work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
561       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY
562                                         ,0, lp_serverstring(),True);
563
564       /* DON'T do anything else after calling add_my_name_entry() */
565       break;
566     }
567
568     case LOGON_SRV:
569     {
570       DEBUG(3,("logon third stage: there isn't one!\n"));
571       break;
572     }
573   }
574 }
575
576
577 /*******************************************************************
578   unbecome the local master browser. initates removal of necessary netbios 
579   names, and tells the world that we are no longer a master browser.
580
581   XXXX this _should_ be used to demote to a backup master browser, without
582   going straight to non-master browser.  another time.
583
584   ******************************************************************/
585 void unbecome_local_master(struct subnet_record *d, struct work_record *work,
586                                 int remove_type)
587 {
588   int new_server_type = work->ServerType;
589
590   /* can only remove master types with this function */
591   remove_type &= SV_TYPE_MASTER_BROWSER;
592
593   new_server_type &= ~remove_type;
594
595   if (remove_type)
596   {
597     DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
598   
599     /* no longer a master browser of any sort */
600
601     work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
602     work->ElectionCriterion &= ~0x4;
603     work->mst_state = MST_POTENTIAL;
604
605         /* announce ourselves as no longer active as a master browser. */
606     announce_server(d, work, work->work_group, myname, 0, 0);
607     remove_name_entry(d,MSBROWSE        ,0x01);
608     remove_name_entry(d,work->work_group,0x1d);
609   }
610 }
611
612
613 /*******************************************************************
614   unbecome the domain master browser. initates removal of necessary netbios 
615   names, and tells the world that we are no longer a domain browser.
616   ******************************************************************/
617 void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
618                                 int remove_type)
619 {
620   int new_server_type = work->ServerType;
621
622   DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
623   
624   /* can only remove master or domain types with this function */
625   remove_type &= SV_TYPE_DOMAIN_MASTER;
626
627   new_server_type &= ~remove_type;
628
629   if (remove_type)
630   {
631     /* no longer a domain master browser of any sort */
632
633     work->dom_state = DOMAIN_NONE;
634
635     /* announce ourselves as no longer active as a master browser on
636        all our local subnets. */
637     for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
638     {
639       work = find_workgroupstruct(d, myworkgroup, False);
640
641       announce_server(d, work, work->work_group, myname, 0, 0);
642       /* Remove the name entry without any NetBIOS traffic as that's
643          how it was registered. */
644       remove_name_entry(d,work->work_group,0x1b);    
645     }
646   }
647 }
648
649
650 /*******************************************************************
651   unbecome the logon server. initates removal of necessary netbios 
652   names, and tells the world that we are no longer a logon server.
653   ******************************************************************/
654 void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
655                                 int remove_type)
656 {
657   int new_server_type = work->ServerType;
658
659   DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
660   
661   /* can only remove master or domain types with this function */
662   remove_type &= SV_TYPE_DOMAIN_MEMBER;
663
664   new_server_type &= ~remove_type;
665
666   if (remove_type)
667   {
668     /* no longer a master browser of any sort */
669
670     work->log_state = LOGON_NONE;
671
672         /* announce ourselves as no longer active as a master browser. */
673     announce_server(d, work, work->work_group, myname, 0, 0);
674     remove_name_entry(d,work->work_group,0x1c);    
675   }
676 }
677
678
679 /*******************************************************************
680   run the election
681   ******************************************************************/
682 void run_elections(time_t t)
683 {
684   static time_t lastime = 0;
685   
686   struct subnet_record *d;
687   
688   /* send election packets once a second */
689   if (lastime && t-lastime <= 0) return;
690   
691   lastime = t;
692   
693   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
694   {
695     struct work_record *work;
696
697     for (work = d->workgrouplist; work; work = work->next)
698         {
699           if (work->RunningElection)
700           {
701             send_election(d,work->work_group, work->ElectionCriterion,
702                             t-StartupTime,myname);
703               
704             if (work->ElectionCount++ >= 4)
705                 {
706                   /* I won! now what :-) */
707                   DEBUG(2,(">>> Won election on %s %s <<<\n",
708                            work->work_group,inet_ntoa(d->bcast_ip)));
709                   
710                   work->RunningElection = False;
711                   work->mst_state = MST_POTENTIAL;
712
713                   become_local_master(d, work);
714                 }
715           }
716         }
717   }
718 }
719
720
721 /*******************************************************************
722   work out if I win an election
723   ******************************************************************/
724 static BOOL win_election(struct work_record *work,int version,uint32 criterion,
725                          int timeup,char *name)
726 {  
727   int mytimeup = time(NULL) - StartupTime;
728   uint32 mycriterion = work->ElectionCriterion;
729
730   /* If local master is false then never win
731      in election broadcasts. */
732   if(!lp_local_master())
733   {
734     DEBUG(3,("win_election: Losing election as local master == False\n"));
735     return False;
736   }
737  
738   DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
739            version,ELECTION_VERSION,
740            criterion,mycriterion,
741            timeup,mytimeup,
742            name,myname));
743
744   if (version > ELECTION_VERSION) return(False);
745   if (version < ELECTION_VERSION) return(True);
746   
747   if (criterion > mycriterion) return(False);
748   if (criterion < mycriterion) return(True);
749
750   if (timeup > mytimeup) return(False);
751   if (timeup < mytimeup) return(True);
752
753   if (strcasecmp(myname,name) > 0) return(False);
754   
755   return(True);
756 }
757
758
759 /*******************************************************************
760   process a election packet
761
762   An election dynamically decides who will be the master. 
763   ******************************************************************/
764 void process_election(struct packet_struct *p,char *buf)
765 {
766         struct dgram_packet *dgram = &p->packet.dgram;
767         struct in_addr ip = dgram->header.source_ip;
768         struct subnet_record *d = find_subnet(ip);
769         int version = CVAL(buf,0);
770         uint32 criterion = IVAL(buf,1);
771         int timeup = IVAL(buf,5)/1000;
772         char *name = buf+13;
773         struct work_record *work;
774
775         if (!d) return;
776
777         if (ip_equal(d->bcast_ip,wins_ip))
778         {
779                 DEBUG(3,("Unexpected election request from %s %s on WINS net\n",
780                           name, inet_ntoa(p->ip)));
781                 return;
782         }
783
784         name[15] = 0;  
785
786         DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
787                   name,inet_ntoa(p->ip),version,criterion,timeup));
788
789         if (same_context(dgram)) return;
790
791         for (work = d->workgrouplist; work; work = work->next)
792         {
793                 if (!strequal(work->work_group, myworkgroup))
794                 continue;
795
796                 if (win_election(work, version,criterion,timeup,name))
797                 {
798                         if (!work->RunningElection)
799                         {
800                                 work->needelection = True;
801                                 work->ElectionCount=0;
802                                 work->mst_state = MST_POTENTIAL;
803                         }
804                 }
805                 else
806                 {
807                         work->needelection = False;
808
809                         if (work->RunningElection || AM_MASTER(work))
810                         {
811                                 work->RunningElection = False;
812                                 DEBUG(3,(">>> Lost election on %s %s <<<\n",
813                                                   work->work_group,inet_ntoa(d->bcast_ip)));
814                                 if (AM_MASTER(work))
815                                 {
816                                         unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
817                                 }
818                         }
819                 }
820         }
821 }
822
823
824 /****************************************************************************
825   checks whether a browser election is to be run on any workgroup
826
827   this function really ought to return the time between election
828   packets (which depends on whether samba intends to be a domain
829   master or a master browser) in milliseconds.
830
831   ***************************************************************************/
832 BOOL check_elections(void)
833 {
834   struct subnet_record *d;
835   BOOL run_any_election = False;
836
837   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
838     {
839       struct work_record *work;
840       for (work = d->workgrouplist; work; work = work->next)
841         {
842           run_any_election |= work->RunningElection;
843           
844           if (work->needelection && !work->RunningElection)
845             {
846               DEBUG(3,(">>> Starting election on %s %s <<<\n",
847                        work->work_group,inet_ntoa(d->bcast_ip)));
848               work->ElectionCount = 0;
849               work->RunningElection = True;
850               work->needelection = False;
851             }
852         }
853     }
854   return run_any_election;
855 }
856