2 Unix SMB/Netbios implementation.
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
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.
37 extern int ClientDGRAM
;
39 extern int DEBUGLEVEL
;
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) return;
70 for (d
= subnetlist
; d
; d
= d
->next
)
72 struct work_record
*work
;
74 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
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
);
92 /* if we are not the browse master of a workgroup,
93 and we can't find a browser on the subnet, do
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
))
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
;
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
)
155 DEBUG(2,("Sending election to %s for workgroup %s\n",
156 inet_ntoa(d
->bcast_ip
),group
));
158 bzero(outbuf
,sizeof(outbuf
));
160 CVAL(p
,0) = ANN_Election
; /* election */
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 */
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 &&
205 remove_type_local
|= SV_TYPE_MASTER_BROWSER
;
207 if (AM_DOMMST(work
) && strequal(name
, lp_workgroup()) == 0 &&
210 remove_type_domain
|= SV_TYPE_DOMAIN_MASTER
;
212 if (AM_DOMMEM(work
) && strequal(name
, lp_workgroup()) == 0 &&
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 /****************************************************************************
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
)) ?
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
);
245 int add_type_local
= False
;
246 int add_type_domain
= False
;
247 int add_type_logon
= False
;
249 /* work out what to become, from the name type being added */
251 if (ms_browser_name(name
, name_type
))
253 add_type_local
= True
;
255 if (strequal(name
, lp_workgroup()) == 0 && name_type
== 0x1d)
257 add_type_local
= True
;
259 if (strequal(name
, lp_workgroup()) == 0 && name_type
== 0x1b)
261 add_type_domain
= True
;
263 if (strequal(name
, lp_workgroup()) == 0 && name_type
== 0x1c)
265 add_type_logon
= True
;
268 if (add_type_local
) become_local_master (d
, work
);
269 if (add_type_domain
) become_domain_master(d
, work
);
270 if (add_type_logon
) become_logon_server (d
, work
);
276 /*******************************************************************
277 become the local master browser.
279 this is done in stages. note that this could take a while,
280 particularly on a broadcast subnet, as we have to wait for
281 the implicit registration of each name to be accepted.
283 as each name is successfully registered, become_local_master() is
284 called again, in order to initiate the next stage. see
285 dead_netbios_entry() - deals with implicit name registration
286 and response_name_reg() - deals with explicit registration
289 stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
290 stage 2: was MST_BACK - go to MST_MSB and register WORKGROUP(0x1d)
291 stage 3: was MST_MSB - go to MST_BROWSER and stay there
293 XXXX note: this code still does not cope with the distinction
294 between different types of nodes, particularly between M and P
295 nodes. that comes later.
297 ******************************************************************/
298 void become_local_master(struct subnet_record
*d
, struct work_record
*work
)
300 /* domain type must be limited to domain enum + server type. it must
301 not have SV_TYPE_SERVER or anything else with SERVER in it, else
302 clients get confused and start thinking this entry is a server
305 uint32 domain_type
= SV_TYPE_DOMAIN_ENUM
|SV_TYPE_NT
;
307 if (!work
|| !d
) return;
309 DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
310 work
->work_group
,inet_ntoa(d
->bcast_ip
),work
->mst_state
));
312 switch (work
->mst_state
)
314 case MST_POTENTIAL
: /* while we were nothing but a server... */
316 DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
317 work
->mst_state
= MST_BACK
; /* ... an election win was successful */
319 work
->ElectionCriterion
|= 0x5;
321 /* update our server status */
322 work
->ServerType
&= ~SV_TYPE_POTENTIAL_BROWSER
;
323 add_server_entry(d
,work
,myname
,work
->ServerType
,0,lp_serverstring(),True
);
325 /* add special browser name */
326 add_my_name_entry(d
,MSBROWSE
,0x01,nb_type
|NB_ACTIVE
|NB_GROUP
);
328 /* DON'T do anything else after calling add_my_name_entry() */
332 case MST_BACK
: /* while nothing had happened except we won an election... */
334 DEBUG(3,("go to second stage: register as master browser\n"));
335 work
->mst_state
= MST_MSB
; /* ... registering MSBROWSE was successful */
337 /* add server entry on successful registration of MSBROWSE */
338 add_server_entry(d
,work
,work
->work_group
,domain_type
,0,myname
,True
);
340 /* add master name */
341 add_my_name_entry(d
,work
->work_group
,0x1d,nb_type
|NB_ACTIVE
);
343 /* DON'T do anything else after calling add_my_name_entry() */
347 case MST_MSB
: /* while we were still only registered MSBROWSE state... */
349 DEBUG(3,("2nd stage complete: registered as master browser\n"));
350 work
->mst_state
= MST_BROWSER
; /* ... registering WORKGROUP(1d) succeeded */
352 /* update our server status */
353 work
->ServerType
|= SV_TYPE_MASTER_BROWSER
;
354 add_server_entry(d
,work
,myname
,work
->ServerType
,0,lp_serverstring(),True
);
356 if (work
->serverlist
== NULL
) /* no servers! */
358 /* ask all servers on our local net to announce to us */
359 /* XXXX OOPS! add_server_entry will always add one entry - our own. */
360 announce_request(work
, d
->bcast_ip
);
367 /* don't have to do anything: just report success */
368 DEBUG(3,("3rd stage: become master browser!\n"));
376 /*******************************************************************
377 become the domain master browser.
379 this is done in stages. note that this could take a while,
380 particularly on a broadcast subnet, as we have to wait for
381 the implicit registration of each name to be accepted.
383 as each name is successfully registered, become_domain_master() is
384 called again, in order to initiate the next stage. see
385 dead_netbios_entry() - deals with implicit name registration
386 and response_name_reg() - deals with explicit registration
389 stage 1: was DOMAIN_NONE - go to DOMAIN_MST
391 XXXX note: this code still does not cope with the distinction
392 between different types of nodes, particularly between M and P
393 nodes. that comes later.
395 ******************************************************************/
396 void become_domain_master(struct subnet_record
*d
, struct work_record
*work
)
398 /* domain type must be limited to domain enum + server type. it must
399 not have SV_TYPE_SERVER or anything else with SERVER in it, else
400 clients get confused and start thinking this entry is a server
404 if (!work
|| !d
) return;
406 DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
407 work
->work_group
,inet_ntoa(d
->bcast_ip
),work
->dom_state
));
409 switch (work
->dom_state
)
411 case DOMAIN_NONE
: /* while we were nothing but a server... */
413 if (lp_domain_master())
415 DEBUG(3,("go to first stage: register <1b> name\n"));
416 work
->dom_state
= DOMAIN_WAIT
;
418 /* XXXX the 0x1b is domain master browser name */
419 add_my_name_entry(d
, lp_workgroup(),0x1b,nb_type
|NB_ACTIVE
|NB_GROUP
);
421 /* DON'T do anything else after calling add_my_name_entry() */
426 DEBUG(4,("samba not configured as a domain master.\n"));
434 if (lp_domain_master())
436 work
->dom_state
= DOMAIN_MST
; /* ... become domain master */
437 DEBUG(3,("domain first stage: register as domain member\n"));
439 /* update our server status */
440 work
->ServerType
|= SV_TYPE_NT
|SV_TYPE_DOMAIN_MASTER
;
441 add_server_entry(d
,work
,myname
,work
->ServerType
,0,
442 lp_serverstring(),True
);
444 DEBUG(4,("samba is now a domain master\n"));
450 DEBUG(4,("samba not configured as a domain master.\n"));
458 /* don't have to do anything: just report success */
459 DEBUG(3,("domain second stage: there isn't one!\n"));
466 /*******************************************************************
467 become a logon server.
468 ******************************************************************/
469 void become_logon_server(struct subnet_record
*d
, struct work_record
*work
)
471 if (!work
|| !d
) return;
473 DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
474 work
->work_group
,inet_ntoa(d
->bcast_ip
),work
->log_state
));
476 switch (work
->log_state
)
478 case LOGON_NONE
: /* while we were nothing but a server... */
480 if (lp_domain_logons())
482 DEBUG(3,("go to first stage: register <1c> name\n"));
483 work
->log_state
= LOGON_WAIT
;
485 /* XXXX the 0x1c is apparently something to do with domain logons */
486 add_my_name_entry(d
, lp_workgroup(),0x1c,nb_type
|NB_ACTIVE
|NB_GROUP
);
488 /* DON'T do anything else after calling add_my_name_entry() */
492 DEBUG(4,("samba not configured as a logon master.\n"));
500 if (lp_domain_logons())
502 work
->log_state
= LOGON_SRV
; /* ... become logon server */
503 DEBUG(3,("logon second stage: register \n"));
505 /* update our server status */
506 work
->ServerType
|= SV_TYPE_NT
|SV_TYPE_DOMAIN_MEMBER
;
507 add_server_entry(d
,work
,myname
,work
->ServerType
,0,
508 lp_serverstring(),True
);
510 /* DON'T do anything else after calling add_my_name_entry() */
515 DEBUG(4,("samba not configured as a logon server.\n"));
523 DEBUG(3,("logon third stage: there isn't one!\n"));
531 /*******************************************************************
532 unbecome the local master browser. initates removal of necessary netbios
533 names, and tells the world that we are no longer a master browser.
535 XXXX this _should_ be used to demote to a backup master browser, without
536 going straight to non-master browser. another time.
538 ******************************************************************/
539 void unbecome_local_master(struct subnet_record
*d
, struct work_record
*work
,
542 int new_server_type
= work
->ServerType
;
544 /* can only remove master types with this function */
545 remove_type
&= SV_TYPE_MASTER_BROWSER
;
547 new_server_type
&= ~remove_type
;
551 DEBUG(2,("Becoming local non-master for %s\n",work
->work_group
));
553 /* no longer a master browser of any sort */
555 work
->ServerType
|= SV_TYPE_POTENTIAL_BROWSER
;
556 work
->ElectionCriterion
&= ~0x4;
557 work
->mst_state
= MST_POTENTIAL
;
559 /* announce ourselves as no longer active as a master browser. */
560 announce_server(d
, work
, work
->work_group
, myname
, 0, 0);
561 remove_name_entry(d
,MSBROWSE
,0x01);
562 remove_name_entry(d
,work
->work_group
,0x1d);
567 /*******************************************************************
568 unbecome the domain master browser. initates removal of necessary netbios
569 names, and tells the world that we are no longer a domain browser.
570 ******************************************************************/
571 void unbecome_domain_master(struct subnet_record
*d
, struct work_record
*work
,
574 int new_server_type
= work
->ServerType
;
576 DEBUG(2,("Becoming domain non-master for %s\n",work
->work_group
));
578 /* can only remove master or domain types with this function */
579 remove_type
&= SV_TYPE_DOMAIN_MASTER
;
581 new_server_type
&= ~remove_type
;
585 /* no longer a domain master browser of any sort */
587 work
->dom_state
= DOMAIN_NONE
;
589 /* announce ourselves as no longer active as a master browser. */
590 announce_server(d
, work
, work
->work_group
, myname
, 0, 0);
591 remove_name_entry(d
,work
->work_group
,0x1b);
596 /*******************************************************************
597 unbecome the logon server. initates removal of necessary netbios
598 names, and tells the world that we are no longer a logon server.
599 ******************************************************************/
600 void unbecome_logon_server(struct subnet_record
*d
, struct work_record
*work
,
603 int new_server_type
= work
->ServerType
;
605 DEBUG(2,("Becoming logon non-server for %s\n",work
->work_group
));
607 /* can only remove master or domain types with this function */
608 remove_type
&= SV_TYPE_DOMAIN_MEMBER
;
610 new_server_type
&= ~remove_type
;
614 /* no longer a master browser of any sort */
616 work
->log_state
= LOGON_NONE
;
618 /* announce ourselves as no longer active as a master browser. */
619 announce_server(d
, work
, work
->work_group
, myname
, 0, 0);
620 remove_name_entry(d
,work
->work_group
,0x1c);
625 /*******************************************************************
627 ******************************************************************/
628 void run_elections(time_t t
)
630 static time_t lastime
= 0;
632 struct subnet_record
*d
;
634 /* send election packets once a second */
635 if (lastime
&& t
-lastime
<= 0) return;
639 for (d
= subnetlist
; d
; d
= d
->next
)
641 struct work_record
*work
;
642 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
644 if (work
->RunningElection
)
646 send_election(d
,work
->work_group
, work
->ElectionCriterion
,
647 t
-StartupTime
,myname
);
649 if (work
->ElectionCount
++ >= 4)
651 /* I won! now what :-) */
652 DEBUG(2,(">>> Won election on %s %s <<<\n",
653 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
655 work
->RunningElection
= False
;
656 work
->mst_state
= MST_POTENTIAL
;
658 become_local_master(d
, work
);
666 /*******************************************************************
667 work out if I win an election
668 ******************************************************************/
669 static BOOL
win_election(struct work_record
*work
,int version
,uint32 criterion
,
670 int timeup
,char *name
)
672 int mytimeup
= time(NULL
) - StartupTime
;
673 uint32 mycriterion
= work
->ElectionCriterion
;
675 DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
676 version
,ELECTION_VERSION
,
677 criterion
,mycriterion
,
681 if (version
> ELECTION_VERSION
) return(False
);
682 if (version
< ELECTION_VERSION
) return(True
);
684 if (criterion
> mycriterion
) return(False
);
685 if (criterion
< mycriterion
) return(True
);
687 if (timeup
> mytimeup
) return(False
);
688 if (timeup
< mytimeup
) return(True
);
690 if (strcasecmp(myname
,name
) > 0) return(False
);
696 /*******************************************************************
697 process a election packet
699 An election dynamically decides who will be the master.
700 ******************************************************************/
701 void process_election(struct packet_struct
*p
,char *buf
)
703 struct dgram_packet
*dgram
= &p
->packet
.dgram
;
704 struct in_addr ip
= dgram
->header
.source_ip
;
705 struct subnet_record
*d
= find_subnet(ip
);
706 int version
= CVAL(buf
,0);
707 uint32 criterion
= IVAL(buf
,1);
708 int timeup
= IVAL(buf
,5)/1000;
710 struct work_record
*work
;
714 if (ip_equal(d
->bcast_ip
,ipgrp
)) {
715 DEBUG(3,("Unexpected election request from %s %s on WINS net\n",
716 name
, inet_ntoa(p
->ip
)));
722 DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
723 name
,inet_ntoa(p
->ip
),version
,criterion
,timeup
));
725 if (same_context(dgram
)) return;
727 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
729 if (!strequal(work
->work_group
, lp_workgroup()))
732 if (win_election(work
, version
,criterion
,timeup
,name
)) {
733 if (!work
->RunningElection
) {
734 work
->needelection
= True
;
735 work
->ElectionCount
=0;
736 work
->mst_state
= MST_POTENTIAL
;
739 work
->needelection
= False
;
741 if (work
->RunningElection
|| AM_MASTER(work
)) {
742 work
->RunningElection
= False
;
743 DEBUG(3,(">>> Lost election on %s %s <<<\n",
744 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
746 unbecome_local_master(d
, work
, SV_TYPE_MASTER_BROWSER
);
753 /****************************************************************************
754 checks whether a browser election is to be run on any workgroup
756 this function really ought to return the time between election
757 packets (which depends on whether samba intends to be a domain
758 master or a master browser) in milliseconds.
760 ***************************************************************************/
761 BOOL
check_elections(void)
763 struct subnet_record
*d
;
764 BOOL run_any_election
= False
;
766 for (d
= subnetlist
; d
; d
= d
->next
)
768 struct work_record
*work
;
769 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
771 run_any_election
|= work
->RunningElection
;
773 if (work
->needelection
&& !work
->RunningElection
)
775 DEBUG(3,(">>> Starting election on %s %s <<<\n",
776 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
777 work
->ElectionCount
= 0;
778 work
->RunningElection
= True
;
779 work
->needelection
= False
;
783 return run_any_election
;