2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1995
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.
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
31 extern int ClientDGRAM
;
33 extern int DEBUGLEVEL
;
36 extern pstring myname
;
37 extern struct in_addr ipzero
;
39 /* machine comment for host announcements */
40 extern pstring ServerComment
;
42 /* here are my election parameters */
44 extern time_t StartupTime
;
46 extern struct subnet_record
*subnetlist
;
49 /*******************************************************************
50 occasionally check to see if the master browser is around
51 ******************************************************************/
52 void check_master_browser(void)
54 static time_t lastrun
=0;
55 time_t t
= time(NULL
);
56 struct subnet_record
*d
;
58 if (!lastrun
) lastrun
= t
;
59 if (t
< lastrun
+ CHECK_TIME_MST_BROWSE
* 60)
65 for (d
= subnetlist
; d
; d
= d
->next
)
67 struct work_record
*work
;
69 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
71 /* if we are not the browse master of a workgroup, and we can't
72 find a browser on the subnet, do something about it. */
76 queue_netbios_packet(d
,ClientNMB
,NMB_QUERY
,NAME_QUERY_MST_CHK
,
77 work
->work_group
,0x1d,0,0,
78 True
,False
,d
->bcast_ip
);
85 /*******************************************************************
86 what to do if a master browser DOESN't exist
87 ******************************************************************/
88 void browser_gone(char *work_name
, struct in_addr ip
)
90 struct subnet_record
*d
= find_subnet(ip
);
91 struct work_record
*work
= find_workgroupstruct(d
, work_name
, False
);
93 if (!work
|| !d
) return;
95 if (strequal(work
->work_group
, lp_workgroup()) &&
96 ismybcast(d
->bcast_ip
))
99 DEBUG(2,("Forcing election on %s %s\n",
100 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
102 /* we can attempt to become master browser */
103 work
->needelection
= True
;
107 /* XXXX note: this will delete entries that have been added in by
108 lmhosts as well. a flag to ensure that these are not deleted may
111 /* workgroup with no master browser is not the default workgroup:
112 it's also not on our subnet. therefore delete it: it can be
113 recreated dynamically */
115 send_election(d
, work
->work_group
, 0, 0, myname
);
116 remove_workgroup(d
, work
);
121 /****************************************************************************
122 send an election packet
123 **************************************************************************/
124 void send_election(struct subnet_record
*d
, char *group
,uint32 criterion
,
125 int timeup
,char *name
)
132 DEBUG(2,("Sending election to %s for workgroup %s\n",
133 inet_ntoa(d
->bcast_ip
),group
));
135 bzero(outbuf
,sizeof(outbuf
));
137 CVAL(p
,0) = 8; /* election */
140 CVAL(p
,0) = (criterion
== 0 && timeup
== 0) ? 0 : ELECTION_VERSION
;
141 SIVAL(p
,1,criterion
);
142 SIVAL(p
,5,timeup
*1000); /* ms - despite the spec */
146 p
= skip_string(p
,1);
148 send_mailslot_reply(BROWSE_MAILSLOT
,ClientDGRAM
,outbuf
,PTR_DIFF(p
,outbuf
),
149 name
,group
,0,0x1e,d
->bcast_ip
,*iface_ip(d
->bcast_ip
));
153 /****************************************************************************
154 un-register a SELF name that got rejected.
156 if this name happens to be rejected when samba is in the process
157 of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
158 or WORKGROUP(1b)) then we must stop being a master browser. sad.
160 **************************************************************************/
161 void name_unregister_work(struct subnet_record
*d
, char *name
, int name_type
)
163 struct work_record
*work
;
165 remove_netbios_name(d
,name
,name_type
,SELF
,ipzero
);
167 if (!(work
= find_workgroupstruct(d
, name
, False
))) return;
169 if (special_browser_name(name
, name_type
) ||
170 (AM_MASTER(work
) && strequal(name
, lp_workgroup()) == 0 &&
171 (name_type
== 0x1d || name_type
== 0x1b)))
175 if (special_browser_name(name
, name_type
))
176 remove_type
= SV_TYPE_MASTER_BROWSER
|SV_TYPE_DOMAIN_MASTER
;
177 if (name_type
== 0x1d)
178 remove_type
= SV_TYPE_MASTER_BROWSER
;
179 if (name_type
== 0x1b)
180 remove_type
= SV_TYPE_DOMAIN_MASTER
;
182 become_nonmaster(d
, work
, remove_type
);
187 /****************************************************************************
190 if the name being added is a SELF name, we must additionally check
191 whether to proceed to the next stage in samba becoming a master browser.
193 **************************************************************************/
194 void name_register_work(struct subnet_record
*d
, char *name
, int name_type
,
195 int nb_flags
, time_t ttl
, struct in_addr ip
, BOOL bcast
)
197 enum name_source source
= ismyip(ip
) ? SELF
: REGISTER
;
201 struct work_record
*work
= find_workgroupstruct(d
, lp_workgroup(), False
);
203 if (work
&& work
->state
!= MST_NONE
)
205 /* samba is in the process of working towards master browser-ness.
206 initiate the next stage.
208 become_master(d
, work
);
211 add_netbios_entry(d
,name
,name_type
,nb_flags
,ttl
,source
,ip
,True
,!bcast
);
215 /*******************************************************************
216 become the master browser.
218 this is done in stages. note that this could take a while,
219 particularly on a broadcast subnet, as we have to wait for
220 the implicit registration of each name to be accepted.
222 as each name is successfully registered, become_master() is
223 called again, in order to initiate the next stage. see
224 dead_netbios_entry() - deals with implicit name registration
225 and response_name_reg() - deals with explicit registration
228 stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1.
229 stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d)
230 stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b)
231 stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...)
233 XXXX note: this code still does not cope with the distinction
234 between different types of nodes, particularly between M and P
235 nodes. that comes later.
237 ******************************************************************/
238 void become_master(struct subnet_record
*d
, struct work_record
*work
)
240 uint32 domain_type
= SV_TYPE_DOMAIN_ENUM
|SV_TYPE_SERVER_UNIX
|0x00400000;
244 DEBUG(2,("Becoming master for %s (stage %d)",work
->work_group
,work
->state
));
248 case MST_NONE
: /* while we were nothing but a server... */
250 work
->state
= MST_WON
; /* election win was successful */
252 work
->ElectionCriterion
|= 0x5;
254 /* update our server status */
255 work
->ServerType
&= ~SV_TYPE_POTENTIAL_BROWSER
;
256 add_server_entry(d
,work
,myname
,work
->ServerType
,0,ServerComment
,True
);
258 DEBUG(2,("first stage: register ^1^2__MSBROWSE__^2^1\n"));
260 /* add special browser name */
261 add_my_name_entry(d
,MSBROWSE
,0x01,NB_ACTIVE
|NB_GROUP
);
265 case MST_WON
: /* while nothing had happened except we won an election... */
267 work
->state
= MST_MSB
; /* registering MSBROWSE was successful */
269 /* add server entry on successful registration of MSBROWSE */
270 add_server_entry(d
,work
,work
->work_group
,domain_type
,0,myname
,True
);
272 DEBUG(2,("second stage: register as master browser\n"));
274 /* add master name */
275 add_my_name_entry(d
,work
->work_group
,0x1d,NB_ACTIVE
);
279 case MST_MSB
: /* while we were still only registered MSBROWSE state */
281 work
->state
= MST_BROWSER
; /* registering WORKGROUP(1d) was successful */
283 /* update our server status */
284 work
->ServerType
|= SV_TYPE_MASTER_BROWSER
;
285 add_server_entry(d
,work
,myname
,work
->ServerType
,0,ServerComment
,True
);
287 if (d
->my_interface
&& work
->serverlist
== NULL
) /* no servers! */
289 /* ask all servers on our local net to announce to us */
290 announce_request(work
, d
->bcast_ip
);
293 if (lp_domain_master())
295 DEBUG(2,("third stage: register as domain master\n"));
296 /* add domain master name */
297 add_my_name_entry(d
,work
->work_group
,0x1b,NB_ACTIVE
);
302 case MST_BROWSER
: /* while we were still a master browser... */
304 work
->state
= MST_DOMAIN
; /* registering WORKGROUP(1b) was successful */
306 /* update our server status */
307 if (lp_domain_master())
309 work
->ServerType
|= SV_TYPE_DOMAIN_MASTER
;
311 if (lp_domain_logons())
313 work
->ServerType
|= SV_TYPE_DOMAIN_CTRL
;
314 work
->ServerType
|= SV_TYPE_DOMAIN_MEMBER
;
316 DEBUG(2,("fourth stage: samba is now a domain master.\n"));
317 add_server_entry(d
,work
,myname
,work
->ServerType
,0,ServerComment
,True
);
324 /* nothing else to become, at the moment: we are top-dog. */
325 DEBUG(2,("fifth stage: there isn't one yet!\n"));
332 /*******************************************************************
333 unbecome the master browser. initates removal of necessary netbios
334 names, and tells the world that we are no longer a master browser.
335 ******************************************************************/
336 void become_nonmaster(struct subnet_record
*d
, struct work_record
*work
,
339 int new_server_type
= work
->ServerType
;
341 DEBUG(2,("Becoming non-master for %s\n",work
->work_group
));
343 /* can only remove master or domain types with this function */
344 remove_type
&= ~(SV_TYPE_MASTER_BROWSER
|SV_TYPE_DOMAIN_MASTER
);
346 /* unbecome a master browser; unbecome a domain master, too :-( */
347 if (remove_type
& SV_TYPE_MASTER_BROWSER
)
348 remove_type
|= SV_TYPE_DOMAIN_MASTER
;
350 new_server_type
&= ~remove_type
;
352 if (!(new_server_type
& (SV_TYPE_MASTER_BROWSER
|SV_TYPE_DOMAIN_MASTER
)))
354 /* no longer a master browser of any sort */
356 work
->ServerType
|= SV_TYPE_POTENTIAL_BROWSER
;
357 work
->ElectionCriterion
&= ~0x4;
358 work
->state
= MST_NONE
;
360 /* announce ourselves as no longer active as a master browser. */
361 announce_server(d
, work
, work
->work_group
, myname
, 0, 0);
362 remove_name_entry(d
,MSBROWSE
,0x01);
365 work
->ServerType
= new_server_type
;
367 if (!(work
->ServerType
& SV_TYPE_DOMAIN_MASTER
))
369 if (work
->state
== MST_DOMAIN
)
370 work
->state
= MST_BROWSER
;
371 remove_name_entry(d
,work
->work_group
,0x1b);
375 if (!(work
->ServerType
& SV_TYPE_DOMAIN_MASTER
))
377 if (work
->state
>= MST_BROWSER
)
378 work
->state
= MST_NONE
;
379 remove_name_entry(d
,work
->work_group
,0x1d);
384 /*******************************************************************
386 ******************************************************************/
387 void run_elections(void)
389 time_t t
= time(NULL
);
390 static time_t lastime
= 0;
392 struct subnet_record
*d
;
394 /* send election packets once a second */
395 if (lastime
&& t
-lastime
<= 0) return;
399 for (d
= subnetlist
; d
; d
= d
->next
)
401 struct work_record
*work
;
402 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
404 if (work
->RunningElection
)
406 send_election(d
,work
->work_group
, work
->ElectionCriterion
,
407 t
-StartupTime
,myname
);
409 if (work
->ElectionCount
++ >= 4)
411 /* I won! now what :-) */
412 DEBUG(2,(">>> Won election on %s %s <<<\n",
413 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
415 work
->RunningElection
= False
;
416 work
->state
= MST_NONE
;
418 become_master(d
, work
);
426 /*******************************************************************
427 work out if I win an election
428 ******************************************************************/
429 static BOOL
win_election(struct work_record
*work
,int version
,uint32 criterion
,
430 int timeup
,char *name
)
432 time_t t
= time(NULL
);
434 if (version
> ELECTION_VERSION
) return(False
);
435 if (version
< ELECTION_VERSION
) return(True
);
437 mycriterion
= work
->ElectionCriterion
;
439 if (criterion
> mycriterion
) return(False
);
440 if (criterion
< mycriterion
) return(True
);
442 if (timeup
> (t
- StartupTime
)) return(False
);
443 if (timeup
< (t
- StartupTime
)) return(True
);
445 if (strcasecmp(myname
,name
) > 0) return(False
);
451 /*******************************************************************
452 process a election packet
454 An election dynamically decides who will be the master.
455 ******************************************************************/
456 void process_election(struct packet_struct
*p
,char *buf
)
458 struct dgram_packet
*dgram
= &p
->packet
.dgram
;
459 struct in_addr ip
= dgram
->header
.source_ip
;
460 struct subnet_record
*d
= find_subnet(ip
);
461 int version
= CVAL(buf
,0);
462 uint32 criterion
= IVAL(buf
,1);
463 int timeup
= IVAL(buf
,5)/1000;
465 struct work_record
*work
;
471 DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n",
472 name
,version
,criterion
,timeup
));
474 if (same_context(dgram
)) return;
476 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
478 if (listening_name(work
, &dgram
->dest_name
) &&
479 strequal(work
->work_group
, lp_workgroup()) &&
482 if (win_election(work
, version
,criterion
,timeup
,name
))
484 if (!work
->RunningElection
)
486 work
->needelection
= True
;
487 work
->ElectionCount
=0;
488 work
->state
= MST_NONE
;
493 work
->needelection
= False
;
495 if (work
->RunningElection
)
497 work
->RunningElection
= False
;
498 DEBUG(3,(">>> Lost election on %s %s <<<\n",
499 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
501 /* if we are the master then remove our masterly names */
504 become_nonmaster(d
, work
,
505 SV_TYPE_MASTER_BROWSER
|SV_TYPE_DOMAIN_MASTER
);
514 /****************************************************************************
515 checks whether a browser election is to be run on any workgroup
516 ***************************************************************************/
517 BOOL
check_elections(void)
519 struct subnet_record
*d
;
520 BOOL run_any_election
= False
;
522 for (d
= subnetlist
; d
; d
= d
->next
)
524 struct work_record
*work
;
525 for (work
= d
->workgrouplist
; work
; work
= work
->next
)
527 run_any_election
|= work
->RunningElection
;
529 if (work
->needelection
&& !work
->RunningElection
)
531 DEBUG(3,(">>> Starting election on %s %s <<<\n",
532 work
->work_group
,inet_ntoa(d
->bcast_ip
)));
533 work
->ElectionCount
= 0;
534 work
->RunningElection
= True
;
535 work
->needelection
= False
;
539 return run_any_election
;