removed two unneeded files after Richard backed out these changes.
[Samba.git] / source / nmbd / nmbd_become_lmb.c
blob52955d9bfc0d636a260b7acbbf441e391e9f5c66
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 extern pstring global_myname;
29 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
31 /*******************************************************************
32 Utility function to add a name to the unicast subnet, or add in
33 our IP address if it already exists.
34 ******************************************************************/
36 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
37 struct nmb_name *nmbname, uint16 nb_type )
39 struct name_record *namerec;
41 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
43 /* The name needs to be created on the unicast subnet. */
44 (void)add_name_to_subnet( unicast_subnet, nmbname->name,
45 nmbname->name_type, nb_type,
46 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
48 else
50 /* The name already exists on the unicast subnet. Add our local
51 IP for the given broadcast subnet to the name. */
52 add_ip_to_name_record( namerec, subrec->myip);
56 /*******************************************************************
57 Utility function to remove a name from the unicast subnet.
58 ******************************************************************/
60 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
61 struct nmb_name *nmbname )
63 struct name_record *namerec;
65 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
67 /* Remove this broadcast subnet IP address from the name. */
68 remove_ip_from_name_record( namerec, subrec->myip);
69 if(namerec->data.num_ips == 0)
70 remove_name_from_namelist( unicast_subnet, namerec);
74 /*******************************************************************
75 Utility function always called to set our workgroup and server
76 state back to potential browser, or none.
77 ******************************************************************/
79 static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name,
80 BOOL force_new_election )
82 struct work_record *work;
83 struct server_record *servrec;
84 struct nmb_name nmbname;
86 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
88 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
89 subnet %s.\n", workgroup_name, subrec->subnet_name ));
90 return;
93 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
95 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
96 in workgroup %s on subnet %s\n",
97 global_myname, work->work_group, subrec->subnet_name));
98 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
99 return;
102 /* Update our server status - remove any master flag and replace
103 it with the potential browser flag. */
104 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
105 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
107 /* Tell the namelist writer to write out a change. */
108 subrec->work_changed = True;
110 /* Reset our election flags. */
111 work->ElectionCriterion &= ~0x4;
113 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
115 /* Forget who the local master browser was for
116 this workgroup. */
118 set_workgroup_local_master_browser_name( work, "");
121 * Ensure the IP address of this subnet is not registered as one
122 * of the IP addresses of the WORKGROUP<1d> name on the unicast
123 * subnet. This undoes what we did below when we became a local
124 * master browser.
127 make_nmb_name(&nmbname, work->work_group, 0x1d);
129 remove_permanent_name_from_unicast( subrec, &nmbname);
131 if(force_new_election)
132 work->needelection = True;
135 /*******************************************************************
136 Unbecome the local master browser name release success function.
137 ******************************************************************/
139 static void unbecome_local_master_success(struct subnet_record *subrec,
140 struct userdata_struct *userdata,
141 struct nmb_name *released_name,
142 struct in_addr released_ip)
144 BOOL force_new_election = False;
146 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
148 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
149 nmb_namestr(released_name)));
151 /* Now reset the workgroup and server state. */
152 reset_workgroup_state( subrec, released_name->name, force_new_election );
154 if( DEBUGLVL( 0 ) )
156 dbgtext( "*****\n\n" );
157 dbgtext( "Samba name server %s ", global_myname );
158 dbgtext( "has stopped being a local master browser " );
159 dbgtext( "for workgroup %s ", released_name->name );
160 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
165 /*******************************************************************
166 Unbecome the local master browser name release fail function.
167 ******************************************************************/
169 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
170 struct nmb_name *fail_name)
172 struct name_record *namerec;
173 struct userdata_struct *userdata = rrec->userdata;
174 BOOL force_new_election = False;
176 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
178 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
179 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
181 /* Do it anyway. */
182 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
183 if(namerec)
184 remove_name_from_namelist(subrec, namerec);
186 /* Now reset the workgroup and server state. */
187 reset_workgroup_state( subrec, fail_name->name, force_new_election );
189 if( DEBUGLVL( 0 ) )
191 dbgtext( "*****\n\n" );
192 dbgtext( "Samba name server %s ", global_myname );
193 dbgtext( "has stopped being a local master browser " );
194 dbgtext( "for workgroup %s ", fail_name->name );
195 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
199 /*******************************************************************
200 Utility function to remove the WORKGROUP<1d> name.
201 ******************************************************************/
203 static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
204 BOOL force_new_election)
206 struct nmb_name nmbname;
207 struct name_record *namerec;
209 make_nmb_name(&nmbname, workgroup_name, 0x1d);
210 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
212 struct userdata_struct *userdata;
213 int size = sizeof(struct userdata_struct) + sizeof(BOOL);
215 if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
217 DEBUG(0,("release_1d_name: malloc fail.\n"));
218 return;
221 userdata->copy_fn = NULL;
222 userdata->free_fn = NULL;
223 userdata->userdata_len = sizeof(BOOL);
224 memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
226 release_name(subrec, namerec,
227 unbecome_local_master_success,
228 unbecome_local_master_fail,
229 userdata);
231 zero_free(userdata, size);
235 /*******************************************************************
236 Unbecome the local master browser MSBROWSE name release success function.
237 ******************************************************************/
239 static void release_msbrowse_name_success(struct subnet_record *subrec,
240 struct userdata_struct *userdata,
241 struct nmb_name *released_name,
242 struct in_addr released_ip)
244 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
245 nmb_namestr(released_name), subrec->subnet_name ));
247 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
248 remove_permanent_name_from_unicast( subrec, released_name);
251 /*******************************************************************
252 Unbecome the local master browser MSBROWSE name release fail function.
253 ******************************************************************/
255 static void release_msbrowse_name_fail( struct subnet_record *subrec,
256 struct response_record *rrec,
257 struct nmb_name *fail_name)
259 struct name_record *namerec;
261 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
262 nmb_namestr(fail_name), subrec->subnet_name ));
264 /* Release the name anyway. */
265 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
266 if(namerec)
267 remove_name_from_namelist(subrec, namerec);
269 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
270 remove_permanent_name_from_unicast( subrec, fail_name);
273 /*******************************************************************
274 Unbecome the local master browser. If force_new_election is true, restart
275 the election process after we've unbecome the local master.
276 ******************************************************************/
278 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
279 BOOL force_new_election)
281 struct name_record *namerec;
282 struct nmb_name nmbname;
284 /* Sanity check. */
286 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
287 on subnet %s\n",work->work_group, subrec->subnet_name));
289 if(find_server_in_workgroup( work, global_myname) == NULL)
291 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
292 in workgroup %s on subnet %s\n",
293 global_myname, work->work_group, subrec->subnet_name));
294 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
295 return;
298 /* Set the state to unbecoming. */
299 work->mst_state = MST_UNBECOMING_MASTER;
302 * Release the WORKGROUP<1d> name asap to allow another machine to
303 * claim it.
306 release_1d_name( subrec, work->work_group, force_new_election);
308 /* Deregister any browser names we may have. */
309 make_nmb_name(&nmbname, MSBROWSE, 0x1);
310 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
312 release_name(subrec, namerec,
313 release_msbrowse_name_success,
314 release_msbrowse_name_fail,
315 NULL);
319 * Ensure we have sent and processed these release packets
320 * before returning - we don't want to process any election
321 * packets before dealing with the 1d release.
324 retransmit_or_expire_response_records(time(NULL));
327 /****************************************************************************
328 Success in registering the WORKGROUP<1d> name.
329 We are now *really* a local master browser.
330 ****************************************************************************/
332 static void become_local_master_stage2(struct subnet_record *subrec,
333 struct userdata_struct *userdata,
334 struct nmb_name *registered_name,
335 uint16 nb_flags,
336 int ttl, struct in_addr registered_ip)
338 int i = 0;
339 struct server_record *sl;
340 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
341 struct server_record *servrec;
343 if(!work)
345 DEBUG(0,("become_local_master_stage2: Error - cannot find \
346 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
347 return;
350 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
352 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
353 in workgroup %s on subnet %s\n",
354 global_myname, registered_name->name, subrec->subnet_name));
355 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
356 return;
359 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
360 on subnet %s\n", work->work_group, subrec->subnet_name));
362 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
364 /* update our server status */
365 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
366 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
368 /* Tell the namelist writer to write out a change. */
369 subrec->work_changed = True;
371 /* Add this name to the workgroup as local master browser. */
372 set_workgroup_local_master_browser_name( work, global_myname);
374 /* Count the number of servers we have on our list. If it's
375 less than 10 (just a heuristic) request the servers
376 to announce themselves.
378 for( sl = work->serverlist; sl != NULL; sl = sl->next)
379 i++;
381 if (i < 10)
383 /* Ask all servers on our local net to announce to us. */
384 broadcast_announce_request(subrec, work);
388 * Now we are a local master on a broadcast subnet, we need to add
389 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
390 * unicast requests sent to this name. We can create this name directly on
391 * the unicast subnet as a WINS server always returns true when registering
392 * this name, and discards the registration. We use the number of IP
393 * addresses registered to this name as a reference count, as we
394 * remove this broadcast subnet IP address from it when we stop becoming a local
395 * master browser for this broadcast subnet.
398 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
400 /* Reset the announce master browser timer so that we try and tell a domain
401 master browser as soon as possible that we are a local master browser. */
402 reset_announce_timer();
404 if( DEBUGLVL( 0 ) )
406 dbgtext( "*****\n\n" );
407 dbgtext( "Samba name server %s ", global_myname );
408 dbgtext( "is now a local master browser " );
409 dbgtext( "for workgroup %s ", work->work_group );
410 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
415 /****************************************************************************
416 Failed to register the WORKGROUP<1d> name.
417 ****************************************************************************/
418 static void become_local_master_fail2(struct subnet_record *subrec,
419 struct response_record *rrec,
420 struct nmb_name *fail_name)
422 struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
424 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
425 Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
427 if(!work)
429 DEBUG(0,("become_local_master_fail2: Error - cannot find \
430 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
431 return;
434 /* Roll back all the way by calling unbecome_local_master_browser(). */
435 unbecome_local_master_browser(subrec, work, False);
438 /****************************************************************************
439 Success in registering the MSBROWSE name.
440 ****************************************************************************/
442 static void become_local_master_stage1(struct subnet_record *subrec,
443 struct userdata_struct *userdata,
444 struct nmb_name *registered_name,
445 uint16 nb_flags,
446 int ttl, struct in_addr registered_ip)
448 char *work_name = userdata->data;
449 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
451 if(!work)
453 DEBUG(0,("become_local_master_stage1: Error - cannot find \
454 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
455 return;
458 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
459 work->work_group));
461 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
464 * We registered the MSBROWSE name on a broadcast subnet, now need to add
465 * the MSBROWSE name to the unicast subnet so that we can answer
466 * unicast requests sent to this name. We create this name directly on
467 * the unicast subnet.
470 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
472 /* Attempt to register the WORKGROUP<1d> name. */
473 register_name(subrec, work->work_group,0x1d,samba_nb_type,
474 become_local_master_stage2,
475 become_local_master_fail2,
476 NULL);
479 /****************************************************************************
480 Failed to register the MSBROWSE name.
481 ****************************************************************************/
483 static void become_local_master_fail1(struct subnet_record *subrec,
484 struct response_record *rrec,
485 struct nmb_name *fail_name)
487 char *work_name = rrec->userdata->data;
488 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
490 if(!work)
492 DEBUG(0,("become_local_master_fail1: Error - cannot find \
493 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
494 return;
497 if(find_server_in_workgroup(work, global_myname) == NULL)
499 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
500 in workgroup %s on subnet %s\n",
501 global_myname, work->work_group, subrec->subnet_name));
502 return;
505 reset_workgroup_state( subrec, work->work_group, False );
507 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
508 workgroup %s on subnet %s. Couldn't register name %s.\n",
509 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
512 /******************************************************************
513 Become the local master browser on a subnet.
514 This gets called if we win an election on this subnet.
516 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
517 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
518 Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
519 ******************************************************************/
521 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
523 struct userdata_struct *userdata;
524 int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
526 /* Sanity check. */
527 if (!lp_local_master())
529 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
530 return;
533 if(!AM_POTENTIAL_MASTER_BROWSER(work))
535 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
536 work->mst_state ));
537 return;
540 if(find_server_in_workgroup( work, global_myname) == NULL)
542 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
543 in workgroup %s on subnet %s\n",
544 global_myname, work->work_group, subrec->subnet_name));
545 return;
548 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
549 %s on subnet %s\n", work->work_group, subrec->subnet_name));
551 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
552 work->mst_state = MST_BACKUP; /* an election win was successful */
554 work->ElectionCriterion |= 0x5;
556 /* Tell the namelist writer to write out a change. */
557 subrec->work_changed = True;
559 /* Setup the userdata_struct. */
560 if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
562 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
563 return;
566 userdata->copy_fn = NULL;
567 userdata->free_fn = NULL;
568 userdata->userdata_len = strlen(work->work_group)+1;
569 pstrcpy(userdata->data, work->work_group);
571 /* Register the special browser group name. */
572 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
573 become_local_master_stage1,
574 become_local_master_fail1,
575 userdata);
577 zero_free(userdata, size);
580 /***************************************************************
581 Utility function to set the local master browser name. Does
582 some sanity checking as old versions of Samba seem to sometimes
583 say that the master browser name for a workgroup is the same
584 as the workgroup name.
585 ****************************************************************/
587 void set_workgroup_local_master_browser_name( struct work_record *work, char *newname)
589 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
590 for workgroup %s.\n", newname, work->work_group ));
592 #if 0
594 * Apparently some sites use the workgroup name as the local
595 * master browser name. Arrrrggghhhhh ! (JRA).
597 if(strequal( work->work_group, newname))
599 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
600 local_master_browser_name for workgroup %s to workgroup name.\n",
601 work->work_group ));
602 return;
604 #endif
606 StrnCpy(work->local_master_browser_name, newname,
607 sizeof(work->local_master_browser_name)-1);