netcmd: user: turn user.py into module netcmd.user
[Samba.git] / source3 / nmbd / nmbd_become_lmb.c
blob7fea757e6f4a5a4424dc9741c940dac1a6aa3887
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"
26 #include "lib/util/string_wrappers.h"
28 extern uint16_t samba_nb_type; /* Samba's NetBIOS name type. */
30 /*******************************************************************
31 Utility function to add a name to the unicast subnet, or add in
32 our IP address if it already exists.
33 ******************************************************************/
35 void insert_permanent_name_into_unicast( struct subnet_record *subrec,
36 struct nmb_name *nmbname, uint16_t nb_type )
38 unstring name;
39 struct name_record *namerec;
41 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
42 pull_ascii_nstring(name, sizeof(name), nmbname->name);
43 /* The name needs to be created on the unicast subnet. */
44 (void)add_name_to_subnet( unicast_subnet, name,
45 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 add_ip_to_name_record( namerec, subrec->myip);
54 /*******************************************************************
55 Utility function to remove a name from the unicast subnet.
56 ******************************************************************/
58 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
59 struct nmb_name *nmbname )
61 struct name_record *namerec;
63 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
64 /* Remove this broadcast subnet IP address from the name. */
65 remove_ip_from_name_record( namerec, subrec->myip);
66 if(namerec->data.num_ips == 0)
67 remove_name_from_namelist( unicast_subnet, namerec);
71 /*******************************************************************
72 Utility function always called to set our workgroup and server
73 state back to potential browser, or none.
74 ******************************************************************/
76 static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
77 bool force_new_election )
79 struct work_record *work;
80 struct server_record *servrec;
81 struct nmb_name nmbname;
83 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
84 DBG_ERR("reset_workgroup_state: Error - cannot find workgroup %s on \
85 subnet %s.\n", workgroup_name, subrec->subnet_name );
86 return;
89 if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
90 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 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
94 return;
97 /* Update our server status - remove any master flag and replace
98 it with the potential browser flag. */
99 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
100 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
102 /* Tell the namelist writer to write out a change. */
103 subrec->work_changed = True;
105 /* Reset our election flags. */
106 work->ElectionCriterion &= ~0x4;
108 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
110 /* Forget who the local master browser was for
111 this workgroup. */
113 set_workgroup_local_master_browser_name( work, "");
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.
122 make_nmb_name(&nmbname, work->work_group, 0x1d);
124 remove_permanent_name_from_unicast( subrec, &nmbname);
126 if(force_new_election)
127 work->needelection = True;
130 /*******************************************************************
131 Unbecome the local master browser name release success function.
132 ******************************************************************/
134 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)
139 bool force_new_election = False;
140 unstring relname;
142 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
144 DBG_NOTICE("unbecome_local_master_success: released name %s.\n",
145 nmb_namestr(released_name));
147 /* Now reset the workgroup and server state. */
148 pull_ascii_nstring(relname, sizeof(relname), released_name->name);
149 reset_workgroup_state( subrec, relname, force_new_election );
151 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 );
158 /*******************************************************************
159 Unbecome the local master browser name release fail function.
160 ******************************************************************/
162 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
163 struct nmb_name *fail_name)
165 struct name_record *namerec;
166 struct userdata_struct *userdata = rrec->userdata;
167 bool force_new_election = False;
168 unstring failname;
170 memcpy((char *)&force_new_election, userdata->data, sizeof(bool));
172 DBG_WARNING("unbecome_local_master_fail: failed to release name %s. "
173 "Removing from namelist anyway.\n", nmb_namestr(fail_name));
175 /* Do it anyway. */
176 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
177 if(namerec)
178 remove_name_from_namelist(subrec, namerec);
180 /* Now reset the workgroup and server state. */
181 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
182 reset_workgroup_state( subrec, failname, force_new_election );
184 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);
190 /*******************************************************************
191 Utility function to remove the WORKGROUP<1d> name.
192 ******************************************************************/
194 static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
195 bool force_new_election)
197 struct nmb_name nmbname;
198 struct name_record *namerec;
200 make_nmb_name(&nmbname, workgroup_name, 0x1d);
201 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
202 struct userdata_struct *userdata;
203 size_t size = sizeof(struct userdata_struct) + sizeof(bool);
205 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
206 DBG_ERR("release_1d_name: malloc fail.\n");
207 return;
210 userdata->copy_fn = NULL;
211 userdata->free_fn = NULL;
212 userdata->userdata_len = sizeof(bool);
213 memcpy((char *)userdata->data, &force_new_election, sizeof(bool));
215 release_name(subrec, namerec,
216 unbecome_local_master_success,
217 unbecome_local_master_fail,
218 userdata);
220 zero_free(userdata, size);
224 /*******************************************************************
225 Unbecome the local master browser MSBROWSE name release success function.
226 ******************************************************************/
228 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)
233 DBG_INFO("release_msbrowse_name_success: Released name %s on subnet %s\n.",
234 nmb_namestr(released_name), subrec->subnet_name );
236 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
237 remove_permanent_name_from_unicast( subrec, released_name);
240 /*******************************************************************
241 Unbecome the local master browser MSBROWSE name release fail function.
242 ******************************************************************/
244 static void release_msbrowse_name_fail( struct subnet_record *subrec,
245 struct response_record *rrec,
246 struct nmb_name *fail_name)
248 struct name_record *namerec;
250 DBG_INFO("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
251 nmb_namestr(fail_name), subrec->subnet_name );
253 /* Release the name anyway. */
254 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
255 if(namerec)
256 remove_name_from_namelist(subrec, namerec);
258 /* Remove the permanent MSBROWSE name added into the unicast subnet. */
259 remove_permanent_name_from_unicast( subrec, fail_name);
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 ******************************************************************/
267 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
268 bool force_new_election)
270 struct name_record *namerec;
271 struct nmb_name nmbname;
273 /* Sanity check. */
275 DBG_NOTICE("unbecome_local_master_browser: unbecoming local master for workgroup %s \
276 on subnet %s\n",work->work_group, subrec->subnet_name);
278 if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) {
279 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 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
283 return;
286 /* Set the state to unbecoming. */
287 work->mst_state = MST_UNBECOMING_MASTER;
290 * Release the WORKGROUP<1d> name asap to allow another machine to
291 * claim it.
294 release_1d_name( subrec, work->work_group, force_new_election);
296 /* Deregister any browser names we may have. */
297 make_nmb_name(&nmbname, MSBROWSE, 0x1);
298 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
299 release_name(subrec, namerec,
300 release_msbrowse_name_success,
301 release_msbrowse_name_fail,
302 NULL);
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.
311 retransmit_or_expire_response_records(time(NULL));
314 /****************************************************************************
315 Success in registering the WORKGROUP<1d> name.
316 We are now *really* a local master browser.
317 ****************************************************************************/
319 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)
325 int i = 0;
326 struct server_record *sl;
327 struct work_record *work;
328 struct server_record *servrec;
329 unstring regname;
331 pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
332 work = find_workgroup_on_subnet( subrec, regname);
334 if(!work) {
335 DBG_WARNING("become_local_master_stage2: Error - cannot find \
336 workgroup %s on subnet %s\n", regname, subrec->subnet_name);
337 return;
340 if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
341 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 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
345 return;
348 DBG_NOTICE("become_local_master_stage2: registered as master browser for workgroup %s \
349 on subnet %s\n", work->work_group, subrec->subnet_name);
351 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
353 /* update our server status */
354 servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
355 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
357 /* Tell the namelist writer to write out a change. */
358 subrec->work_changed = True;
360 /* Add this name to the workgroup as local master browser. */
361 set_workgroup_local_master_browser_name( work, lp_netbios_name());
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.
367 for( sl = work->serverlist; sl != NULL; sl = sl->next)
368 i++;
370 if (i < 10) {
371 /* Ask all servers on our local net to announce to us. */
372 broadcast_announce_request(subrec, work);
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.
386 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
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 reset_announce_timer();
392 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 );
398 /****************************************************************************
399 Failed to register the WORKGROUP<1d> name.
400 ****************************************************************************/
402 static void become_local_master_fail2(struct subnet_record *subrec,
403 struct response_record *rrec,
404 struct nmb_name *fail_name)
406 unstring failname;
407 struct work_record *work;
409 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);
412 pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
413 work = find_workgroup_on_subnet( subrec, failname);
415 if(!work) {
416 DBG_WARNING("become_local_master_fail2: Error - cannot find \
417 workgroup %s on subnet %s\n", failname, subrec->subnet_name);
418 return;
421 /* Roll back all the way by calling unbecome_local_master_browser(). */
422 unbecome_local_master_browser(subrec, work, False);
425 /****************************************************************************
426 Success in registering the MSBROWSE name.
427 ****************************************************************************/
429 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)
435 char *work_name = userdata->data;
436 struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
438 if(!work) {
439 DBG_WARNING("become_local_master_stage1: Error - cannot find \
440 %s on subnet %s\n", work_name, subrec->subnet_name);
441 return;
444 DBG_NOTICE("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
445 work->work_group);
447 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
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.
456 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
458 /* Attempt to register the WORKGROUP<1d> name. */
459 register_name(subrec, work->work_group,0x1d,samba_nb_type,
460 become_local_master_stage2,
461 become_local_master_fail2,
462 NULL);
465 /****************************************************************************
466 Failed to register the MSBROWSE name.
467 ****************************************************************************/
469 static void become_local_master_fail1(struct subnet_record *subrec,
470 struct response_record *rrec,
471 struct nmb_name *fail_name)
473 char *work_name = rrec->userdata->data;
474 struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
476 if(!work) {
477 DBG_WARNING("become_local_master_fail1: Error - cannot find \
478 workgroup %s on subnet %s\n", work_name, subrec->subnet_name);
479 return;
482 if(find_server_in_workgroup(work, lp_netbios_name()) == NULL) {
483 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 return;
489 reset_workgroup_state( subrec, work->work_group, False );
491 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));
496 /******************************************************************
497 Become the local master browser on a subnet.
498 This gets called if we win an election on this subnet.
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 ******************************************************************/
505 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
507 struct userdata_struct *userdata;
508 size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
510 /* Sanity check. */
511 if (!lp_local_master()) {
512 DBG_WARNING("become_local_master_browser: Samba not configured as a local master browser.\n");
513 return;
516 if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
517 DBG_NOTICE("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
518 work->mst_state );
519 return;
522 if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) {
523 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 return;
529 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);
532 DBG_NOTICE("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n");
533 work->mst_state = MST_BACKUP; /* an election win was successful */
535 work->ElectionCriterion |= 0x5;
537 /* Tell the namelist writer to write out a change. */
538 subrec->work_changed = True;
540 /* Setup the userdata_struct. */
541 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
542 DBG_ERR("become_local_master_browser: malloc fail.\n");
543 return;
546 userdata->copy_fn = NULL;
547 userdata->free_fn = NULL;
548 userdata->userdata_len = strlen(work->work_group)+1;
549 strlcpy(userdata->data, work->work_group, size - sizeof(*userdata));
551 /* Register the special browser group name. */
552 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
553 become_local_master_stage1,
554 become_local_master_fail1,
555 userdata);
557 zero_free(userdata, size);
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 ****************************************************************/
567 void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
569 DBG_INFO("set_workgroup_local_master_browser_name: setting local master name to '%s' \
570 for workgroup %s.\n", newname, work->work_group );
572 #if 0
574 * Apparently some sites use the workgroup name as the local
575 * master browser name. Arrrrggghhhhh ! (JRA).
577 if(strequal( work->work_group, newname))
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;
584 #endif
586 unstrcpy(work->local_master_browser_name, newname);