Samba Shared Repository - branch v3-3-test updated - release-3-2-0pre2-2279-gd077ef6
[Samba.git] / source / nmbd / nmbd_become_lmb.c
blob8aedd2c4785d0823ca081f3d52ad26195af8576d
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
25 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
27 /*******************************************************************
28 Utility function to add a name to the unicast subnet, or add in
29 our IP address if it already exists.
30 ******************************************************************/
32 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
33 struct nmb_name *nmbname, uint16 nb_type )
35 unstring name;
36 struct name_record *namerec;
38 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
39 pull_ascii_nstring(name, sizeof(name), nmbname->name);
40 /* The name needs to be created on the unicast subnet. */
41 (void)add_name_to_subnet( unicast_subnet, name,
42 nmbname->name_type, nb_type,
43 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
44 } else {
45 /* The name already exists on the unicast subnet. Add our local
46 IP for the given broadcast subnet to the name. */
47 add_ip_to_name_record( namerec, subrec->myip);
51 /*******************************************************************
52 Utility function to remove a name from the unicast subnet.
53 ******************************************************************/
55 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
56 struct nmb_name *nmbname )
58 struct name_record *namerec;
60 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
61 /* Remove this broadcast subnet IP address from the name. */
62 remove_ip_from_name_record( namerec, subrec->myip);
63 if(namerec->data.num_ips == 0)
64 remove_name_from_namelist( unicast_subnet, namerec);
68 /*******************************************************************
69 Utility function always called to set our workgroup and server
70 state back to potential browser, or none.
71 ******************************************************************/
73 static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
74 bool force_new_election )
76 struct work_record *work;
77 struct server_record *servrec;
78 struct nmb_name nmbname;
80 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
81 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
82 subnet %s.\n", workgroup_name, subrec->subnet_name ));
83 return;
86 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
87 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
88 in workgroup %s on subnet %s\n",
89 global_myname(), work->work_group, subrec->subnet_name));
90 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
91 return;
94 /* Update our server status - remove any master flag and replace
95 it with the potential browser flag. */
96 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
97 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
99 /* Tell the namelist writer to write out a change. */
100 subrec->work_changed = True;
102 /* Reset our election flags. */
103 work->ElectionCriterion &= ~0x4;
105 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
107 /* Forget who the local master browser was for
108 this workgroup. */
110 set_workgroup_local_master_browser_name( work, "");
113 * Ensure the IP address of this subnet is not registered as one
114 * of the IP addresses of the WORKGROUP<1d> name on the unicast
115 * subnet. This undoes what we did below when we became a local
116 * master browser.
119 make_nmb_name(&nmbname, work->work_group, 0x1d);
121 remove_permanent_name_from_unicast( subrec, &nmbname);
123 if(force_new_election)
124 work->needelection = True;
127 /*******************************************************************
128 Unbecome the local master browser name release success function.
129 ******************************************************************/
131 static void unbecome_local_master_success(struct subnet_record *subrec,
132 struct userdata_struct *userdata,
133 struct nmb_name *released_name,
134 struct in_addr released_ip)
136 bool force_new_election = False;
137 unstring relname;
139 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
141 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
142 nmb_namestr(released_name)));
144 /* Now reset the workgroup and server state. */
145 pull_ascii_nstring(relname, sizeof(relname), released_name->name);
146 reset_workgroup_state( subrec, relname, force_new_election );
148 if( DEBUGLVL( 0 ) ) {
149 dbgtext( "*****\n\n" );
150 dbgtext( "Samba name server %s ", global_myname() );
151 dbgtext( "has stopped being a local master browser " );
152 dbgtext( "for workgroup %s ", relname );
153 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
158 /*******************************************************************
159 Unbecome the local master browser name release fail function.
160 ******************************************************************/
162 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
163 struct nmb_name *fail_name)
165 struct name_record *namerec;
166 struct userdata_struct *userdata = rrec->userdata;
167 bool force_new_election = False;
168 unstring failname;
170 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
172 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
173 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
175 /* Do it anyway. */
176 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
177 if(namerec)
178 remove_name_from_namelist(subrec, namerec);
180 /* Now reset the workgroup and server state. */
181 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
182 reset_workgroup_state( subrec, failname, force_new_election );
184 if( DEBUGLVL( 0 ) ) {
185 dbgtext( "*****\n\n" );
186 dbgtext( "Samba name server %s ", global_myname() );
187 dbgtext( "has stopped being a local master browser " );
188 dbgtext( "for workgroup %s ", failname );
189 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
193 /*******************************************************************
194 Utility function to remove the WORKGROUP<1d> name.
195 ******************************************************************/
197 static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
198 bool force_new_election)
200 struct nmb_name nmbname;
201 struct name_record *namerec;
203 make_nmb_name(&nmbname, workgroup_name, 0x1d);
204 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
205 struct userdata_struct *userdata;
206 size_t size = sizeof(struct userdata_struct) + sizeof(bool);
208 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
209 DEBUG(0,("release_1d_name: malloc fail.\n"));
210 return;
213 userdata->copy_fn = NULL;
214 userdata->free_fn = NULL;
215 userdata->userdata_len = sizeof(bool);
216 memcpy((char *)userdata->data, &force_new_election, sizeof(bool));
218 release_name(subrec, namerec,
219 unbecome_local_master_success,
220 unbecome_local_master_fail,
221 userdata);
223 zero_free(userdata, size);
227 /*******************************************************************
228 Unbecome the local master browser MSBROWSE name release success function.
229 ******************************************************************/
231 static void release_msbrowse_name_success(struct subnet_record *subrec,
232 struct userdata_struct *userdata,
233 struct nmb_name *released_name,
234 struct in_addr released_ip)
236 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
237 nmb_namestr(released_name), subrec->subnet_name ));
239 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
240 remove_permanent_name_from_unicast( subrec, released_name);
243 /*******************************************************************
244 Unbecome the local master browser MSBROWSE name release fail function.
245 ******************************************************************/
247 static void release_msbrowse_name_fail( struct subnet_record *subrec,
248 struct response_record *rrec,
249 struct nmb_name *fail_name)
251 struct name_record *namerec;
253 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
254 nmb_namestr(fail_name), subrec->subnet_name ));
256 /* Release the name anyway. */
257 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
258 if(namerec)
259 remove_name_from_namelist(subrec, namerec);
261 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
262 remove_permanent_name_from_unicast( subrec, fail_name);
265 /*******************************************************************
266 Unbecome the local master browser. If force_new_election is true, restart
267 the election process after we've unbecome the local master.
268 ******************************************************************/
270 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
271 bool force_new_election)
273 struct name_record *namerec;
274 struct nmb_name nmbname;
276 /* Sanity check. */
278 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
279 on subnet %s\n",work->work_group, subrec->subnet_name));
281 if(find_server_in_workgroup( work, global_myname()) == NULL) {
282 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
283 in workgroup %s on subnet %s\n",
284 global_myname(), work->work_group, subrec->subnet_name));
285 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
286 return;
289 /* Set the state to unbecoming. */
290 work->mst_state = MST_UNBECOMING_MASTER;
293 * Release the WORKGROUP<1d> name asap to allow another machine to
294 * claim it.
297 release_1d_name( subrec, work->work_group, force_new_election);
299 /* Deregister any browser names we may have. */
300 make_nmb_name(&nmbname, MSBROWSE, 0x1);
301 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
302 release_name(subrec, namerec,
303 release_msbrowse_name_success,
304 release_msbrowse_name_fail,
305 NULL);
309 * Ensure we have sent and processed these release packets
310 * before returning - we don't want to process any election
311 * packets before dealing with the 1d release.
314 retransmit_or_expire_response_records(time(NULL));
317 /****************************************************************************
318 Success in registering the WORKGROUP<1d> name.
319 We are now *really* a local master browser.
320 ****************************************************************************/
322 static void become_local_master_stage2(struct subnet_record *subrec,
323 struct userdata_struct *userdata,
324 struct nmb_name *registered_name,
325 uint16 nb_flags,
326 int ttl, struct in_addr registered_ip)
328 int i = 0;
329 struct server_record *sl;
330 struct work_record *work;
331 struct server_record *servrec;
332 unstring regname;
334 pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
335 work = find_workgroup_on_subnet( subrec, regname);
337 if(!work) {
338 DEBUG(0,("become_local_master_stage2: Error - cannot find \
339 workgroup %s on subnet %s\n", regname, subrec->subnet_name));
340 return;
343 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
344 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
345 in workgroup %s on subnet %s\n",
346 global_myname(), regname, subrec->subnet_name));
347 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
348 return;
351 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
352 on subnet %s\n", work->work_group, subrec->subnet_name));
354 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
356 /* update our server status */
357 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
358 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
360 /* Tell the namelist writer to write out a change. */
361 subrec->work_changed = True;
363 /* Add this name to the workgroup as local master browser. */
364 set_workgroup_local_master_browser_name( work, global_myname());
366 /* Count the number of servers we have on our list. If it's
367 less than 10 (just a heuristic) request the servers
368 to announce themselves.
370 for( sl = work->serverlist; sl != NULL; sl = sl->next)
371 i++;
373 if (i < 10) {
374 /* Ask all servers on our local net to announce to us. */
375 broadcast_announce_request(subrec, work);
379 * Now we are a local master on a broadcast subnet, we need to add
380 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
381 * unicast requests sent to this name. We can create this name directly on
382 * the unicast subnet as a WINS server always returns true when registering
383 * this name, and discards the registration. We use the number of IP
384 * addresses registered to this name as a reference count, as we
385 * remove this broadcast subnet IP address from it when we stop becoming a local
386 * master browser for this broadcast subnet.
389 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
391 /* Reset the announce master browser timer so that we try and tell a domain
392 master browser as soon as possible that we are a local master browser. */
393 reset_announce_timer();
395 if( DEBUGLVL( 0 ) ) {
396 dbgtext( "*****\n\n" );
397 dbgtext( "Samba name server %s ", global_myname() );
398 dbgtext( "is now a local master browser " );
399 dbgtext( "for workgroup %s ", work->work_group );
400 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
404 /****************************************************************************
405 Failed to register the WORKGROUP<1d> name.
406 ****************************************************************************/
408 static void become_local_master_fail2(struct subnet_record *subrec,
409 struct response_record *rrec,
410 struct nmb_name *fail_name)
412 unstring failname;
413 struct work_record *work;
415 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
416 Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
418 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
419 work = find_workgroup_on_subnet( subrec, failname);
421 if(!work) {
422 DEBUG(0,("become_local_master_fail2: Error - cannot find \
423 workgroup %s on subnet %s\n", failname, subrec->subnet_name));
424 return;
427 /* Roll back all the way by calling unbecome_local_master_browser(). */
428 unbecome_local_master_browser(subrec, work, False);
431 /****************************************************************************
432 Success in registering the MSBROWSE name.
433 ****************************************************************************/
435 static void become_local_master_stage1(struct subnet_record *subrec,
436 struct userdata_struct *userdata,
437 struct nmb_name *registered_name,
438 uint16 nb_flags,
439 int ttl, struct in_addr registered_ip)
441 char *work_name = userdata->data;
442 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
444 if(!work) {
445 DEBUG(0,("become_local_master_stage1: Error - cannot find \
446 %s on subnet %s\n", work_name, subrec->subnet_name));
447 return;
450 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
451 work->work_group));
453 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
456 * We registered the MSBROWSE name on a broadcast subnet, now need to add
457 * the MSBROWSE name to the unicast subnet so that we can answer
458 * unicast requests sent to this name. We create this name directly on
459 * the unicast subnet.
462 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
464 /* Attempt to register the WORKGROUP<1d> name. */
465 register_name(subrec, work->work_group,0x1d,samba_nb_type,
466 become_local_master_stage2,
467 become_local_master_fail2,
468 NULL);
471 /****************************************************************************
472 Failed to register the MSBROWSE name.
473 ****************************************************************************/
475 static void become_local_master_fail1(struct subnet_record *subrec,
476 struct response_record *rrec,
477 struct nmb_name *fail_name)
479 char *work_name = rrec->userdata->data;
480 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
482 if(!work) {
483 DEBUG(0,("become_local_master_fail1: Error - cannot find \
484 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
485 return;
488 if(find_server_in_workgroup(work, global_myname()) == NULL) {
489 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
490 in workgroup %s on subnet %s\n",
491 global_myname(), work->work_group, subrec->subnet_name));
492 return;
495 reset_workgroup_state( subrec, work->work_group, False );
497 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
498 workgroup %s on subnet %s. Couldn't register name %s.\n",
499 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
502 /******************************************************************
503 Become the local master browser on a subnet.
504 This gets called if we win an election on this subnet.
506 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
507 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
508 Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
509 ******************************************************************/
511 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
513 struct userdata_struct *userdata;
514 size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
516 /* Sanity check. */
517 if (!lp_local_master()) {
518 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
519 return;
522 if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
523 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
524 work->mst_state ));
525 return;
528 if(find_server_in_workgroup( work, global_myname()) == NULL) {
529 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
530 in workgroup %s on subnet %s\n",
531 global_myname(), work->work_group, subrec->subnet_name));
532 return;
535 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
536 %s on subnet %s\n", work->work_group, subrec->subnet_name));
538 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
539 work->mst_state = MST_BACKUP; /* an election win was successful */
541 work->ElectionCriterion |= 0x5;
543 /* Tell the namelist writer to write out a change. */
544 subrec->work_changed = True;
546 /* Setup the userdata_struct. */
547 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
548 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
549 return;
552 userdata->copy_fn = NULL;
553 userdata->free_fn = NULL;
554 userdata->userdata_len = strlen(work->work_group)+1;
555 overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
557 /* Register the special browser group name. */
558 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
559 become_local_master_stage1,
560 become_local_master_fail1,
561 userdata);
563 zero_free(userdata, size);
566 /***************************************************************
567 Utility function to set the local master browser name. Does
568 some sanity checking as old versions of Samba seem to sometimes
569 say that the master browser name for a workgroup is the same
570 as the workgroup name.
571 ****************************************************************/
573 void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
575 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
576 for workgroup %s.\n", newname, work->work_group ));
578 #if 0
580 * Apparently some sites use the workgroup name as the local
581 * master browser name. Arrrrggghhhhh ! (JRA).
583 if(strequal( work->work_group, newname))
585 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
586 local_master_browser_name for workgroup %s to workgroup name.\n",
587 work->work_group ));
588 return;
590 #endif
592 unstrcpy(work->local_master_browser_name, newname);