bug: when checking whether there is a PDC already on the current local
[Samba/gbeck.git] / source / nameelect.c
blob9254e44712892e0786b8ada3f6127702d54e4662
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1996
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.
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.
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.
21 Module name: nameelect.c
23 Revision History:
25 14 jan 96: lkcl@pires.co.uk
26 added multiple workgroup domain master support
28 04 jul 96: lkcl@pires.co.uk
29 added system to become a master browser by stages.
34 #include "includes.h"
36 extern int ClientNMB;
37 extern int ClientDGRAM;
39 extern int DEBUGLEVEL;
40 extern pstring scope;
42 extern pstring myname;
43 extern struct in_addr ipzero;
44 extern struct in_addr ipgrp;
46 /* here are my election parameters */
48 extern time_t StartupTime;
50 extern struct subnet_record *subnetlist;
52 extern uint16 nb_type; /* samba's NetBIOS name type */
55 /*******************************************************************
56 occasionally check to see if the master browser is around
57 ******************************************************************/
58 void check_master_browser(time_t t)
60 static time_t lastrun=0;
61 struct subnet_record *d;
63 if (!lastrun) lastrun = t;
64 if (t < lastrun + CHECK_TIME_MST_BROWSE * 60)
65 return;
66 lastrun = t;
68 dump_workgroups();
70 for (d = subnetlist; d; d = d->next)
72 struct work_record *work;
74 for (work = d->workgrouplist; work; work = work->next)
76 if (!AM_MASTER(work))
78 if (lp_preferred_master())
80 /* preferred master - not a master browser. force
81 becoming a master browser, hence the log message.
84 DEBUG(0,("%s preferred master for %s %s - force election\n",
85 timestring(), work->work_group,
86 inet_ntoa(d->bcast_ip)));
88 browser_gone(work->work_group, d->bcast_ip);
90 else
92 /* if we are not the browse master of a workgroup,
93 and we can't find a browser on the subnet, do
94 something about it.
97 queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
98 work->work_group,0x1d,0,0,0,NULL,NULL,
99 True,False,d->bcast_ip,d->bcast_ip);
107 /*******************************************************************
108 what to do if a master browser DOESN't exist
109 ******************************************************************/
110 void browser_gone(char *work_name, struct in_addr ip)
112 struct subnet_record *d = find_subnet(ip);
113 struct work_record *work = find_workgroupstruct(d, work_name, False);
115 /* i don't know about this workgroup, therefore i don't care */
116 if (!work || !d) return;
118 /* don't do election stuff on the WINS subnet */
119 if (ip_equal(d->bcast_ip,ipgrp))
120 return;
122 if (strequal(work->work_group, lp_workgroup()))
125 DEBUG(2,("Forcing election on %s %s\n",
126 work->work_group,inet_ntoa(d->bcast_ip)));
128 /* we can attempt to become master browser */
129 work->needelection = True;
131 else
133 /* local interfaces: force an election */
134 send_election(d, work->work_group, 0, 0, myname);
136 /* only removes workgroup completely on a local interface
137 persistent lmhosts entries on a local interface _will_ be removed).
139 remove_workgroup(d, work,True);
144 /****************************************************************************
145 send an election packet
146 **************************************************************************/
147 void send_election(struct subnet_record *d, char *group,uint32 criterion,
148 int timeup,char *name)
150 pstring outbuf;
151 char *p;
153 if (!d) return;
155 DEBUG(2,("Sending election to %s for workgroup %s\n",
156 inet_ntoa(d->bcast_ip),group));
158 bzero(outbuf,sizeof(outbuf));
159 p = outbuf;
160 CVAL(p,0) = ANN_Election; /* election */
161 p++;
163 CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
164 SIVAL(p,1,criterion);
165 SIVAL(p,5,timeup*1000); /* ms - despite the spec */
166 p += 13;
167 strcpy(p,name);
168 strupper(p);
169 p = skip_string(p,1);
171 send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
172 outbuf,PTR_DIFF(p,outbuf),
173 name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
177 /****************************************************************************
178 un-register a SELF name that got rejected.
180 if this name happens to be rejected when samba is in the process
181 of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
182 or WORKGROUP(1b)) then we must stop being a master browser. sad.
184 **************************************************************************/
185 void name_unregister_work(struct subnet_record *d, char *name, int name_type)
187 struct work_record *work;
188 int remove_type_local = 0;
189 int remove_type_domain = 0;
190 int remove_type_logon = 0;
192 remove_netbios_name(d,name,name_type,SELF,ipzero);
194 if (!(work = find_workgroupstruct(d, name, False))) return;
196 /* work out what to unbecome, from the name type being removed */
198 if (ms_browser_name(name, name_type))
200 remove_type_local |= SV_TYPE_MASTER_BROWSER;
202 if (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
203 name_type == 0x1d)
205 remove_type_local |= SV_TYPE_MASTER_BROWSER;
207 if (AM_DOMMST(work) && strequal(name, lp_workgroup()) == 0 &&
208 name_type == 0x1b)
210 remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
212 if (AM_DOMMEM(work) && strequal(name, lp_workgroup()) == 0 &&
213 name_type == 0x1c)
215 remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
218 if (remove_type_local ) unbecome_local_master (d, work, remove_type_local );
219 if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain);
220 if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon );
224 /****************************************************************************
225 registers a name.
227 if the name being added is a SELF name, we must additionally check
228 whether to proceed to the next stage in samba becoming a master browser.
230 **************************************************************************/
231 void name_register_work(struct subnet_record *d, char *name, int name_type,
232 int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
234 enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
235 SELF : REGISTER;
237 if (source == SELF)
239 struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
241 add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
243 if (work)
245 if (work->mst_state != MST_POTENTIAL)
247 /* samba is working towards local master browser-ness.
248 initiate the next stage.
250 become_local_master(d, work);
251 return;
253 if (work->dom_state != DOMAIN_NONE)
255 /* samba is working towards domain master browser-ness.
256 initiate the next stage.
258 become_domain_master(d, work);
259 return;
261 if (work->log_state != LOGON_NONE)
263 /* samba is working towards domain master browser-ness.
264 initiate the next stage.
266 become_logon_server(d, work);
267 return;
274 /*******************************************************************
275 become the local master browser.
277 this is done in stages. note that this could take a while,
278 particularly on a broadcast subnet, as we have to wait for
279 the implicit registration of each name to be accepted.
281 as each name is successfully registered, become_local_master() is
282 called again, in order to initiate the next stage. see
283 dead_netbios_entry() - deals with implicit name registration
284 and response_name_reg() - deals with explicit registration
285 with a WINS server.
287 stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
288 stage 2: was MST_BACK - go to MST_MSB and register WORKGROUP(0x1d)
289 stage 3: was MST_MSB - go to MST_BROWSER and stay there
291 XXXX note: this code still does not cope with the distinction
292 between different types of nodes, particularly between M and P
293 nodes. that comes later.
295 ******************************************************************/
296 void become_local_master(struct subnet_record *d, struct work_record *work)
298 /* domain type must be limited to domain enum + server type. it must
299 not have SV_TYPE_SERVER or anything else with SERVER in it, else
300 clients get confused and start thinking this entry is a server
301 not a workgroup
303 uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
305 if (!work || !d) return;
307 DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
308 work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
310 switch (work->mst_state)
312 case MST_POTENTIAL: /* while we were nothing but a server... */
314 DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
315 work->mst_state = MST_BACK; /* ... an election win was successful */
317 work->ElectionCriterion |= 0x5;
319 /* update our server status */
320 work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
321 add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
323 /* add special browser name */
324 add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
326 /* DON'T do anything else after calling add_my_name_entry() */
327 break;
330 case MST_BACK: /* while nothing had happened except we won an election... */
332 DEBUG(3,("go to second stage: register as master browser\n"));
333 work->mst_state = MST_MSB; /* ... registering MSBROWSE was successful */
335 /* add server entry on successful registration of MSBROWSE */
336 add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
338 /* add master name */
339 add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
341 /* DON'T do anything else after calling add_my_name_entry() */
342 break;
345 case MST_MSB: /* while we were still only registered MSBROWSE state... */
347 DEBUG(3,("2nd stage complete: registered as master browser\n"));
348 work->mst_state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
350 /* update our server status */
351 work->ServerType |= SV_TYPE_MASTER_BROWSER;
352 add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
354 if (work->serverlist == NULL) /* no servers! */
356 /* ask all servers on our local net to announce to us */
357 /* XXXX OOPS! add_server_entry will always add one entry - our own. */
358 announce_request(work, d->bcast_ip);
360 break;
363 case MST_BROWSER:
365 /* don't have to do anything: just report success */
366 DEBUG(3,("3rd stage: become master browser!\n"));
368 break;
374 /*******************************************************************
375 become the domain master browser.
377 this is done in stages. note that this could take a while,
378 particularly on a broadcast subnet, as we have to wait for
379 the implicit registration of each name to be accepted.
381 as each name is successfully registered, become_domain_master() is
382 called again, in order to initiate the next stage. see
383 dead_netbios_entry() - deals with implicit name registration
384 and response_name_reg() - deals with explicit registration
385 with a WINS server.
387 stage 1: was DOMAIN_NONE - go to DOMAIN_MST
389 XXXX note: this code still does not cope with the distinction
390 between different types of nodes, particularly between M and P
391 nodes. that comes later.
393 ******************************************************************/
394 void become_domain_master(struct subnet_record *d, struct work_record *work)
396 /* domain type must be limited to domain enum + server type. it must
397 not have SV_TYPE_SERVER or anything else with SERVER in it, else
398 clients get confused and start thinking this entry is a server
399 not a workgroup
402 if (!work || !d) return;
404 DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
405 work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
407 switch (work->dom_state)
409 case DOMAIN_NONE: /* while we were nothing but a server... */
411 if (lp_domain_master())
413 DEBUG(3,("go to first stage: register <1b> name\n"));
414 work->dom_state = DOMAIN_WAIT;
416 /* XXXX the 0x1b is domain master browser name */
417 add_my_name_entry(d, lp_workgroup(),0x1b,nb_type|NB_ACTIVE|NB_GROUP);
419 /* DON'T do anything else after calling add_my_name_entry() */
420 break;
422 else
424 DEBUG(4,("samba not configured as a domain master.\n"));
427 break;
430 case DOMAIN_WAIT:
432 if (lp_domain_master())
434 work->dom_state = DOMAIN_MST; /* ... become domain master */
435 DEBUG(3,("domain first stage: register as domain member\n"));
437 /* update our server status */
438 work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
439 add_server_entry(d,work,myname,work->ServerType,0,
440 lp_serverstring(),True);
442 DEBUG(4,("samba is now a domain master\n"));
444 break;
446 else
448 DEBUG(4,("samba not configured as a domain master.\n"));
451 break;
454 case DOMAIN_MST:
456 /* don't have to do anything: just report success */
457 DEBUG(3,("domain second stage: there isn't one!\n"));
458 break;
464 /*******************************************************************
465 become a logon server.
466 ******************************************************************/
467 void become_logon_server(struct subnet_record *d, struct work_record *work)
469 if (!work || !d) return;
471 DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
472 work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
474 switch (work->log_state)
476 case LOGON_NONE: /* while we were nothing but a server... */
478 if (lp_domain_logons())
480 DEBUG(3,("go to first stage: register <1c> name\n"));
481 work->log_state = LOGON_WAIT;
483 /* XXXX the 0x1c is apparently something to do with domain logons */
484 add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
486 /* DON'T do anything else after calling add_my_name_entry() */
487 break;
490 DEBUG(4,("samba not configured as a logon master.\n"));
493 break;
496 case LOGON_WAIT:
498 if (lp_domain_logons())
500 work->log_state = LOGON_SRV; /* ... become logon server */
501 DEBUG(3,("logon second stage: register \n"));
503 /* update our server status */
504 work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
505 add_server_entry(d,work,myname,work->ServerType,0,
506 lp_serverstring(),True);
508 /* DON'T do anything else after calling add_my_name_entry() */
509 break;
511 else
513 DEBUG(4,("samba not configured as a logon server.\n"));
516 break;
519 case LOGON_SRV:
521 DEBUG(3,("logon third stage: there isn't one!\n"));
522 break;
529 /*******************************************************************
530 unbecome the local master browser. initates removal of necessary netbios
531 names, and tells the world that we are no longer a master browser.
533 XXXX this _should_ be used to demote to a backup master browser, without
534 going straight to non-master browser. another time.
536 ******************************************************************/
537 void unbecome_local_master(struct subnet_record *d, struct work_record *work,
538 int remove_type)
540 int new_server_type = work->ServerType;
542 /* can only remove master types with this function */
543 remove_type &= SV_TYPE_MASTER_BROWSER;
545 new_server_type &= ~remove_type;
547 if (remove_type)
549 DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
551 /* no longer a master browser of any sort */
553 work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
554 work->ElectionCriterion &= ~0x4;
555 work->mst_state = MST_POTENTIAL;
557 /* announce ourselves as no longer active as a master browser. */
558 announce_server(d, work, work->work_group, myname, 0, 0);
559 remove_name_entry(d,MSBROWSE ,0x01);
560 remove_name_entry(d,work->work_group,0x1d);
565 /*******************************************************************
566 unbecome the domain master browser. initates removal of necessary netbios
567 names, and tells the world that we are no longer a domain browser.
568 ******************************************************************/
569 void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
570 int remove_type)
572 int new_server_type = work->ServerType;
574 DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
576 /* can only remove master or domain types with this function */
577 remove_type &= SV_TYPE_DOMAIN_MASTER;
579 new_server_type &= ~remove_type;
581 if (remove_type)
583 /* no longer a domain master browser of any sort */
585 work->dom_state = DOMAIN_NONE;
587 /* announce ourselves as no longer active as a master browser. */
588 announce_server(d, work, work->work_group, myname, 0, 0);
589 remove_name_entry(d,work->work_group,0x1b);
594 /*******************************************************************
595 unbecome the logon server. initates removal of necessary netbios
596 names, and tells the world that we are no longer a logon server.
597 ******************************************************************/
598 void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
599 int remove_type)
601 int new_server_type = work->ServerType;
603 DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
605 /* can only remove master or domain types with this function */
606 remove_type &= SV_TYPE_DOMAIN_MEMBER;
608 new_server_type &= ~remove_type;
610 if (remove_type)
612 /* no longer a master browser of any sort */
614 work->log_state = LOGON_NONE;
616 /* announce ourselves as no longer active as a master browser. */
617 announce_server(d, work, work->work_group, myname, 0, 0);
618 remove_name_entry(d,work->work_group,0x1c);
623 /*******************************************************************
624 run the election
625 ******************************************************************/
626 void run_elections(time_t t)
628 static time_t lastime = 0;
630 struct subnet_record *d;
632 /* send election packets once a second */
633 if (lastime && t-lastime <= 0) return;
635 lastime = t;
637 for (d = subnetlist; d; d = d->next)
639 struct work_record *work;
640 for (work = d->workgrouplist; work; work = work->next)
642 if (work->RunningElection)
644 send_election(d,work->work_group, work->ElectionCriterion,
645 t-StartupTime,myname);
647 if (work->ElectionCount++ >= 4)
649 /* I won! now what :-) */
650 DEBUG(2,(">>> Won election on %s %s <<<\n",
651 work->work_group,inet_ntoa(d->bcast_ip)));
653 work->RunningElection = False;
654 work->mst_state = MST_POTENTIAL;
656 become_local_master(d, work);
664 /*******************************************************************
665 work out if I win an election
666 ******************************************************************/
667 static BOOL win_election(struct work_record *work,int version,uint32 criterion,
668 int timeup,char *name)
670 int mytimeup = time(NULL) - StartupTime;
671 uint32 mycriterion = work->ElectionCriterion;
673 DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
674 version,ELECTION_VERSION,
675 criterion,mycriterion,
676 timeup,mytimeup,
677 name,myname));
679 if (version > ELECTION_VERSION) return(False);
680 if (version < ELECTION_VERSION) return(True);
682 if (criterion > mycriterion) return(False);
683 if (criterion < mycriterion) return(True);
685 if (timeup > mytimeup) return(False);
686 if (timeup < mytimeup) return(True);
688 if (strcasecmp(myname,name) > 0) return(False);
690 return(True);
694 /*******************************************************************
695 process a election packet
697 An election dynamically decides who will be the master.
698 ******************************************************************/
699 void process_election(struct packet_struct *p,char *buf)
701 struct dgram_packet *dgram = &p->packet.dgram;
702 struct in_addr ip = dgram->header.source_ip;
703 struct subnet_record *d = find_subnet(ip);
704 int version = CVAL(buf,0);
705 uint32 criterion = IVAL(buf,1);
706 int timeup = IVAL(buf,5)/1000;
707 char *name = buf+13;
708 struct work_record *work;
710 if (!d) return;
712 if (ip_equal(d->bcast_ip,ipgrp)) {
713 DEBUG(3,("Unexpected election request from %s %s on WINS net\n",
714 name, inet_ntoa(p->ip)));
715 return;
718 name[15] = 0;
720 DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
721 name,inet_ntoa(p->ip),version,criterion,timeup));
723 if (same_context(dgram)) return;
725 for (work = d->workgrouplist; work; work = work->next)
727 if (!strequal(work->work_group, lp_workgroup()))
728 continue;
730 if (win_election(work, version,criterion,timeup,name)) {
731 if (!work->RunningElection) {
732 work->needelection = True;
733 work->ElectionCount=0;
734 work->mst_state = MST_POTENTIAL;
736 } else {
737 work->needelection = False;
739 if (work->RunningElection || AM_MASTER(work)) {
740 work->RunningElection = False;
741 DEBUG(3,(">>> Lost election on %s %s <<<\n",
742 work->work_group,inet_ntoa(d->bcast_ip)));
743 if (AM_MASTER(work))
744 unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
751 /****************************************************************************
752 checks whether a browser election is to be run on any workgroup
754 this function really ought to return the time between election
755 packets (which depends on whether samba intends to be a domain
756 master or a master browser) in milliseconds.
758 ***************************************************************************/
759 BOOL check_elections(void)
761 struct subnet_record *d;
762 BOOL run_any_election = False;
764 for (d = subnetlist; d; d = d->next)
766 struct work_record *work;
767 for (work = d->workgrouplist; work; work = work->next)
769 run_any_election |= work->RunningElection;
771 if (work->needelection && !work->RunningElection)
773 DEBUG(3,(">>> Starting election on %s %s <<<\n",
774 work->work_group,inet_ntoa(d->bcast_ip)));
775 work->ElectionCount = 0;
776 work->RunningElection = True;
777 work->needelection = False;
781 return run_any_election;