2 Unix SMB/Netbios implementation.
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.
27 extern int DEBUGLEVEL;
29 extern pstring global_myname;
31 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
33 /*******************************************************************
34 Utility function to add a name to the unicast subnet, or add in
35 our IP address if it already exists.
36 ******************************************************************/
38 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
39 struct nmb_name *nmbname, uint16 nb_type )
41 struct name_record *namerec;
43 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
45 /* The name needs to be created on the unicast subnet. */
46 add_name_to_subnet( unicast_subnet, nmbname->name, nmbname->name_type,
47 nb_type, PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
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->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 )
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 ));
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;
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
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
127 make_nmb_name(&nmbname, work->work_group, 0x1d, scope);
129 remove_permanent_name_from_unicast( subrec, &nmbname);
133 /*******************************************************************
134 Unbecome the local master browser name release success function.
135 ******************************************************************/
137 void unbecome_local_master_success(struct subnet_record *subrec,
138 struct userdata_struct *userdata,
139 struct nmb_name *released_name,
140 struct in_addr released_ip)
142 DEBUG(3,("unbecome_local_master_success: released name %s.\n",
143 namestr(released_name)));
145 /* Now reset the workgroup and server state. */
146 reset_workgroup_state( subrec, released_name->name );
148 DEBUG(0,("\n%s ***** Samba name server %s has stopped being a local master browser for workgroup %s \
149 on subnet %s *****\n\n", timestring(), global_myname, released_name->name, subrec->subnet_name));
153 /*******************************************************************
154 Unbecome the local master browser name release fail function.
155 ******************************************************************/
157 void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
158 struct nmb_name *fail_name)
160 struct name_record *namerec;
162 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
163 Removing from namelist anyway.\n", namestr(fail_name)));
166 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
168 remove_name_from_namelist(subrec, namerec);
170 /* Now reset the workgroup and server state. */
171 reset_workgroup_state( subrec, fail_name->name );
173 DEBUG(0,("\n%s ***** Samba name server %s has stopped being a local master browser for workgroup %s \
174 on subnet %s *****\n\n", timestring(), global_myname, fail_name->name, subrec->subnet_name));
178 /*******************************************************************
179 Utility function to remove the WORKGROUP<1d> name called by both
180 success and fail of releasing the MSBROWSE name.
181 ******************************************************************/
183 void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
185 struct nmb_name nmbname;
186 struct name_record *namerec;
188 make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
189 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
191 release_name(subrec, namerec,
192 unbecome_local_master_success,
193 unbecome_local_master_fail,
198 /*******************************************************************
199 Unbecome the local master browser MSBROWSE name release success function.
200 ******************************************************************/
202 static void release_msbrowse_name_success(struct subnet_record *subrec,
203 struct userdata_struct *userdata,
204 struct nmb_name *released_name,
205 struct in_addr released_ip)
207 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
208 namestr(released_name), subrec->subnet_name ));
210 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
211 remove_permanent_name_from_unicast( subrec, released_name);
213 release_1d_name( subrec, userdata->data );
216 /*******************************************************************
217 Unbecome the local master browser MSBROWSE name release fail function.
218 ******************************************************************/
220 static void release_msbrowse_name_fail( struct subnet_record *subrec,
221 struct response_record *rrec,
222 struct nmb_name *fail_name)
224 struct userdata_struct *userdata = rrec->userdata;
225 struct name_record *namerec;
227 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
228 namestr(fail_name), subrec->subnet_name ));
230 /* Release the name anyway. */
231 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
233 remove_name_from_namelist(subrec, namerec);
235 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
236 remove_permanent_name_from_unicast( subrec, fail_name);
238 release_1d_name( subrec, userdata->data );
241 /*******************************************************************
242 Unbecome the local master browser.
243 ******************************************************************/
245 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work)
247 struct server_record *servrec;
248 struct name_record *namerec;
249 struct nmb_name nmbname;
250 struct userdata_struct *userdata;
254 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
255 on subnet %s\n",work->work_group, subrec->subnet_name));
257 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
259 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
260 in workgroup %s on subnet %s\n",
261 global_myname, work->work_group, subrec->subnet_name));
262 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
266 /* Set the state to unbecoming. */
267 work->mst_state = MST_UNBECOMING_MASTER;
269 /* Setup the userdata for the MSBROWSE name release. */
270 if((userdata = (struct userdata_struct *)malloc( sizeof(struct userdata_struct) + sizeof(fstring)+1)) == NULL)
272 DEBUG(0,("unbecome_local_master_browser: malloc fail.\n"));
276 userdata->copy_fn = NULL;
277 userdata->free_fn = NULL;
278 userdata->userdata_len = strlen(work->work_group)+1;
279 pstrcpy(userdata->data, work->work_group);
281 /* Deregister any browser names we may have. */
282 make_nmb_name(&nmbname, MSBROWSE, 0x1, scope);
283 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
285 release_name(subrec, namerec,
286 release_msbrowse_name_success,
287 release_msbrowse_name_fail,
291 free((char *)userdata);
294 /****************************************************************************
295 Success in registering the WORKGROUP<1d> name.
296 We are now *really* a local master browser.
297 ****************************************************************************/
299 static void become_local_master_stage2(struct subnet_record *subrec,
300 struct userdata_struct *userdata,
301 struct nmb_name *registered_name,
303 int ttl, struct in_addr registered_ip)
306 struct server_record *sl;
307 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
308 struct server_record *servrec;
312 DEBUG(0,("become_local_master_stage2: Error - cannot find \
313 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
317 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
319 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
320 in workgroup %s on subnet %s\n",
321 global_myname, registered_name->name, subrec->subnet_name));
322 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
326 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
327 on subnet %s\n", work->work_group, subrec->subnet_name));
329 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
331 /* update our server status */
332 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
333 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
335 /* Tell the namelist writer to write out a change. */
336 subrec->work_changed = True;
338 /* Add this name to the workgroup as local master browser. */
339 set_workgroup_local_master_browser_name( work, global_myname);
341 /* Count the number of servers we have on our list. If it's
342 less than 10 (just a heuristic) request the servers
343 to announce themselves.
345 for( sl = work->serverlist; sl != NULL; sl = sl->next)
350 /* Ask all servers on our local net to announce to us. */
351 broadcast_announce_request(subrec, work);
355 * Now we are a local master on a broadcast subnet, we need to add
356 * the WORKGROUP<1d> name to the unicast subnet so that we can answer
357 * unicast requests sent to this name. We can create this name directly on
358 * the unicast subnet as a WINS server always returns true when registering
359 * this name, and discards the registration. We use the number of IP
360 * addresses registered to this name as a reference count, as we
361 * remove this broadcast subnet IP address from it when we stop becoming a local
362 * master browser for this broadcast subnet.
365 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
367 /* Reset the announce master browser timer so that we try and tell a domain
368 master browser as soon as possible that we are a local master browser. */
369 reset_announce_timer();
371 DEBUG(0,("\n%s ***** Samba name server %s is now a local master browser for workgroup %s \
372 on subnet %s *****\n\n", timestring(), global_myname, work->work_group, subrec->subnet_name));
376 /****************************************************************************
377 Failed to register the WORKGROUP<1d> name.
378 ****************************************************************************/
379 static void become_local_master_fail2(struct subnet_record *subrec,
380 struct response_record *rrec,
381 struct nmb_name *fail_name)
383 struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
385 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
386 Failed to become a local master browser.\n", namestr(fail_name), subrec->subnet_name));
390 DEBUG(0,("become_local_master_fail2: Error - cannot find \
391 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
395 /* Roll back all the way by calling unbecome_local_master_browser(). */
396 unbecome_local_master_browser(subrec, work);
399 /****************************************************************************
400 Success in registering the MSBROWSE name.
401 ****************************************************************************/
403 static void become_local_master_stage1(struct subnet_record *subrec,
404 struct userdata_struct *userdata,
405 struct nmb_name *registered_name,
407 int ttl, struct in_addr registered_ip)
409 char *work_name = userdata->data;
410 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
414 DEBUG(0,("become_local_master_stage1: Error - cannot find \
415 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
419 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
422 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
425 * We registered the MSBROWSE name on a broadcast subnet, now need to add
426 * the MSBROWSE name to the unicast subnet so that we can answer
427 * unicast requests sent to this name. We create this name directly on
428 * the unicast subnet.
431 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
433 /* Attempt to register the WORKGROUP<1d> name. */
434 register_name(subrec, work->work_group,0x1d,samba_nb_type,
435 become_local_master_stage2,
436 become_local_master_fail2,
440 /****************************************************************************
441 Failed to register the MSBROWSE name.
442 ****************************************************************************/
444 static void become_local_master_fail1(struct subnet_record *subrec,
445 struct response_record *rrec,
446 struct nmb_name *fail_name)
448 char *work_name = rrec->userdata->data;
449 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
450 struct server_record *servrec;
454 DEBUG(0,("become_local_master_fail1: Error - cannot find \
455 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
459 if((servrec = find_server_in_workgroup(work, global_myname)) == NULL)
461 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
462 in workgroup %s on subnet %s\n",
463 global_myname, work->work_group, subrec->subnet_name));
467 reset_workgroup_state( subrec, work->work_group );
469 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
470 workgroup %s on subnet %s. Couldn't register name %s.\n",
471 work->work_group, subrec->subnet_name, namestr(fail_name)));
474 /******************************************************************
475 Become the local master browser on a subnet.
476 This gets called if we win an election on this subnet.
478 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
479 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
480 Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
481 ******************************************************************/
483 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
485 struct server_record *servrec;
486 struct userdata_struct *userdata;
489 if (!lp_local_master())
491 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
495 if(!AM_POTENTIAL_MASTER_BROWSER(work))
497 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
502 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
504 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
505 in workgroup %s on subnet %s\n",
506 global_myname, work->work_group, subrec->subnet_name));
510 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
511 %s on subnet %s\n", work->work_group, subrec->subnet_name));
513 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
514 work->mst_state = MST_BACKUP; /* an election win was successful */
516 work->ElectionCriterion |= 0x5;
518 /* Tell the namelist writer to write out a change. */
519 subrec->work_changed = True;
521 /* Setup the userdata_struct. */
522 if((userdata = (struct userdata_struct *)malloc(sizeof(struct userdata_struct) + sizeof(fstring)+1)) == NULL)
524 DEBUG(0,("become_local_master_browser: malloc fail.\n"));
528 userdata->copy_fn = NULL;
529 userdata->free_fn = NULL;
530 userdata->userdata_len = strlen(work->work_group)+1;
531 pstrcpy(userdata->data, work->work_group);
533 /* Register the special browser group name. */
534 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
535 become_local_master_stage1,
536 become_local_master_fail1,
539 free((char *)userdata);
542 /***************************************************************
543 Utility function to set the local master browser name. Does
544 some sanity checking as old versions of Samba seem to sometimes
545 say that the master browser name for a workgroup is the same
546 as the workgroup name.
547 ****************************************************************/
549 void set_workgroup_local_master_browser_name( struct work_record *work, char *newname)
551 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
552 for workgroup %s.\n", newname, work->work_group ));
556 * Apparently some sites use the workgroup name as the local
557 * master browser name. Arrrrggghhhhh ! (JRA).
559 if(strequal( work->work_group, newname))
561 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
562 local_master_browser_name for workgroup %s to workgroup name.\n",
568 StrnCpy(work->local_master_browser_name, newname,
569 sizeof(work->local_master_browser_name)-1);