dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba / source / nmbd / nmbd_become_lmb.c
bloba7f17454f9c1320ae444956e00eb4de922984d85
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 int DEBUGLEVEL;
28 extern pstring global_myname;
30 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
32 /*******************************************************************
33 Utility function to add a name to the unicast subnet, or add in
34 our IP address if it already exists.
35 ******************************************************************/
37 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
38 struct nmb_name *nmbname, uint16 nb_type )
40 struct name_record *namerec;
42 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
44 /* The name needs to be created on the unicast subnet. */
45 (void)add_name_to_subnet( unicast_subnet, nmbname->name,
46 nmbname->name_type, nb_type,
47 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
49 else
51 /* The name already exists on the unicast subnet. Add our local
52 IP for the given broadcast subnet to the name. */
53 add_ip_to_name_record( namerec, subrec->myip);
57 /*******************************************************************
58 Utility function to remove a name from the unicast subnet.
59 ******************************************************************/
61 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
62 struct nmb_name *nmbname )
64 struct name_record *namerec;
66 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
68 /* Remove this broadcast subnet IP address from the name. */
69 remove_ip_from_name_record( namerec, subrec->myip);
70 if(namerec->data.num_ips == 0)
71 remove_name_from_namelist( unicast_subnet, namerec);
75 /*******************************************************************
76 Utility function always called to set our workgroup and server
77 state back to potential browser, or none.
78 ******************************************************************/
80 static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name,
81 BOOL force_new_election )
83 struct work_record *work;
84 struct server_record *servrec;
85 struct nmb_name nmbname;
87 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
89 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
90 subnet %s.\n", workgroup_name, subrec->subnet_name ));
91 return;
94 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
96 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
97 in workgroup %s on subnet %s\n",
98 global_myname, work->work_group, subrec->subnet_name));
99 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
100 return;
103 /* Update our server status - remove any master flag and replace
104 it with the potential browser flag. */
105 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
106 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
108 /* Tell the namelist writer to write out a change. */
109 subrec->work_changed = True;
111 /* Reset our election flags. */
112 work->ElectionCriterion &= ~0x4;
114 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
116 /* Forget who the local master browser was for
117 this workgroup. */
119 set_workgroup_local_master_browser_name( work, "");
122 * Ensure the IP address of this subnet is not registered as one
123 * of the IP addresses of the WORKGROUP<1d> name on the unicast
124 * subnet. This undoes what we did below when we became a local
125 * master browser.
128 make_nmb_name(&nmbname, work->work_group, 0x1d);
130 remove_permanent_name_from_unicast( subrec, &nmbname);
132 if(force_new_election)
133 work->needelection = True;
136 /*******************************************************************
137 Unbecome the local master browser name release success function.
138 ******************************************************************/
140 static void unbecome_local_master_success(struct subnet_record *subrec,
141 struct userdata_struct *userdata,
142 struct nmb_name *released_name,
143 struct in_addr released_ip)
145 BOOL force_new_election = False;
147 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
149 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
150 nmb_namestr(released_name)));
152 /* Now reset the workgroup and server state. */
153 reset_workgroup_state( subrec, released_name->name, force_new_election );
155 if( DEBUGLVL( 0 ) )
157 dbgtext( "Samba name server %s has stopped being a local master browser for workgroup %s "
158 "on subnet %s\n", global_myname, released_name->name, subrec->subnet_name );
163 /*******************************************************************
164 Unbecome the local master browser name release fail function.
165 ******************************************************************/
167 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
168 struct nmb_name *fail_name)
170 struct name_record *namerec;
171 struct userdata_struct *userdata = rrec->userdata;
172 BOOL force_new_election = False;
174 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
176 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
177 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
179 /* Do it anyway. */
180 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
181 if(namerec)
182 remove_name_from_namelist(subrec, namerec);
184 /* Now reset the workgroup and server state. */
185 reset_workgroup_state( subrec, fail_name->name, force_new_election );
187 if( DEBUGLVL( 0 ) )
189 dbgtext( "Samba name server %s has stopped being a local master browser for workgroup %s "
190 "on subnet %s\n", global_myname, fail_name->name, subrec->subnet_name );
194 /*******************************************************************
195 Utility function to remove the WORKGROUP<1d> name.
196 ******************************************************************/
198 static void release_1d_name( struct subnet_record *subrec, 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)
207 struct userdata_struct *userdata;
208 int size = sizeof(struct userdata_struct) + sizeof(BOOL);
210 if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
212 DEBUG(0,("release_1d_name: malloc fail.\n"));
213 return;
216 userdata->copy_fn = NULL;
217 userdata->free_fn = NULL;
218 userdata->userdata_len = sizeof(BOOL);
219 memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
221 release_name(subrec, namerec,
222 unbecome_local_master_success,
223 unbecome_local_master_fail,
224 userdata);
226 zero_free(userdata, size);
230 /*******************************************************************
231 Unbecome the local master browser MSBROWSE name release success function.
232 ******************************************************************/
234 static void release_msbrowse_name_success(struct subnet_record *subrec,
235 struct userdata_struct *userdata,
236 struct nmb_name *released_name,
237 struct in_addr released_ip)
239 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
240 nmb_namestr(released_name), subrec->subnet_name ));
242 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
243 remove_permanent_name_from_unicast( subrec, released_name);
246 /*******************************************************************
247 Unbecome the local master browser MSBROWSE name release fail function.
248 ******************************************************************/
250 static void release_msbrowse_name_fail( struct subnet_record *subrec,
251 struct response_record *rrec,
252 struct nmb_name *fail_name)
254 struct name_record *namerec;
256 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
257 nmb_namestr(fail_name), subrec->subnet_name ));
259 /* Release the name anyway. */
260 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
261 if(namerec)
262 remove_name_from_namelist(subrec, namerec);
264 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
265 remove_permanent_name_from_unicast( subrec, fail_name);
268 /*******************************************************************
269 Unbecome the local master browser. If force_new_election is true, restart
270 the election process after we've unbecome the local master.
271 ******************************************************************/
273 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
274 BOOL force_new_election)
276 struct name_record *namerec;
277 struct nmb_name nmbname;
279 /* Sanity check. */
281 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
282 on subnet %s\n",work->work_group, subrec->subnet_name));
284 if(find_server_in_workgroup( work, global_myname) == NULL)
286 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
287 in workgroup %s on subnet %s\n",
288 global_myname, work->work_group, subrec->subnet_name));
289 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
290 return;
293 /* Set the state to unbecoming. */
294 work->mst_state = MST_UNBECOMING_MASTER;
297 * Release the WORKGROUP<1d> name asap to allow another machine to
298 * claim it.
301 release_1d_name( subrec, work->work_group, force_new_election);
303 /* Deregister any browser names we may have. */
304 make_nmb_name(&nmbname, MSBROWSE, 0x1);
305 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
307 release_name(subrec, namerec,
308 release_msbrowse_name_success,
309 release_msbrowse_name_fail,
310 NULL);
314 * Ensure we have sent and processed these release packets
315 * before returning - we don't want to process any election
316 * packets before dealing with the 1d release.
319 retransmit_or_expire_response_records(time(NULL));
322 /****************************************************************************
323 Success in registering the WORKGROUP<1d> name.
324 We are now *really* a local master browser.
325 ****************************************************************************/
327 static void become_local_master_stage2(struct subnet_record *subrec,
328 struct userdata_struct *userdata,
329 struct nmb_name *registered_name,
330 uint16 nb_flags,
331 int ttl, struct in_addr registered_ip)
333 int i = 0;
334 struct server_record *sl;
335 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
336 struct server_record *servrec;
338 if(!work)
340 DEBUG(0,("become_local_master_stage2: Error - cannot find \
341 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
342 return;
345 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
347 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
348 in workgroup %s on subnet %s\n",
349 global_myname, registered_name->name, subrec->subnet_name));
350 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
351 return;
354 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
355 on subnet %s\n", work->work_group, subrec->subnet_name));
357 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
359 /* update our server status */
360 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
361 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
363 /* Tell the namelist writer to write out a change. */
364 subrec->work_changed = True;
366 /* Add this name to the workgroup as local master browser. */
367 set_workgroup_local_master_browser_name( work, global_myname);
369 /* Count the number of servers we have on our list. If it's
370 less than 10 (just a heuristic) request the servers
371 to announce themselves.
373 for( sl = work->serverlist; sl != NULL; sl = sl->next)
374 i++;
376 if (i < 10)
378 /* Ask all servers on our local net to announce to us. */
379 broadcast_announce_request(subrec, work);
383 * Now we are a local master on a broadcast subnet, we need to add
384 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
385 * unicast requests sent to this name. We can create this name directly on
386 * the unicast subnet as a WINS server always returns true when registering
387 * this name, and discards the registration. We use the number of IP
388 * addresses registered to this name as a reference count, as we
389 * remove this broadcast subnet IP address from it when we stop becoming a local
390 * master browser for this broadcast subnet.
393 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
395 /* Reset the announce master browser timer so that we try and tell a domain
396 master browser as soon as possible that we are a local master browser. */
397 reset_announce_timer();
399 if( DEBUGLVL( 0 ) )
401 dbgtext( "Samba name server %s is now a local master browser for workgroup %s "
402 "on subnet %s\n", global_myname, work->work_group, subrec->subnet_name );
407 /****************************************************************************
408 Failed to register the WORKGROUP<1d> name.
409 ****************************************************************************/
410 static void become_local_master_fail2(struct subnet_record *subrec,
411 struct response_record *rrec,
412 struct nmb_name *fail_name)
414 struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
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 if(!work)
421 DEBUG(0,("become_local_master_fail2: Error - cannot find \
422 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
423 return;
426 /* Roll back all the way by calling unbecome_local_master_browser(). */
427 unbecome_local_master_browser(subrec, work, False);
430 /****************************************************************************
431 Success in registering the MSBROWSE name.
432 ****************************************************************************/
434 static void become_local_master_stage1(struct subnet_record *subrec,
435 struct userdata_struct *userdata,
436 struct nmb_name *registered_name,
437 uint16 nb_flags,
438 int ttl, struct in_addr registered_ip)
440 char *work_name = userdata->data;
441 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
443 if(!work)
445 DEBUG(0,("become_local_master_stage1: Error - cannot find \
446 workgroup %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)
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)
491 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
492 in workgroup %s on subnet %s\n",
493 global_myname, work->work_group, subrec->subnet_name));
494 return;
497 reset_workgroup_state( subrec, work->work_group, False );
499 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
500 workgroup %s on subnet %s. Couldn't register name %s.\n",
501 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
504 /******************************************************************
505 Become the local master browser on a subnet.
506 This gets called if we win an election on this subnet.
508 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
509 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
510 Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
511 ******************************************************************/
513 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
515 struct userdata_struct *userdata;
516 int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
518 /* Sanity check. */
519 if (!lp_local_master())
521 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
522 return;
525 if(!AM_POTENTIAL_MASTER_BROWSER(work))
527 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
528 work->mst_state ));
529 return;
532 if(find_server_in_workgroup( work, global_myname) == NULL)
534 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
535 in workgroup %s on subnet %s\n",
536 global_myname, work->work_group, subrec->subnet_name));
537 return;
540 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
541 %s on subnet %s\n", work->work_group, subrec->subnet_name));
543 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
544 work->mst_state = MST_BACKUP; /* an election win was successful */
546 work->ElectionCriterion |= 0x5;
548 /* Tell the namelist writer to write out a change. */
549 subrec->work_changed = True;
551 /* Setup the userdata_struct. */
552 if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
554 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
555 return;
558 userdata->copy_fn = NULL;
559 userdata->free_fn = NULL;
560 userdata->userdata_len = strlen(work->work_group)+1;
561 pstrcpy(userdata->data, work->work_group);
563 /* Register the special browser group name. */
564 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
565 become_local_master_stage1,
566 become_local_master_fail1,
567 userdata);
569 zero_free(userdata, size);
572 /***************************************************************
573 Utility function to set the local master browser name. Does
574 some sanity checking as old versions of Samba seem to sometimes
575 say that the master browser name for a workgroup is the same
576 as the workgroup name.
577 ****************************************************************/
579 void set_workgroup_local_master_browser_name( struct work_record *work, char *newname)
581 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
582 for workgroup %s.\n", newname, work->work_group ));
584 #if 0
586 * Apparently some sites use the workgroup name as the local
587 * master browser name. Arrrrggghhhhh ! (JRA).
589 if(strequal( work->work_group, newname))
591 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
592 local_master_browser_name for workgroup %s to workgroup name.\n",
593 work->work_group ));
594 return;
596 #endif
598 StrnCpy(work->local_master_browser_name, newname,
599 sizeof(work->local_master_browser_name)-1);