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