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);
84 DEBUG(0,("\n%s ***** Samba server %s has stopped being a domain master browser \
85 for workgroup %s on subnet %s *****\n\n", timestring(), global_myname, work->work_group, subrec->subnet_name));
89 /*******************************************************************
90 Unbecome a domain master browser - name release fail function.
91 ******************************************************************/
93 static void unbecome_dmb_fail(struct subnet_record *subrec,
94 struct response_record *rrec,
95 struct nmb_name *released_name)
97 DEBUG(0,("unbecome_dmb_fail: Failed to unbecome domain master browser for \
98 workgroup %s on subnet %s.\n", released_name->name, subrec->subnet_name));
101 /*******************************************************************
102 Unbecome a domain master browser.
103 ******************************************************************/
105 void unbecome_domain_master(char *workgroup_name)
107 struct subnet_record *subrec;
109 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
111 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
113 if(work && (work->dom_state == DOMAIN_MST))
115 struct name_record *namerec;
116 struct nmb_name nmbname;
117 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
119 /* We can only do this if we are a domain master already. */
120 DEBUG(2,("unbecome_domain_master: attempting to stop being a domain \
121 master browser for workgroup %s on subnet %s\n",
122 work->work_group, subrec->subnet_name));
124 /* Find the WORKGROUP<1b> name on the subnet namelist. */
125 if((namerec = find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME))==NULL)
127 DEBUG(0,("unbecome_domain_master: Cannot find name %s on subnet %s.\n",
128 namestr(&nmbname), subrec->subnet_name));
131 release_name(subrec, namerec,
132 unbecome_dmb_success,
139 /****************************************************************************
140 Fail to become a Domain Master Browser on a subnet.
141 ****************************************************************************/
143 static void become_domain_master_fail(struct subnet_record *subrec,
144 struct response_record *rrec,
145 struct nmb_name *fail_name)
147 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
148 struct server_record *servrec;
152 DEBUG(0,("become_domain_master_fail: Error - cannot find \
153 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
157 /* Set the state back to DOMAIN_NONE. */
158 work->dom_state = DOMAIN_NONE;
160 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
162 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
163 in workgroup %s on subnet %s\n",
164 global_myname, work->work_group, subrec->subnet_name));
168 /* Update our server status. */
169 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
171 /* Tell the namelist writer to write out a change. */
172 subrec->work_changed = True;
174 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
175 workgroup %s on subnet %s. Couldn't register name %s.\n",
176 work->work_group, subrec->subnet_name, namestr(fail_name)));
179 /****************************************************************************
180 Become a Domain Master Browser on a subnet.
181 ****************************************************************************/
183 static void become_domain_master_stage2(struct subnet_record *subrec,
184 struct userdata_struct *userdata,
185 struct nmb_name *registered_name,
187 int ttl, struct in_addr registered_ip)
189 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
190 struct server_record *servrec;
194 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
195 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
199 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
201 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
202 in workgroup %s on subnet %s\n",
203 global_myname, registered_name->name, subrec->subnet_name));
204 work->dom_state = DOMAIN_NONE;
208 /* Set the state in the workgroup structure. */
209 work->dom_state = DOMAIN_MST; /* Become domain master. */
211 /* Update our server status. */
212 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
214 /* Tell the namelist writer to write out a change. */
215 subrec->work_changed = True;
217 DEBUG(0,("\n%s ***** Samba server %s is now a domain master browser for \
218 workgroup %s on subnet %s *****\n\n", timestring(),global_myname, work->work_group,
219 subrec->subnet_name));
221 if(subrec == unicast_subnet)
223 struct nmb_name nmbname;
224 struct in_addr my_first_ip;
226 /* Put our name and first IP address into the
227 workgroup struct as domain master browser. This
228 will stop us syncing with ourself if we are also
229 a local master browser. */
231 make_nmb_name(&nmbname, global_myname, 0x20, scope);
233 work->dmb_name = nmbname;
234 /* Pick the first interface ip address as the domain master browser ip. */
235 my_first_ip = *iface_n_ip(0);
237 putip((char *)&work->dmb_addr, &my_first_ip);
239 /* We successfully registered by unicast with the
240 WINS server. We now expect to become the domain
241 master on the local subnets. If this fails, it's
242 probably a 1.9.16p2 to 1.9.16p11 server's fault.
244 This is a configuration issue that should be addressed
245 by the network administrator - you shouldn't have
246 several machines configured as a domain master browser
247 for the same WINS scope (except if they are 1.9.17 or
248 greater, and you know what you're doing.
253 become_domain_master_browser_bcast(work->work_group);
257 /****************************************************************************
258 Start the name registration process when becoming a Domain Master Browser
260 ****************************************************************************/
262 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
264 struct work_record *work;
266 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
267 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
269 /* First, find the workgroup on the subnet. */
270 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
272 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
273 wg_name, subrec->subnet_name));
277 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
278 work->dom_state = DOMAIN_WAIT;
280 /* WORKGROUP<1b> is the domain master browser name. */
281 register_name(subrec, work->work_group,0x1b,samba_nb_type,
282 become_domain_master_stage2,
283 become_domain_master_fail, NULL);
286 /****************************************************************************
287 Function called when a query for a WORKGROUP<1b> name succeeds.
288 This is normally a fail condition as it means there is already
289 a domain master browser for a workgroup and we were trying to
291 ****************************************************************************/
293 static void become_domain_master_query_success(struct subnet_record *subrec,
294 struct userdata_struct *userdata,
295 struct nmb_name *nmbname, struct in_addr ip,
296 struct res_rec *rrec)
298 /* If the given ip is not ours, then we can't become a domain
299 controler as the name is already registered.
302 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
303 address or zero ip for this query. Pretend this is ok. */
305 if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
307 DEBUG(3,("become_domain_master_query_success: Our address (%s) returned \
308 in query for name %s (domain master browser name) on subnet %s. \
309 Continuing with domain master code.\n",
310 inet_ntoa(ip), namestr(nmbname), subrec->subnet_name));
312 become_domain_master_stage1(subrec, nmbname->name);
316 DEBUG(0,("%s become_domain_master_query_success: There is already a domain \
317 master browser at IP %s for workgroup %s registered on subnet %s.\n",
318 timestring(), inet_ntoa(ip), nmbname->name, subrec->subnet_name));
322 /****************************************************************************
323 Function called when a query for a WORKGROUP<1b> name fails.
324 This is normally a success condition as it then allows us to register
325 our own Domain Master Browser name.
326 ****************************************************************************/
328 static void become_domain_master_query_fail(struct subnet_record *subrec,
329 struct response_record *rrec,
330 struct nmb_name *question_name, int fail_code)
332 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
333 then this is a failure. Otherwise, not finding the name is what we want. */
334 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
336 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
337 querying WINS server for name %s.\n",
338 fail_code, namestr(question_name)));
342 /* Otherwise - not having the name allows us to register it. */
343 become_domain_master_stage1(subrec, question_name->name);
346 /****************************************************************************
347 Attempt to become a domain master browser on all broadcast subnets.
348 ****************************************************************************/
350 static void become_domain_master_browser_bcast(char *workgroup_name)
352 struct subnet_record *subrec;
354 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
356 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
358 if (work && (work->dom_state == DOMAIN_NONE))
360 struct nmb_name nmbname;
361 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
364 * Check for our name on the given broadcast subnet first, only initiate
365 * further processing if we cannot find it.
368 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
370 DEBUG(0,("become_domain_master_browser_bcast: At time %s attempting to become domain \
371 master browser on workgroup %s on subnet %s\n", timestring(),
372 workgroup_name, subrec->subnet_name));
374 /* Send out a query to establish whether there's a
375 domain controller on the local subnet. If not,
376 we can become a domain controller.
379 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
380 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
382 query_name(subrec, nmbname.name, nmbname.name_type,
383 become_domain_master_query_success,
384 become_domain_master_query_fail,
391 /****************************************************************************
392 Attempt to become a domain master browser by registering with WINS.
393 ****************************************************************************/
395 static void become_domain_master_browser_wins(char *workgroup_name)
397 struct work_record *work;
399 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
401 if (work && (work->dom_state == DOMAIN_NONE))
403 struct nmb_name nmbname;
405 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
408 * Check for our name on the unicast subnet first, only initiate
409 * further processing if we cannot find it.
412 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
414 DEBUG(0,("%s become_domain_master_browser_wins: attempting to become domain \
415 master browser on workgroup %s, subnet %s.\n",
416 timestring(), workgroup_name, unicast_subnet->subnet_name));
418 /* Send out a query to establish whether there's a
419 domain master broswer registered with WINS. If not,
420 we can become a domain master browser.
423 DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
424 for domain master browser name %s on workgroup %s\n",
425 inet_ntoa(unicast_subnet->myip), namestr(&nmbname), workgroup_name));
427 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
428 become_domain_master_query_success,
429 become_domain_master_query_fail,
435 /****************************************************************************
436 Add the domain logon server and domain master browser names
437 if we are set up to do so.
438 **************************************************************************/
440 void add_domain_names(time_t t)
442 static time_t lastrun = 0;
444 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
449 /* Do the "internet group" - <1c> names. */
450 if (lp_domain_logons())
453 /* Do the domain master names. */
454 if(lp_domain_master())
456 if(we_are_a_wins_client())
458 /* We register the WORKGROUP<1b> name with the WINS
459 server first, and call add_domain_master_bcast()
460 only if this is successful.
462 This results in domain logon services being gracefully provided,
463 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
464 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
465 cannot provide domain master / domain logon services.
467 become_domain_master_browser_wins(global_myworkgroup);
470 become_domain_master_browser_bcast(global_myworkgroup);