Line data Source code
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
7 :
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.
12 :
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.
17 :
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/>.
20 :
21 : */
22 :
23 : #include "includes.h"
24 : #include "nmbd/nmbd.h"
25 : #include "../librpc/gen_ndr/svcctl.h"
26 : #include "lib/util/string_wrappers.h"
27 :
28 : extern uint16_t samba_nb_type; /* Samba's NetBIOS name type. */
29 :
30 : /*******************************************************************
31 : Utility function to add a name to the unicast subnet, or add in
32 : our IP address if it already exists.
33 : ******************************************************************/
34 :
35 312 : void insert_permanent_name_into_unicast( struct subnet_record *subrec,
36 : struct nmb_name *nmbname, uint16_t nb_type )
37 : {
38 : unstring name;
39 : struct name_record *namerec;
40 :
41 312 : if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
42 312 : pull_ascii_nstring(name, sizeof(name), nmbname->name);
43 : /* The name needs to be created on the unicast subnet. */
44 312 : (void)add_name_to_subnet( unicast_subnet, name,
45 312 : nmbname->name_type, nb_type,
46 : PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
47 : } else {
48 : /* The name already exists on the unicast subnet. Add our local
49 : IP for the given broadcast subnet to the name. */
50 0 : add_ip_to_name_record( namerec, subrec->myip);
51 : }
52 312 : }
53 :
54 : /*******************************************************************
55 : Utility function to remove a name from the unicast subnet.
56 : ******************************************************************/
57 :
58 4 : static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
59 : struct nmb_name *nmbname )
60 : {
61 : struct name_record *namerec;
62 :
63 4 : if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
64 : /* Remove this broadcast subnet IP address from the name. */
65 4 : remove_ip_from_name_record( namerec, subrec->myip);
66 4 : if(namerec->data.num_ips == 0)
67 4 : remove_name_from_namelist( unicast_subnet, namerec);
68 : }
69 4 : }
70 :
71 : /*******************************************************************
72 : Utility function always called to set our workgroup and server
73 : state back to potential browser, or none.
74 : ******************************************************************/
75 :
76 2 : static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
77 : bool force_new_election )
78 : {
79 : struct work_record *work;
80 : struct server_record *servrec;
81 : struct nmb_name nmbname;
82 :
83 2 : if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
84 0 : DBG_ERR("reset_workgroup_state: Error - cannot find workgroup %s on \
85 : subnet %s.\n", workgroup_name, subrec->subnet_name );
86 0 : return;
87 : }
88 :
89 2 : if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
90 0 : DBG_ERR("reset_workgroup_state: Error - cannot find server %s \
91 : in workgroup %s on subnet %s\n",
92 : lp_netbios_name(), work->work_group, subrec->subnet_name);
93 0 : work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
94 0 : return;
95 : }
96 :
97 : /* Update our server status - remove any master flag and replace
98 : it with the potential browser flag. */
99 2 : servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
100 2 : servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
101 :
102 : /* Tell the namelist writer to write out a change. */
103 2 : subrec->work_changed = True;
104 :
105 : /* Reset our election flags. */
106 2 : work->ElectionCriterion &= ~0x4;
107 :
108 2 : work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
109 :
110 : /* Forget who the local master browser was for
111 : this workgroup. */
112 :
113 2 : set_workgroup_local_master_browser_name( work, "");
114 :
115 : /*
116 : * Ensure the IP address of this subnet is not registered as one
117 : * of the IP addresses of the WORKGROUP<1d> name on the unicast
118 : * subnet. This undoes what we did below when we became a local
119 : * master browser.
120 : */
121 :
122 2 : make_nmb_name(&nmbname, work->work_group, 0x1d);
123 :
124 2 : remove_permanent_name_from_unicast( subrec, &nmbname);
125 :
126 2 : if(force_new_election)
127 0 : work->needelection = True;
128 : }
129 :
130 : /*******************************************************************
131 : Unbecome the local master browser name release success function.
132 : ******************************************************************/
133 :
134 2 : static void unbecome_local_master_success(struct subnet_record *subrec,
135 : struct userdata_struct *userdata,
136 : struct nmb_name *released_name,
137 : struct in_addr released_ip)
138 : {
139 2 : bool force_new_election = False;
140 : unstring relname;
141 :
142 2 : memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
143 :
144 2 : DBG_NOTICE("unbecome_local_master_success: released name %s.\n",
145 : nmb_namestr(released_name));
146 :
147 : /* Now reset the workgroup and server state. */
148 2 : pull_ascii_nstring(relname, sizeof(relname), released_name->name);
149 2 : reset_workgroup_state( subrec, relname, force_new_election );
150 :
151 2 : DBG_WARNING("*****\n\n"
152 : "Samba name server %s has stopped being a local master browser "
153 : "for workgroup %s on subnet %s\n\n*****\n",
154 : lp_netbios_name(), relname, subrec->subnet_name );
155 :
156 2 : }
157 :
158 : /*******************************************************************
159 : Unbecome the local master browser name release fail function.
160 : ******************************************************************/
161 :
162 0 : static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
163 : struct nmb_name *fail_name)
164 : {
165 : struct name_record *namerec;
166 0 : struct userdata_struct *userdata = rrec->userdata;
167 0 : bool force_new_election = False;
168 : unstring failname;
169 :
170 0 : memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
171 :
172 0 : DBG_WARNING("unbecome_local_master_fail: failed to release name %s. "
173 : "Removing from namelist anyway.\n", nmb_namestr(fail_name));
174 :
175 : /* Do it anyway. */
176 0 : namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
177 0 : if(namerec)
178 0 : remove_name_from_namelist(subrec, namerec);
179 :
180 : /* Now reset the workgroup and server state. */
181 0 : pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
182 0 : reset_workgroup_state( subrec, failname, force_new_election );
183 :
184 0 : DBG_WARNING("*****\n\n"
185 : "Samba name server %s has stopped being a local master browser "
186 : "for workgroup %s on subnet %s\n\n*****\n",
187 : lp_netbios_name(), failname, subrec->subnet_name);
188 0 : }
189 :
190 : /*******************************************************************
191 : Utility function to remove the WORKGROUP<1d> name.
192 : ******************************************************************/
193 :
194 2 : static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
195 : bool force_new_election)
196 : {
197 : struct nmb_name nmbname;
198 : struct name_record *namerec;
199 :
200 2 : make_nmb_name(&nmbname, workgroup_name, 0x1d);
201 2 : if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
202 : struct userdata_struct *userdata;
203 2 : size_t size = sizeof(struct userdata_struct) + sizeof(bool);
204 :
205 2 : if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
206 0 : DBG_ERR("release_1d_name: malloc fail.\n");
207 0 : return;
208 : }
209 :
210 2 : userdata->copy_fn = NULL;
211 2 : userdata->free_fn = NULL;
212 2 : userdata->userdata_len = sizeof(bool);
213 2 : memcpy((char *)userdata->data, &force_new_election, sizeof(bool));
214 :
215 2 : release_name(subrec, namerec,
216 : unbecome_local_master_success,
217 : unbecome_local_master_fail,
218 : userdata);
219 :
220 2 : zero_free(userdata, size);
221 : }
222 : }
223 :
224 : /*******************************************************************
225 : Unbecome the local master browser MSBROWSE name release success function.
226 : ******************************************************************/
227 :
228 2 : static void release_msbrowse_name_success(struct subnet_record *subrec,
229 : struct userdata_struct *userdata,
230 : struct nmb_name *released_name,
231 : struct in_addr released_ip)
232 : {
233 2 : DBG_INFO("release_msbrowse_name_success: Released name %s on subnet %s\n.",
234 : nmb_namestr(released_name), subrec->subnet_name );
235 :
236 : /* Remove the permanent MSBROWSE name added into the unicast subnet. */
237 2 : remove_permanent_name_from_unicast( subrec, released_name);
238 2 : }
239 :
240 : /*******************************************************************
241 : Unbecome the local master browser MSBROWSE name release fail function.
242 : ******************************************************************/
243 :
244 0 : static void release_msbrowse_name_fail( struct subnet_record *subrec,
245 : struct response_record *rrec,
246 : struct nmb_name *fail_name)
247 : {
248 : struct name_record *namerec;
249 :
250 0 : DBG_INFO("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
251 : nmb_namestr(fail_name), subrec->subnet_name );
252 :
253 : /* Release the name anyway. */
254 0 : namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
255 0 : if(namerec)
256 0 : remove_name_from_namelist(subrec, namerec);
257 :
258 : /* Remove the permanent MSBROWSE name added into the unicast subnet. */
259 0 : remove_permanent_name_from_unicast( subrec, fail_name);
260 0 : }
261 :
262 : /*******************************************************************
263 : Unbecome the local master browser. If force_new_election is true, restart
264 : the election process after we've unbecome the local master.
265 : ******************************************************************/
266 :
267 2 : void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
268 : bool force_new_election)
269 : {
270 : struct name_record *namerec;
271 : struct nmb_name nmbname;
272 :
273 : /* Sanity check. */
274 :
275 2 : DBG_NOTICE("unbecome_local_master_browser: unbecoming local master for workgroup %s \
276 : on subnet %s\n",work->work_group, subrec->subnet_name);
277 :
278 2 : if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) {
279 0 : DBG_WARNING("unbecome_local_master_browser: Error - cannot find server %s \
280 : in workgroup %s on subnet %s\n",
281 : lp_netbios_name(), work->work_group, subrec->subnet_name);
282 0 : work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
283 0 : return;
284 : }
285 :
286 : /* Set the state to unbecoming. */
287 2 : work->mst_state = MST_UNBECOMING_MASTER;
288 :
289 : /*
290 : * Release the WORKGROUP<1d> name asap to allow another machine to
291 : * claim it.
292 : */
293 :
294 2 : release_1d_name( subrec, work->work_group, force_new_election);
295 :
296 : /* Deregister any browser names we may have. */
297 2 : make_nmb_name(&nmbname, MSBROWSE, 0x1);
298 2 : if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
299 2 : release_name(subrec, namerec,
300 : release_msbrowse_name_success,
301 : release_msbrowse_name_fail,
302 : NULL);
303 : }
304 :
305 : /*
306 : * Ensure we have sent and processed these release packets
307 : * before returning - we don't want to process any election
308 : * packets before dealing with the 1d release.
309 : */
310 :
311 2 : retransmit_or_expire_response_records(time(NULL));
312 : }
313 :
314 : /****************************************************************************
315 : Success in registering the WORKGROUP<1d> name.
316 : We are now *really* a local master browser.
317 : ****************************************************************************/
318 :
319 29 : static void become_local_master_stage2(struct subnet_record *subrec,
320 : struct userdata_struct *userdata,
321 : struct nmb_name *registered_name,
322 : uint16_t nb_flags,
323 : int ttl, struct in_addr registered_ip)
324 : {
325 29 : int i = 0;
326 : struct server_record *sl;
327 : struct work_record *work;
328 : struct server_record *servrec;
329 : unstring regname;
330 :
331 29 : pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
332 29 : work = find_workgroup_on_subnet( subrec, regname);
333 :
334 29 : if(!work) {
335 0 : DBG_WARNING("become_local_master_stage2: Error - cannot find \
336 : workgroup %s on subnet %s\n", regname, subrec->subnet_name);
337 0 : return;
338 : }
339 :
340 29 : if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
341 0 : DBG_WARNING("become_local_master_stage2: Error - cannot find server %s \
342 : in workgroup %s on subnet %s\n",
343 : lp_netbios_name(), regname, subrec->subnet_name);
344 0 : work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
345 0 : return;
346 : }
347 :
348 29 : DBG_NOTICE("become_local_master_stage2: registered as master browser for workgroup %s \
349 : on subnet %s\n", work->work_group, subrec->subnet_name);
350 :
351 29 : work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
352 :
353 : /* update our server status */
354 29 : servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
355 29 : servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
356 :
357 : /* Tell the namelist writer to write out a change. */
358 29 : subrec->work_changed = True;
359 :
360 : /* Add this name to the workgroup as local master browser. */
361 29 : set_workgroup_local_master_browser_name( work, lp_netbios_name());
362 :
363 : /* Count the number of servers we have on our list. If it's
364 : less than 10 (just a heuristic) request the servers
365 : to announce themselves.
366 : */
367 62 : for( sl = work->serverlist; sl != NULL; sl = sl->next)
368 33 : i++;
369 :
370 29 : if (i < 10) {
371 : /* Ask all servers on our local net to announce to us. */
372 29 : broadcast_announce_request(subrec, work);
373 : }
374 :
375 : /*
376 : * Now we are a local master on a broadcast subnet, we need to add
377 : * the WORKGROUP<1d> name to the unicast subnet so that we can answer
378 : * unicast requests sent to this name. We can create this name directly on
379 : * the unicast subnet as a WINS server always returns true when registering
380 : * this name, and discards the registration. We use the number of IP
381 : * addresses registered to this name as a reference count, as we
382 : * remove this broadcast subnet IP address from it when we stop becoming a local
383 : * master browser for this broadcast subnet.
384 : */
385 :
386 29 : insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
387 :
388 : /* Reset the announce master browser timer so that we try and tell a domain
389 : master browser as soon as possible that we are a local master browser. */
390 29 : reset_announce_timer();
391 :
392 29 : DBG_WARNING( "*****\n\n"
393 : "Samba name server %s is now a local master browser "
394 : "for workgroup %s on subnet %s\n\n*****\n",
395 : lp_netbios_name(), work->work_group, subrec->subnet_name );
396 : }
397 :
398 : /****************************************************************************
399 : Failed to register the WORKGROUP<1d> name.
400 : ****************************************************************************/
401 :
402 0 : static void become_local_master_fail2(struct subnet_record *subrec,
403 : struct response_record *rrec,
404 : struct nmb_name *fail_name)
405 : {
406 : unstring failname;
407 : struct work_record *work;
408 :
409 0 : DBG_WARNING("become_local_master_fail2: failed to register name %s on subnet %s. \
410 : Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name);
411 :
412 0 : pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
413 0 : work = find_workgroup_on_subnet( subrec, failname);
414 :
415 0 : if(!work) {
416 0 : DBG_WARNING("become_local_master_fail2: Error - cannot find \
417 : workgroup %s on subnet %s\n", failname, subrec->subnet_name);
418 0 : return;
419 : }
420 :
421 : /* Roll back all the way by calling unbecome_local_master_browser(). */
422 0 : unbecome_local_master_browser(subrec, work, False);
423 : }
424 :
425 : /****************************************************************************
426 : Success in registering the MSBROWSE name.
427 : ****************************************************************************/
428 :
429 29 : static void become_local_master_stage1(struct subnet_record *subrec,
430 : struct userdata_struct *userdata,
431 : struct nmb_name *registered_name,
432 : uint16_t nb_flags,
433 : int ttl, struct in_addr registered_ip)
434 : {
435 29 : char *work_name = userdata->data;
436 29 : struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
437 :
438 29 : if(!work) {
439 0 : DBG_WARNING("become_local_master_stage1: Error - cannot find \
440 : %s on subnet %s\n", work_name, subrec->subnet_name);
441 0 : return;
442 : }
443 :
444 29 : DBG_NOTICE("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
445 : work->work_group);
446 :
447 29 : work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
448 :
449 : /*
450 : * We registered the MSBROWSE name on a broadcast subnet, now need to add
451 : * the MSBROWSE name to the unicast subnet so that we can answer
452 : * unicast requests sent to this name. We create this name directly on
453 : * the unicast subnet.
454 : */
455 :
456 29 : insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
457 :
458 : /* Attempt to register the WORKGROUP<1d> name. */
459 29 : register_name(subrec, work->work_group,0x1d,samba_nb_type,
460 : become_local_master_stage2,
461 : become_local_master_fail2,
462 : NULL);
463 : }
464 :
465 : /****************************************************************************
466 : Failed to register the MSBROWSE name.
467 : ****************************************************************************/
468 :
469 0 : static void become_local_master_fail1(struct subnet_record *subrec,
470 : struct response_record *rrec,
471 : struct nmb_name *fail_name)
472 : {
473 0 : char *work_name = rrec->userdata->data;
474 0 : struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
475 :
476 0 : if(!work) {
477 0 : DBG_WARNING("become_local_master_fail1: Error - cannot find \
478 : workgroup %s on subnet %s\n", work_name, subrec->subnet_name);
479 0 : return;
480 : }
481 :
482 0 : if(find_server_in_workgroup(work, lp_netbios_name()) == NULL) {
483 0 : DBG_WARNING("become_local_master_fail1: Error - cannot find server %s \
484 : in workgroup %s on subnet %s\n",
485 : lp_netbios_name(), work->work_group, subrec->subnet_name);
486 0 : return;
487 : }
488 :
489 0 : reset_workgroup_state( subrec, work->work_group, False );
490 :
491 0 : DBG_WARNING("become_local_master_fail1: Failed to become a local master browser for \
492 : workgroup %s on subnet %s. Couldn't register name %s.\n",
493 : work->work_group, subrec->subnet_name, nmb_namestr(fail_name));
494 : }
495 :
496 : /******************************************************************
497 : Become the local master browser on a subnet.
498 : This gets called if we win an election on this subnet.
499 :
500 : Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
501 : Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
502 : Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
503 : ******************************************************************/
504 :
505 32 : void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
506 : {
507 : struct userdata_struct *userdata;
508 32 : size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
509 :
510 : /* Sanity check. */
511 32 : if (!lp_local_master()) {
512 0 : DBG_WARNING("become_local_master_browser: Samba not configured as a local master browser.\n");
513 0 : return;
514 : }
515 :
516 32 : if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
517 2 : DBG_NOTICE("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
518 : work->mst_state );
519 2 : return;
520 : }
521 :
522 30 : if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) {
523 0 : DBG_WARNING("become_local_master_browser: Error - cannot find server %s \
524 : in workgroup %s on subnet %s\n",
525 : lp_netbios_name(), work->work_group, subrec->subnet_name);
526 0 : return;
527 : }
528 :
529 30 : DBG_NOTICE("become_local_master_browser: Starting to become a master browser for workgroup \
530 : %s on subnet %s\n", work->work_group, subrec->subnet_name);
531 :
532 30 : DBG_NOTICE("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n");
533 30 : work->mst_state = MST_BACKUP; /* an election win was successful */
534 :
535 30 : work->ElectionCriterion |= 0x5;
536 :
537 : /* Tell the namelist writer to write out a change. */
538 30 : subrec->work_changed = True;
539 :
540 : /* Setup the userdata_struct. */
541 30 : if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
542 0 : DBG_ERR("become_local_master_browser: malloc fail.\n");
543 0 : return;
544 : }
545 :
546 30 : userdata->copy_fn = NULL;
547 30 : userdata->free_fn = NULL;
548 30 : userdata->userdata_len = strlen(work->work_group)+1;
549 30 : strlcpy(userdata->data, work->work_group, size - sizeof(*userdata));
550 :
551 : /* Register the special browser group name. */
552 30 : register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
553 : become_local_master_stage1,
554 : become_local_master_fail1,
555 : userdata);
556 :
557 30 : zero_free(userdata, size);
558 : }
559 :
560 : /***************************************************************
561 : Utility function to set the local master browser name. Does
562 : some sanity checking as old versions of Samba seem to sometimes
563 : say that the master browser name for a workgroup is the same
564 : as the workgroup name.
565 : ****************************************************************/
566 :
567 98 : void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
568 : {
569 98 : DBG_INFO("set_workgroup_local_master_browser_name: setting local master name to '%s' \
570 : for workgroup %s.\n", newname, work->work_group );
571 :
572 : #if 0
573 : /*
574 : * Apparently some sites use the workgroup name as the local
575 : * master browser name. Arrrrggghhhhh ! (JRA).
576 : */
577 : if(strequal( work->work_group, newname))
578 : {
579 : DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
580 : local_master_browser_name for workgroup %s to workgroup name.\n",
581 : work->work_group ));
582 : return;
583 : }
584 : #endif
585 :
586 98 : unstrcpy(work->local_master_browser_name, newname);
587 98 : }
|