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-1998
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.
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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern pstring global_myname;
27 extern fstring global_myworkgroup;
28 extern char **my_netbios_names;
29 extern struct in_addr allones_ip;
31 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
33 static void become_domain_master_browser_bcast(char *);
35 /****************************************************************************
36 Fail to become a Domain Master Browser on a subnet.
37 ****************************************************************************/
39 static void become_domain_master_fail(struct subnet_record *subrec,
40 struct response_record *rrec,
41 struct nmb_name *fail_name)
43 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
44 struct server_record *servrec;
48 DEBUG(0,("become_domain_master_fail: Error - cannot find \
49 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
53 /* Set the state back to DOMAIN_NONE. */
54 work->dom_state = DOMAIN_NONE;
56 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
58 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
59 in workgroup %s on subnet %s\n",
60 global_myname, work->work_group, subrec->subnet_name));
64 /* Update our server status. */
65 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
67 /* Tell the namelist writer to write out a change. */
68 subrec->work_changed = True;
70 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
71 workgroup %s on subnet %s. Couldn't register name %s.\n",
72 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
75 /****************************************************************************
76 Become a Domain Master Browser on a subnet.
77 ****************************************************************************/
79 static void become_domain_master_stage2(struct subnet_record *subrec,
80 struct userdata_struct *userdata,
81 struct nmb_name *registered_name,
83 int ttl, struct in_addr registered_ip)
85 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
86 struct server_record *servrec;
90 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
91 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
95 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
97 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
98 in workgroup %s on subnet %s\n",
99 global_myname, registered_name->name, subrec->subnet_name));
100 work->dom_state = DOMAIN_NONE;
104 /* Set the state in the workgroup structure. */
105 work->dom_state = DOMAIN_MST; /* Become domain master. */
107 /* Update our server status. */
108 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
110 /* Tell the namelist writer to write out a change. */
111 subrec->work_changed = True;
115 dbgtext( "*****\n\nSamba server %s ", global_myname );
116 dbgtext( "is now a domain master browser for " );
117 dbgtext( "workgroup %s ", work->work_group );
118 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
121 if( subrec == unicast_subnet )
123 struct nmb_name nmbname;
124 struct in_addr my_first_ip;
126 /* Put our name and first IP address into the
127 workgroup struct as domain master browser. This
128 will stop us syncing with ourself if we are also
129 a local master browser. */
131 make_nmb_name(&nmbname, global_myname, 0x20);
133 work->dmb_name = nmbname;
134 /* Pick the first interface ip address as the domain master browser ip. */
135 my_first_ip = *iface_n_ip(0);
137 putip((char *)&work->dmb_addr, &my_first_ip);
139 /* We successfully registered by unicast with the
140 WINS server. We now expect to become the domain
141 master on the local subnets. If this fails, it's
142 probably a 1.9.16p2 to 1.9.16p11 server's fault.
144 This is a configuration issue that should be addressed
145 by the network administrator - you shouldn't have
146 several machines configured as a domain master browser
147 for the same WINS scope (except if they are 1.9.17 or
148 greater, and you know what you're doing.
153 become_domain_master_browser_bcast(work->work_group);
158 * Now we are a domain master on a broadcast subnet, we need to add
159 * the WORKGROUP<1b> name to the unicast subnet so that we can answer
160 * unicast requests sent to this name. This bug wasn't found for a while
161 * as it is strange to have a DMB without using WINS. JRA.
163 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
167 /****************************************************************************
168 Start the name registration process when becoming a Domain Master Browser
170 ****************************************************************************/
172 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
174 struct work_record *work;
176 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
177 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
179 /* First, find the workgroup on the subnet. */
180 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
182 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
183 wg_name, subrec->subnet_name));
187 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
188 work->dom_state = DOMAIN_WAIT;
190 /* WORKGROUP<1b> is the domain master browser name. */
191 register_name(subrec, work->work_group,0x1b,samba_nb_type,
192 become_domain_master_stage2,
193 become_domain_master_fail, NULL);
196 /****************************************************************************
197 Function called when a query for a WORKGROUP<1b> name succeeds.
198 This is normally a fail condition as it means there is already
199 a domain master browser for a workgroup and we were trying to
201 ****************************************************************************/
203 static void become_domain_master_query_success(struct subnet_record *subrec,
204 struct userdata_struct *userdata,
205 struct nmb_name *nmbname, struct in_addr ip,
206 struct res_rec *rrec)
208 /* If the given ip is not ours, then we can't become a domain
209 controler as the name is already registered.
212 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
213 address or zero ip for this query. Pretend this is ok. */
215 if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
219 dbgtext( "become_domain_master_query_success():\n" );
220 dbgtext( "Our address (%s) ", inet_ntoa(ip) );
221 dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
222 dbgtext( "(domain master browser name) " );
223 dbgtext( "on subnet %s.\n", subrec->subnet_name );
224 dbgtext( "Continuing with domain master code.\n" );
227 become_domain_master_stage1(subrec, nmbname->name);
233 dbgtext( "become_domain_master_query_success:\n" );
234 dbgtext( "There is already a domain master browser at " );
235 dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
236 dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
241 /****************************************************************************
242 Function called when a query for a WORKGROUP<1b> name fails.
243 This is normally a success condition as it then allows us to register
244 our own Domain Master Browser name.
245 ****************************************************************************/
247 static void become_domain_master_query_fail(struct subnet_record *subrec,
248 struct response_record *rrec,
249 struct nmb_name *question_name, int fail_code)
251 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
252 then this is a failure. Otherwise, not finding the name is what we want. */
253 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
255 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
256 querying WINS server for name %s.\n",
257 fail_code, nmb_namestr(question_name)));
261 /* Otherwise - not having the name allows us to register it. */
262 become_domain_master_stage1(subrec, question_name->name);
265 /****************************************************************************
266 Attempt to become a domain master browser on all broadcast subnets.
267 ****************************************************************************/
269 static void become_domain_master_browser_bcast(char *workgroup_name)
271 struct subnet_record *subrec;
273 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
275 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
277 if (work && (work->dom_state == DOMAIN_NONE))
279 struct nmb_name nmbname;
280 make_nmb_name(&nmbname,workgroup_name,0x1b);
283 * Check for our name on the given broadcast subnet first, only initiate
284 * further processing if we cannot find it.
287 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
291 dbgtext( "become_domain_master_browser_bcast:\n" );
292 dbgtext( "Attempting to become domain master browser on " );
293 dbgtext( "workgroup %s on subnet %s\n",
294 workgroup_name, subrec->subnet_name );
297 /* Send out a query to establish whether there's a
298 domain controller on the local subnet. If not,
299 we can become a domain controller.
302 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
303 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
305 query_name(subrec, nmbname.name, nmbname.name_type,
306 become_domain_master_query_success,
307 become_domain_master_query_fail,
314 /****************************************************************************
315 Attempt to become a domain master browser by registering with WINS.
316 ****************************************************************************/
318 static void become_domain_master_browser_wins(char *workgroup_name)
320 struct work_record *work;
322 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
324 if (work && (work->dom_state == DOMAIN_NONE))
326 struct nmb_name nmbname;
328 make_nmb_name(&nmbname,workgroup_name,0x1b);
331 * Check for our name on the unicast subnet first, only initiate
332 * further processing if we cannot find it.
335 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
339 dbgtext( "become_domain_master_browser_wins:\n" );
340 dbgtext( "Attempting to become domain master browser " );
341 dbgtext( "on workgroup %s, subnet %s.\n",
342 workgroup_name, unicast_subnet->subnet_name );
345 /* Send out a query to establish whether there's a
346 domain master broswer registered with WINS. If not,
347 we can become a domain master browser.
350 DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
351 for domain master browser name %s on workgroup %s\n",
352 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
354 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
355 become_domain_master_query_success,
356 become_domain_master_query_fail,
362 /****************************************************************************
363 Add the domain logon server and domain master browser names
364 if we are set up to do so.
365 **************************************************************************/
367 void add_domain_names(time_t t)
369 static time_t lastrun = 0;
371 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
376 /* Do the "internet group" - <1c> names. */
377 if (lp_domain_logons())
380 /* Do the domain master names. */
381 if(lp_server_role() == ROLE_DOMAIN_PDC)
383 if(we_are_a_wins_client())
385 /* We register the WORKGROUP<1b> name with the WINS
386 server first, and call add_domain_master_bcast()
387 only if this is successful.
389 This results in domain logon services being gracefully provided,
390 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
391 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
392 cannot provide domain master / domain logon services.
394 become_domain_master_browser_wins(global_myworkgroup);
397 become_domain_master_browser_bcast(global_myworkgroup);