Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / nmbd / nmbd_become_lmb.c
blobb928a8a7c5c377a121a2bf1c84e366e34e6bb0a6
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
28 /*******************************************************************
29 Utility function to add a name to the unicast subnet, or add in
30 our IP address if it already exists.
31 ******************************************************************/
33 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
34 struct nmb_name *nmbname, uint16 nb_type )
36 unstring name;
37 struct name_record *namerec;
39 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
40 pull_ascii_nstring(name, sizeof(name), nmbname->name);
41 /* The name needs to be created on the unicast subnet. */
42 (void)add_name_to_subnet( unicast_subnet, name,
43 nmbname->name_type, nb_type,
44 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
45 } else {
46 /* The name already exists on the unicast subnet. Add our local
47 IP for the given broadcast subnet to the name. */
48 add_ip_to_name_record( namerec, subrec->myip);
52 /*******************************************************************
53 Utility function to remove a name from the unicast subnet.
54 ******************************************************************/
56 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
57 struct nmb_name *nmbname )
59 struct name_record *namerec;
61 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
62 /* Remove this broadcast subnet IP address from the name. */
63 remove_ip_from_name_record( namerec, subrec->myip);
64 if(namerec->data.num_ips == 0)
65 remove_name_from_namelist( unicast_subnet, namerec);
69 /*******************************************************************
70 Utility function always called to set our workgroup and server
71 state back to potential browser, or none.
72 ******************************************************************/
74 static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
75 BOOL force_new_election )
77 struct work_record *work;
78 struct server_record *servrec;
79 struct nmb_name nmbname;
81 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
82 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
83 subnet %s.\n", workgroup_name, subrec->subnet_name ));
84 return;
87 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
88 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
89 in workgroup %s on subnet %s\n",
90 global_myname(), work->work_group, subrec->subnet_name));
91 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
92 return;
95 /* Update our server status - remove any master flag and replace
96 it with the potential browser flag. */
97 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
98 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
100 /* Tell the namelist writer to write out a change. */
101 subrec->work_changed = True;
103 /* Reset our election flags. */
104 work->ElectionCriterion &= ~0x4;
106 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
108 /* Forget who the local master browser was for
109 this workgroup. */
111 set_workgroup_local_master_browser_name( work, "");
114 * Ensure the IP address of this subnet is not registered as one
115 * of the IP addresses of the WORKGROUP<1d> name on the unicast
116 * subnet. This undoes what we did below when we became a local
117 * master browser.
120 make_nmb_name(&nmbname, work->work_group, 0x1d);
122 remove_permanent_name_from_unicast( subrec, &nmbname);
124 if(force_new_election)
125 work->needelection = True;
128 /*******************************************************************
129 Unbecome the local master browser name release success function.
130 ******************************************************************/
132 static void unbecome_local_master_success(struct subnet_record *subrec,
133 struct userdata_struct *userdata,
134 struct nmb_name *released_name,
135 struct in_addr released_ip)
137 BOOL force_new_election = False;
138 unstring relname;
140 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
142 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
143 nmb_namestr(released_name)));
145 /* Now reset the workgroup and server state. */
146 pull_ascii_nstring(relname, sizeof(relname), released_name->name);
147 reset_workgroup_state( subrec, relname, force_new_election );
149 if( DEBUGLVL( 0 ) ) {
150 dbgtext( "*****\n\n" );
151 dbgtext( "Samba name server %s ", global_myname() );
152 dbgtext( "has stopped being a local master browser " );
153 dbgtext( "for workgroup %s ", relname );
154 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
159 /*******************************************************************
160 Unbecome the local master browser name release fail function.
161 ******************************************************************/
163 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
164 struct nmb_name *fail_name)
166 struct name_record *namerec;
167 struct userdata_struct *userdata = rrec->userdata;
168 BOOL force_new_election = False;
169 unstring failname;
171 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
173 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
174 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
176 /* Do it anyway. */
177 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
178 if(namerec)
179 remove_name_from_namelist(subrec, namerec);
181 /* Now reset the workgroup and server state. */
182 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
183 reset_workgroup_state( subrec, failname, force_new_election );
185 if( DEBUGLVL( 0 ) ) {
186 dbgtext( "*****\n\n" );
187 dbgtext( "Samba name server %s ", global_myname() );
188 dbgtext( "has stopped being a local master browser " );
189 dbgtext( "for workgroup %s ", failname );
190 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
194 /*******************************************************************
195 Utility function to remove the WORKGROUP<1d> name.
196 ******************************************************************/
198 static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
199 BOOL force_new_election)
201 struct nmb_name nmbname;
202 struct name_record *namerec;
204 make_nmb_name(&nmbname, workgroup_name, 0x1d);
205 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
206 struct userdata_struct *userdata;
207 size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
209 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
210 DEBUG(0,("release_1d_name: malloc fail.\n"));
211 return;
214 userdata->copy_fn = NULL;
215 userdata->free_fn = NULL;
216 userdata->userdata_len = sizeof(BOOL);
217 memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
219 release_name(subrec, namerec,
220 unbecome_local_master_success,
221 unbecome_local_master_fail,
222 userdata);
224 zero_free(userdata, size);
228 /*******************************************************************
229 Unbecome the local master browser MSBROWSE name release success function.
230 ******************************************************************/
232 static void release_msbrowse_name_success(struct subnet_record *subrec,
233 struct userdata_struct *userdata,
234 struct nmb_name *released_name,
235 struct in_addr released_ip)
237 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
238 nmb_namestr(released_name), subrec->subnet_name ));
240 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
241 remove_permanent_name_from_unicast( subrec, released_name);
244 /*******************************************************************
245 Unbecome the local master browser MSBROWSE name release fail function.
246 ******************************************************************/
248 static void release_msbrowse_name_fail( struct subnet_record *subrec,
249 struct response_record *rrec,
250 struct nmb_name *fail_name)
252 struct name_record *namerec;
254 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
255 nmb_namestr(fail_name), subrec->subnet_name ));
257 /* Release the name anyway. */
258 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
259 if(namerec)
260 remove_name_from_namelist(subrec, namerec);
262 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
263 remove_permanent_name_from_unicast( subrec, fail_name);
266 /*******************************************************************
267 Unbecome the local master browser. If force_new_election is true, restart
268 the election process after we've unbecome the local master.
269 ******************************************************************/
271 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
272 BOOL force_new_election)
274 struct name_record *namerec;
275 struct nmb_name nmbname;
277 /* Sanity check. */
279 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
280 on subnet %s\n",work->work_group, subrec->subnet_name));
282 if(find_server_in_workgroup( work, global_myname()) == NULL) {
283 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
284 in workgroup %s on subnet %s\n",
285 global_myname(), work->work_group, subrec->subnet_name));
286 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
287 return;
290 /* Set the state to unbecoming. */
291 work->mst_state = MST_UNBECOMING_MASTER;
294 * Release the WORKGROUP<1d> name asap to allow another machine to
295 * claim it.
298 release_1d_name( subrec, work->work_group, force_new_election);
300 /* Deregister any browser names we may have. */
301 make_nmb_name(&nmbname, MSBROWSE, 0x1);
302 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
303 release_name(subrec, namerec,
304 release_msbrowse_name_success,
305 release_msbrowse_name_fail,
306 NULL);
310 * Ensure we have sent and processed these release packets
311 * before returning - we don't want to process any election
312 * packets before dealing with the 1d release.
315 retransmit_or_expire_response_records(time(NULL));
318 /****************************************************************************
319 Success in registering the WORKGROUP<1d> name.
320 We are now *really* a local master browser.
321 ****************************************************************************/
323 static void become_local_master_stage2(struct subnet_record *subrec,
324 struct userdata_struct *userdata,
325 struct nmb_name *registered_name,
326 uint16 nb_flags,
327 int ttl, struct in_addr registered_ip)
329 int i = 0;
330 struct server_record *sl;
331 struct work_record *work;
332 struct server_record *servrec;
333 unstring regname;
335 pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
336 work = find_workgroup_on_subnet( subrec, regname);
338 if(!work) {
339 DEBUG(0,("become_local_master_stage2: Error - cannot find \
340 workgroup %s on subnet %s\n", regname, subrec->subnet_name));
341 return;
344 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
345 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
346 in workgroup %s on subnet %s\n",
347 global_myname(), regname, subrec->subnet_name));
348 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
349 return;
352 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
353 on subnet %s\n", work->work_group, subrec->subnet_name));
355 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
357 /* update our server status */
358 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
359 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
361 /* Tell the namelist writer to write out a change. */
362 subrec->work_changed = True;
364 /* Add this name to the workgroup as local master browser. */
365 set_workgroup_local_master_browser_name( work, global_myname());
367 /* Count the number of servers we have on our list. If it's
368 less than 10 (just a heuristic) request the servers
369 to announce themselves.
371 for( sl = work->serverlist; sl != NULL; sl = sl->next)
372 i++;
374 if (i < 10) {
375 /* Ask all servers on our local net to announce to us. */
376 broadcast_announce_request(subrec, work);
380 * Now we are a local master on a broadcast subnet, we need to add
381 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
382 * unicast requests sent to this name. We can create this name directly on
383 * the unicast subnet as a WINS server always returns true when registering
384 * this name, and discards the registration. We use the number of IP
385 * addresses registered to this name as a reference count, as we
386 * remove this broadcast subnet IP address from it when we stop becoming a local
387 * master browser for this broadcast subnet.
390 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
392 /* Reset the announce master browser timer so that we try and tell a domain
393 master browser as soon as possible that we are a local master browser. */
394 reset_announce_timer();
396 if( DEBUGLVL( 0 ) ) {
397 dbgtext( "*****\n\n" );
398 dbgtext( "Samba name server %s ", global_myname() );
399 dbgtext( "is now a local master browser " );
400 dbgtext( "for workgroup %s ", work->work_group );
401 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
405 /****************************************************************************
406 Failed to register the WORKGROUP<1d> name.
407 ****************************************************************************/
409 static void become_local_master_fail2(struct subnet_record *subrec,
410 struct response_record *rrec,
411 struct nmb_name *fail_name)
413 unstring failname;
414 struct work_record *work;
416 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
417 Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
419 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
420 work = find_workgroup_on_subnet( subrec, failname);
422 if(!work) {
423 DEBUG(0,("become_local_master_fail2: Error - cannot find \
424 workgroup %s on subnet %s\n", failname, subrec->subnet_name));
425 return;
428 /* Roll back all the way by calling unbecome_local_master_browser(). */
429 unbecome_local_master_browser(subrec, work, False);
432 /****************************************************************************
433 Success in registering the MSBROWSE name.
434 ****************************************************************************/
436 static void become_local_master_stage1(struct subnet_record *subrec,
437 struct userdata_struct *userdata,
438 struct nmb_name *registered_name,
439 uint16 nb_flags,
440 int ttl, struct in_addr registered_ip)
442 char *work_name = userdata->data;
443 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
445 if(!work) {
446 DEBUG(0,("become_local_master_stage1: Error - cannot find \
447 %s on subnet %s\n", work_name, subrec->subnet_name));
448 return;
451 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
452 work->work_group));
454 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
457 * We registered the MSBROWSE name on a broadcast subnet, now need to add
458 * the MSBROWSE name to the unicast subnet so that we can answer
459 * unicast requests sent to this name. We create this name directly on
460 * the unicast subnet.
463 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
465 /* Attempt to register the WORKGROUP<1d> name. */
466 register_name(subrec, work->work_group,0x1d,samba_nb_type,
467 become_local_master_stage2,
468 become_local_master_fail2,
469 NULL);
472 /****************************************************************************
473 Failed to register the MSBROWSE name.
474 ****************************************************************************/
476 static void become_local_master_fail1(struct subnet_record *subrec,
477 struct response_record *rrec,
478 struct nmb_name *fail_name)
480 char *work_name = rrec->userdata->data;
481 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
483 if(!work) {
484 DEBUG(0,("become_local_master_fail1: Error - cannot find \
485 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
486 return;
489 if(find_server_in_workgroup(work, global_myname()) == NULL) {
490 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
491 in workgroup %s on subnet %s\n",
492 global_myname(), work->work_group, subrec->subnet_name));
493 return;
496 reset_workgroup_state( subrec, work->work_group, False );
498 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
499 workgroup %s on subnet %s. Couldn't register name %s.\n",
500 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
503 /******************************************************************
504 Become the local master browser on a subnet.
505 This gets called if we win an election on this subnet.
507 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
508 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
509 Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
510 ******************************************************************/
512 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
514 struct userdata_struct *userdata;
515 size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
517 /* Sanity check. */
518 if (!lp_local_master()) {
519 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
520 return;
523 if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
524 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
525 work->mst_state ));
526 return;
529 if(find_server_in_workgroup( work, global_myname()) == NULL) {
530 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
531 in workgroup %s on subnet %s\n",
532 global_myname(), work->work_group, subrec->subnet_name));
533 return;
536 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
537 %s on subnet %s\n", work->work_group, subrec->subnet_name));
539 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
540 work->mst_state = MST_BACKUP; /* an election win was successful */
542 work->ElectionCriterion |= 0x5;
544 /* Tell the namelist writer to write out a change. */
545 subrec->work_changed = True;
547 /* Setup the userdata_struct. */
548 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
549 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
550 return;
553 userdata->copy_fn = NULL;
554 userdata->free_fn = NULL;
555 userdata->userdata_len = strlen(work->work_group)+1;
556 overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
558 /* Register the special browser group name. */
559 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
560 become_local_master_stage1,
561 become_local_master_fail1,
562 userdata);
564 zero_free(userdata, size);
567 /***************************************************************
568 Utility function to set the local master browser name. Does
569 some sanity checking as old versions of Samba seem to sometimes
570 say that the master browser name for a workgroup is the same
571 as the workgroup name.
572 ****************************************************************/
574 void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
576 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
577 for workgroup %s.\n", newname, work->work_group ));
579 #if 0
581 * Apparently some sites use the workgroup name as the local
582 * master browser name. Arrrrggghhhhh ! (JRA).
584 if(strequal( work->work_group, newname))
586 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
587 local_master_browser_name for workgroup %s to workgroup name.\n",
588 work->work_group ));
589 return;
591 #endif
593 unstrcpy(work->local_master_browser_name, newname);