2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
30 extern pstring global_myname;
31 extern fstring global_myworkgroup;
32 extern char **my_netbios_names;
33 extern struct in_addr ipzero;
34 extern struct in_addr allones_ip;
36 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
38 static void become_domain_master_browser_bcast(char *);
40 /*******************************************************************
41 Unbecome a domain master browser - name release success function.
42 ******************************************************************/
44 static void unbecome_dmb_success(struct subnet_record *subrec,
45 struct userdata_struct *userdata,
46 struct nmb_name *released_name,
47 struct in_addr released_ip)
49 struct work_record *work = find_workgroup_on_subnet(subrec, released_name->name);
50 struct server_record *servrec;
54 DEBUG(0,("unbecome_dmb_success: Cannot find workgroup %s on subnet %s\n",
55 released_name->name, subrec->subnet_name));
59 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
61 DEBUG(0,("unbecome_dmb_success: Error - cannot find server %s \
62 in workgroup %s on subnet %s\n",
63 global_myname, released_name->name, subrec->subnet_name));
67 /* Set the state in the workgroup structure. */
68 work->dom_state = DOMAIN_NONE;
70 /* Update our server status. */
71 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
73 /* Tell the namelist writer to write out a change. */
74 subrec->work_changed = True;
76 /* Remove any list of local master browsers we are syncing with. */
77 remove_workgroup_lmb_browsers(released_name->name);
79 /* Delete the known domain master browser name from the workgroup
81 bzero((char *)&work->dmb_name, sizeof(work->dmb_name));
82 putip((char *)&work->dmb_addr, &ipzero);
86 dbgtext( "*****\n\nSamba server %s ", global_myname );
87 dbgtext( "has stopped being a domain master browser " );
88 dbgtext( "for workgroup %s ", work->work_group );
89 dbgtext( "on subnet %s.\n\n*****\n", subrec->subnet_name );
94 /*******************************************************************
95 Unbecome a domain master browser - name release fail function.
96 ******************************************************************/
98 static void unbecome_dmb_fail(struct subnet_record *subrec,
99 struct response_record *rrec,
100 struct nmb_name *released_name)
104 dbgtext( "unbecome_dmb_fail: Failed to unbecome domain master browser " );
105 dbgtext( "for workgroup %s ", released_name->name );
106 dbgtext( "on subnet %s.\n", subrec->subnet_name );
110 /*******************************************************************
111 Unbecome a domain master browser.
112 ******************************************************************/
114 void unbecome_domain_master(char *workgroup_name)
116 struct subnet_record *subrec;
118 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
120 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
122 if(work && (work->dom_state == DOMAIN_MST))
124 struct name_record *namerec;
125 struct nmb_name nmbname;
126 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
128 /* We can only do this if we are a domain master already. */
129 DEBUG(2,("unbecome_domain_master: attempting to stop being a domain \
130 master browser for workgroup %s on subnet %s\n",
131 work->work_group, subrec->subnet_name));
133 /* Find the WORKGROUP<1b> name on the subnet namelist. */
134 if((namerec = find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME))==NULL)
136 DEBUG(0,("unbecome_domain_master: Cannot find name %s on subnet %s.\n",
137 namestr(&nmbname), subrec->subnet_name));
140 release_name(subrec, namerec,
141 unbecome_dmb_success,
148 /****************************************************************************
149 Fail to become a Domain Master Browser on a subnet.
150 ****************************************************************************/
152 static void become_domain_master_fail(struct subnet_record *subrec,
153 struct response_record *rrec,
154 struct nmb_name *fail_name)
156 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
157 struct server_record *servrec;
161 DEBUG(0,("become_domain_master_fail: Error - cannot find \
162 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
166 /* Set the state back to DOMAIN_NONE. */
167 work->dom_state = DOMAIN_NONE;
169 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
171 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
172 in workgroup %s on subnet %s\n",
173 global_myname, work->work_group, subrec->subnet_name));
177 /* Update our server status. */
178 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
180 /* Tell the namelist writer to write out a change. */
181 subrec->work_changed = True;
183 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
184 workgroup %s on subnet %s. Couldn't register name %s.\n",
185 work->work_group, subrec->subnet_name, namestr(fail_name)));
188 /****************************************************************************
189 Become a Domain Master Browser on a subnet.
190 ****************************************************************************/
192 static void become_domain_master_stage2(struct subnet_record *subrec,
193 struct userdata_struct *userdata,
194 struct nmb_name *registered_name,
196 int ttl, struct in_addr registered_ip)
198 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
199 struct server_record *servrec;
203 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
204 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
208 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
210 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
211 in workgroup %s on subnet %s\n",
212 global_myname, registered_name->name, subrec->subnet_name));
213 work->dom_state = DOMAIN_NONE;
217 /* Set the state in the workgroup structure. */
218 work->dom_state = DOMAIN_MST; /* Become domain master. */
220 /* Update our server status. */
221 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
223 /* Tell the namelist writer to write out a change. */
224 subrec->work_changed = True;
228 dbgtext( "*****\n\nSamba server %s ", global_myname );
229 dbgtext( "is now a domain master browser for " );
230 dbgtext( "workgroup %s ", work->work_group );
231 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
234 if( subrec == unicast_subnet )
236 struct nmb_name nmbname;
237 struct in_addr my_first_ip;
239 /* Put our name and first IP address into the
240 workgroup struct as domain master browser. This
241 will stop us syncing with ourself if we are also
242 a local master browser. */
244 make_nmb_name(&nmbname, global_myname, 0x20, scope);
246 work->dmb_name = nmbname;
247 /* Pick the first interface ip address as the domain master browser ip. */
248 my_first_ip = *iface_n_ip(0);
250 putip((char *)&work->dmb_addr, &my_first_ip);
252 /* We successfully registered by unicast with the
253 WINS server. We now expect to become the domain
254 master on the local subnets. If this fails, it's
255 probably a 1.9.16p2 to 1.9.16p11 server's fault.
257 This is a configuration issue that should be addressed
258 by the network administrator - you shouldn't have
259 several machines configured as a domain master browser
260 for the same WINS scope (except if they are 1.9.17 or
261 greater, and you know what you're doing.
266 become_domain_master_browser_bcast(work->work_group);
270 /****************************************************************************
271 Start the name registration process when becoming a Domain Master Browser
273 ****************************************************************************/
275 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
277 struct work_record *work;
279 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
280 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
282 /* First, find the workgroup on the subnet. */
283 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
285 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
286 wg_name, subrec->subnet_name));
290 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
291 work->dom_state = DOMAIN_WAIT;
293 /* WORKGROUP<1b> is the domain master browser name. */
294 register_name(subrec, work->work_group,0x1b,samba_nb_type,
295 become_domain_master_stage2,
296 become_domain_master_fail, NULL);
299 /****************************************************************************
300 Function called when a query for a WORKGROUP<1b> name succeeds.
301 This is normally a fail condition as it means there is already
302 a domain master browser for a workgroup and we were trying to
304 ****************************************************************************/
306 static void become_domain_master_query_success(struct subnet_record *subrec,
307 struct userdata_struct *userdata,
308 struct nmb_name *nmbname, struct in_addr ip,
309 struct res_rec *rrec)
311 /* If the given ip is not ours, then we can't become a domain
312 controler as the name is already registered.
315 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
316 address or zero ip for this query. Pretend this is ok. */
318 if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
320 DEBUG(3,("become_domain_master_query_success: Our address (%s) returned \
321 in query for name %s (domain master browser name) on subnet %s. \
322 Continuing with domain master code.\n",
323 inet_ntoa(ip), namestr(nmbname), subrec->subnet_name));
325 become_domain_master_stage1(subrec, nmbname->name);
331 dbgtext( "become_domain_master_query_success:\n" );
332 dbgtext( "There is already a domain master browser at " );
333 dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
334 dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
339 /****************************************************************************
340 Function called when a query for a WORKGROUP<1b> name fails.
341 This is normally a success condition as it then allows us to register
342 our own Domain Master Browser name.
343 ****************************************************************************/
345 static void become_domain_master_query_fail(struct subnet_record *subrec,
346 struct response_record *rrec,
347 struct nmb_name *question_name, int fail_code)
349 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
350 then this is a failure. Otherwise, not finding the name is what we want. */
351 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
353 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
354 querying WINS server for name %s.\n",
355 fail_code, namestr(question_name)));
359 /* Otherwise - not having the name allows us to register it. */
360 become_domain_master_stage1(subrec, question_name->name);
363 /****************************************************************************
364 Attempt to become a domain master browser on all broadcast subnets.
365 ****************************************************************************/
367 static void become_domain_master_browser_bcast(char *workgroup_name)
369 struct subnet_record *subrec;
371 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
373 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
375 if (work && (work->dom_state == DOMAIN_NONE))
377 struct nmb_name nmbname;
378 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
381 * Check for our name on the given broadcast subnet first, only initiate
382 * further processing if we cannot find it.
385 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
389 dbgtext( "become_domain_master_browser_bcast:\n" );
390 dbgtext( "Attempting to become domain master browser on " );
391 dbgtext( "workgroup %s on subnet %s\n",
392 workgroup_name, subrec->subnet_name );
395 /* Send out a query to establish whether there's a
396 domain controller on the local subnet. If not,
397 we can become a domain controller.
400 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
401 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
403 query_name(subrec, nmbname.name, nmbname.name_type,
404 become_domain_master_query_success,
405 become_domain_master_query_fail,
412 /****************************************************************************
413 Attempt to become a domain master browser by registering with WINS.
414 ****************************************************************************/
416 static void become_domain_master_browser_wins(char *workgroup_name)
418 struct work_record *work;
420 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
422 if (work && (work->dom_state == DOMAIN_NONE))
424 struct nmb_name nmbname;
426 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
429 * Check for our name on the unicast subnet first, only initiate
430 * further processing if we cannot find it.
433 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
437 dbgtext( "become_domain_master_browser_wins:\n" );
438 dbgtext( "Attempting to become domain master browser " );
439 dbgtext( "on workgroup %s, subnet %s.\n",
440 workgroup_name, unicast_subnet->subnet_name );
443 /* Send out a query to establish whether there's a
444 domain master broswer registered with WINS. If not,
445 we can become a domain master browser.
448 DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
449 for domain master browser name %s on workgroup %s\n",
450 inet_ntoa(unicast_subnet->myip), namestr(&nmbname), workgroup_name));
452 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
453 become_domain_master_query_success,
454 become_domain_master_query_fail,
460 /****************************************************************************
461 Add the domain logon server and domain master browser names
462 if we are set up to do so.
463 **************************************************************************/
465 void add_domain_names(time_t t)
467 static time_t lastrun = 0;
469 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
474 /* Do the "internet group" - <1c> names. */
475 if (lp_domain_logons())
478 /* Do the domain master names. */
479 if(lp_domain_master())
481 if(we_are_a_wins_client())
483 /* We register the WORKGROUP<1b> name with the WINS
484 server first, and call add_domain_master_bcast()
485 only if this is successful.
487 This results in domain logon services being gracefully provided,
488 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
489 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
490 cannot provide domain master / domain logon services.
492 become_domain_master_browser_wins(global_myworkgroup);
495 become_domain_master_browser_bcast(global_myworkgroup);