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