Fix bug #10097 - MacOSX 10.9 will not follow path-based DFS referrals handed out...
[Samba.git] / source3 / nmbd / nmbd_become_lmb.c
blobffd92cf0d8ff8f8996f918d14a00e2c4809ac80c
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"
24 #include "nmbd/nmbd.h"
25 #include "../librpc/gen_ndr/svcctl.h"
27 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
29 /*******************************************************************
30 Utility function to add a name to the unicast subnet, or add in
31 our IP address if it already exists.
32 ******************************************************************/
34 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
35 struct nmb_name *nmbname, uint16 nb_type )
37 unstring name;
38 struct name_record *namerec;
40 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
41 pull_ascii_nstring(name, sizeof(name), nmbname->name);
42 /* The name needs to be created on the unicast subnet. */
43 (void)add_name_to_subnet( unicast_subnet, name,
44 nmbname->name_type, nb_type,
45 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
46 } else {
47 /* The name already exists on the unicast subnet. Add our local
48 IP for the given broadcast subnet to the name. */
49 add_ip_to_name_record( namerec, subrec->myip);
53 /*******************************************************************
54 Utility function to remove a name from the unicast subnet.
55 ******************************************************************/
57 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
58 struct nmb_name *nmbname )
60 struct name_record *namerec;
62 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
63 /* Remove this broadcast subnet IP address from the name. */
64 remove_ip_from_name_record( namerec, subrec->myip);
65 if(namerec->data.num_ips == 0)
66 remove_name_from_namelist( unicast_subnet, namerec);
70 /*******************************************************************
71 Utility function always called to set our workgroup and server
72 state back to potential browser, or none.
73 ******************************************************************/
75 static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
76 bool force_new_election )
78 struct work_record *work;
79 struct server_record *servrec;
80 struct nmb_name nmbname;
82 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
83 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
84 subnet %s.\n", workgroup_name, subrec->subnet_name ));
85 return;
88 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
89 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
90 in workgroup %s on subnet %s\n",
91 global_myname(), work->work_group, subrec->subnet_name));
92 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
93 return;
96 /* Update our server status - remove any master flag and replace
97 it with the potential browser flag. */
98 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
99 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
101 /* Tell the namelist writer to write out a change. */
102 subrec->work_changed = True;
104 /* Reset our election flags. */
105 work->ElectionCriterion &= ~0x4;
107 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
109 /* Forget who the local master browser was for
110 this workgroup. */
112 set_workgroup_local_master_browser_name( work, "");
115 * Ensure the IP address of this subnet is not registered as one
116 * of the IP addresses of the WORKGROUP<1d> name on the unicast
117 * subnet. This undoes what we did below when we became a local
118 * master browser.
121 make_nmb_name(&nmbname, work->work_group, 0x1d);
123 remove_permanent_name_from_unicast( subrec, &nmbname);
125 if(force_new_election)
126 work->needelection = True;
129 /*******************************************************************
130 Unbecome the local master browser name release success function.
131 ******************************************************************/
133 static void unbecome_local_master_success(struct subnet_record *subrec,
134 struct userdata_struct *userdata,
135 struct nmb_name *released_name,
136 struct in_addr released_ip)
138 bool force_new_election = False;
139 unstring relname;
141 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
143 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
144 nmb_namestr(released_name)));
146 /* Now reset the workgroup and server state. */
147 pull_ascii_nstring(relname, sizeof(relname), released_name->name);
148 reset_workgroup_state( subrec, relname, force_new_election );
150 if( DEBUGLVL( 0 ) ) {
151 dbgtext( "*****\n\n" );
152 dbgtext( "Samba name server %s ", global_myname() );
153 dbgtext( "has stopped being a local master browser " );
154 dbgtext( "for workgroup %s ", relname );
155 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
160 /*******************************************************************
161 Unbecome the local master browser name release fail function.
162 ******************************************************************/
164 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
165 struct nmb_name *fail_name)
167 struct name_record *namerec;
168 struct userdata_struct *userdata = rrec->userdata;
169 bool force_new_election = False;
170 unstring failname;
172 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
174 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
175 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
177 /* Do it anyway. */
178 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
179 if(namerec)
180 remove_name_from_namelist(subrec, namerec);
182 /* Now reset the workgroup and server state. */
183 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
184 reset_workgroup_state( subrec, failname, force_new_election );
186 if( DEBUGLVL( 0 ) ) {
187 dbgtext( "*****\n\n" );
188 dbgtext( "Samba name server %s ", global_myname() );
189 dbgtext( "has stopped being a local master browser " );
190 dbgtext( "for workgroup %s ", failname );
191 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
195 /*******************************************************************
196 Utility function to remove the WORKGROUP<1d> name.
197 ******************************************************************/
199 static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
200 bool force_new_election)
202 struct nmb_name nmbname;
203 struct name_record *namerec;
205 make_nmb_name(&nmbname, workgroup_name, 0x1d);
206 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
207 struct userdata_struct *userdata;
208 size_t size = sizeof(struct userdata_struct) + sizeof(bool);
210 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
211 DEBUG(0,("release_1d_name: malloc fail.\n"));
212 return;
215 userdata->copy_fn = NULL;
216 userdata->free_fn = NULL;
217 userdata->userdata_len = sizeof(bool);
218 memcpy((char *)userdata->data, &force_new_election, sizeof(bool));
220 release_name(subrec, namerec,
221 unbecome_local_master_success,
222 unbecome_local_master_fail,
223 userdata);
225 zero_free(userdata, size);
229 /*******************************************************************
230 Unbecome the local master browser MSBROWSE name release success function.
231 ******************************************************************/
233 static void release_msbrowse_name_success(struct subnet_record *subrec,
234 struct userdata_struct *userdata,
235 struct nmb_name *released_name,
236 struct in_addr released_ip)
238 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
239 nmb_namestr(released_name), subrec->subnet_name ));
241 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
242 remove_permanent_name_from_unicast( subrec, released_name);
245 /*******************************************************************
246 Unbecome the local master browser MSBROWSE name release fail function.
247 ******************************************************************/
249 static void release_msbrowse_name_fail( struct subnet_record *subrec,
250 struct response_record *rrec,
251 struct nmb_name *fail_name)
253 struct name_record *namerec;
255 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
256 nmb_namestr(fail_name), subrec->subnet_name ));
258 /* Release the name anyway. */
259 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
260 if(namerec)
261 remove_name_from_namelist(subrec, namerec);
263 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
264 remove_permanent_name_from_unicast( subrec, fail_name);
267 /*******************************************************************
268 Unbecome the local master browser. If force_new_election is true, restart
269 the election process after we've unbecome the local master.
270 ******************************************************************/
272 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
273 bool force_new_election)
275 struct name_record *namerec;
276 struct nmb_name nmbname;
278 /* Sanity check. */
280 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
281 on subnet %s\n",work->work_group, subrec->subnet_name));
283 if(find_server_in_workgroup( work, global_myname()) == NULL) {
284 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
285 in workgroup %s on subnet %s\n",
286 global_myname(), work->work_group, subrec->subnet_name));
287 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
288 return;
291 /* Set the state to unbecoming. */
292 work->mst_state = MST_UNBECOMING_MASTER;
295 * Release the WORKGROUP<1d> name asap to allow another machine to
296 * claim it.
299 release_1d_name( subrec, work->work_group, force_new_election);
301 /* Deregister any browser names we may have. */
302 make_nmb_name(&nmbname, MSBROWSE, 0x1);
303 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
304 release_name(subrec, namerec,
305 release_msbrowse_name_success,
306 release_msbrowse_name_fail,
307 NULL);
311 * Ensure we have sent and processed these release packets
312 * before returning - we don't want to process any election
313 * packets before dealing with the 1d release.
316 retransmit_or_expire_response_records(time(NULL));
319 /****************************************************************************
320 Success in registering the WORKGROUP<1d> name.
321 We are now *really* a local master browser.
322 ****************************************************************************/
324 static void become_local_master_stage2(struct subnet_record *subrec,
325 struct userdata_struct *userdata,
326 struct nmb_name *registered_name,
327 uint16 nb_flags,
328 int ttl, struct in_addr registered_ip)
330 int i = 0;
331 struct server_record *sl;
332 struct work_record *work;
333 struct server_record *servrec;
334 unstring regname;
336 pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
337 work = find_workgroup_on_subnet( subrec, regname);
339 if(!work) {
340 DEBUG(0,("become_local_master_stage2: Error - cannot find \
341 workgroup %s on subnet %s\n", regname, subrec->subnet_name));
342 return;
345 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
346 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
347 in workgroup %s on subnet %s\n",
348 global_myname(), regname, subrec->subnet_name));
349 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
350 return;
353 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
354 on subnet %s\n", work->work_group, subrec->subnet_name));
356 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
358 /* update our server status */
359 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
360 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
362 /* Tell the namelist writer to write out a change. */
363 subrec->work_changed = True;
365 /* Add this name to the workgroup as local master browser. */
366 set_workgroup_local_master_browser_name( work, global_myname());
368 /* Count the number of servers we have on our list. If it's
369 less than 10 (just a heuristic) request the servers
370 to announce themselves.
372 for( sl = work->serverlist; sl != NULL; sl = sl->next)
373 i++;
375 if (i < 10) {
376 /* Ask all servers on our local net to announce to us. */
377 broadcast_announce_request(subrec, work);
381 * Now we are a local master on a broadcast subnet, we need to add
382 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
383 * unicast requests sent to this name. We can create this name directly on
384 * the unicast subnet as a WINS server always returns true when registering
385 * this name, and discards the registration. We use the number of IP
386 * addresses registered to this name as a reference count, as we
387 * remove this broadcast subnet IP address from it when we stop becoming a local
388 * master browser for this broadcast subnet.
391 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
393 /* Reset the announce master browser timer so that we try and tell a domain
394 master browser as soon as possible that we are a local master browser. */
395 reset_announce_timer();
397 if( DEBUGLVL( 0 ) ) {
398 dbgtext( "*****\n\n" );
399 dbgtext( "Samba name server %s ", global_myname() );
400 dbgtext( "is now a local master browser " );
401 dbgtext( "for workgroup %s ", work->work_group );
402 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
406 /****************************************************************************
407 Failed to register the WORKGROUP<1d> name.
408 ****************************************************************************/
410 static void become_local_master_fail2(struct subnet_record *subrec,
411 struct response_record *rrec,
412 struct nmb_name *fail_name)
414 unstring failname;
415 struct work_record *work;
417 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
418 Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
420 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
421 work = find_workgroup_on_subnet( subrec, failname);
423 if(!work) {
424 DEBUG(0,("become_local_master_fail2: Error - cannot find \
425 workgroup %s on subnet %s\n", failname, subrec->subnet_name));
426 return;
429 /* Roll back all the way by calling unbecome_local_master_browser(). */
430 unbecome_local_master_browser(subrec, work, False);
433 /****************************************************************************
434 Success in registering the MSBROWSE name.
435 ****************************************************************************/
437 static void become_local_master_stage1(struct subnet_record *subrec,
438 struct userdata_struct *userdata,
439 struct nmb_name *registered_name,
440 uint16 nb_flags,
441 int ttl, struct in_addr registered_ip)
443 char *work_name = userdata->data;
444 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
446 if(!work) {
447 DEBUG(0,("become_local_master_stage1: Error - cannot find \
448 %s on subnet %s\n", work_name, subrec->subnet_name));
449 return;
452 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
453 work->work_group));
455 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
458 * We registered the MSBROWSE name on a broadcast subnet, now need to add
459 * the MSBROWSE name to the unicast subnet so that we can answer
460 * unicast requests sent to this name. We create this name directly on
461 * the unicast subnet.
464 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
466 /* Attempt to register the WORKGROUP<1d> name. */
467 register_name(subrec, work->work_group,0x1d,samba_nb_type,
468 become_local_master_stage2,
469 become_local_master_fail2,
470 NULL);
473 /****************************************************************************
474 Failed to register the MSBROWSE name.
475 ****************************************************************************/
477 static void become_local_master_fail1(struct subnet_record *subrec,
478 struct response_record *rrec,
479 struct nmb_name *fail_name)
481 char *work_name = rrec->userdata->data;
482 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
484 if(!work) {
485 DEBUG(0,("become_local_master_fail1: Error - cannot find \
486 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
487 return;
490 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 size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
518 /* Sanity check. */
519 if (!lp_local_master()) {
520 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
521 return;
524 if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
525 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
526 work->mst_state ));
527 return;
530 if(find_server_in_workgroup( work, global_myname()) == NULL) {
531 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
532 in workgroup %s on subnet %s\n",
533 global_myname(), work->work_group, subrec->subnet_name));
534 return;
537 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
538 %s on subnet %s\n", work->work_group, subrec->subnet_name));
540 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
541 work->mst_state = MST_BACKUP; /* an election win was successful */
543 work->ElectionCriterion |= 0x5;
545 /* Tell the namelist writer to write out a change. */
546 subrec->work_changed = True;
548 /* Setup the userdata_struct. */
549 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
550 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
551 return;
554 userdata->copy_fn = NULL;
555 userdata->free_fn = NULL;
556 userdata->userdata_len = strlen(work->work_group)+1;
557 overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
559 /* Register the special browser group name. */
560 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
561 become_local_master_stage1,
562 become_local_master_fail1,
563 userdata);
565 zero_free(userdata, size);
568 /***************************************************************
569 Utility function to set the local master browser name. Does
570 some sanity checking as old versions of Samba seem to sometimes
571 say that the master browser name for a workgroup is the same
572 as the workgroup name.
573 ****************************************************************/
575 void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
577 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
578 for workgroup %s.\n", newname, work->work_group ));
580 #if 0
582 * Apparently some sites use the workgroup name as the local
583 * master browser name. Arrrrggghhhhh ! (JRA).
585 if(strequal( work->work_group, newname))
587 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
588 local_master_browser_name for workgroup %s to workgroup name.\n",
589 work->work_group ));
590 return;
592 #endif
594 unstrcpy(work->local_master_browser_name, newname);