Line data Source code
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 : #include "../librpc/gen_ndr/svcctl.h"
25 : #include "nmbd/nmbd.h"
26 :
27 : extern uint16_t samba_nb_type; /* Samba's NetBIOS type. */
28 :
29 : static void become_domain_master_browser_bcast(const char *);
30 :
31 : /****************************************************************************
32 : Fail to become a Domain Master Browser on a subnet.
33 : ****************************************************************************/
34 :
35 0 : static void become_domain_master_fail(struct subnet_record *subrec,
36 : struct response_record *rrec,
37 : struct nmb_name *fail_name)
38 : {
39 : unstring failname;
40 : struct work_record *work;
41 : struct server_record *servrec;
42 :
43 0 : pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
44 0 : work = find_workgroup_on_subnet(subrec, failname);
45 0 : if(!work) {
46 0 : DEBUG(0,("become_domain_master_fail: Error - cannot find \
47 : workgroup %s on subnet %s\n", failname, subrec->subnet_name));
48 0 : return;
49 : }
50 :
51 : /* Set the state back to DOMAIN_NONE. */
52 0 : work->dom_state = DOMAIN_NONE;
53 :
54 0 : if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
55 0 : DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
56 : in workgroup %s on subnet %s\n",
57 : lp_netbios_name(), work->work_group, subrec->subnet_name));
58 0 : return;
59 : }
60 :
61 : /* Update our server status. */
62 0 : servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
63 :
64 : /* Tell the namelist writer to write out a change. */
65 0 : subrec->work_changed = True;
66 :
67 0 : DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
68 : workgroup %s on subnet %s. Couldn't register name %s.\n",
69 : work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
70 : }
71 :
72 : /****************************************************************************
73 : Become a Domain Master Browser on a subnet.
74 : ****************************************************************************/
75 :
76 13 : static void become_domain_master_stage2(struct subnet_record *subrec,
77 : struct userdata_struct *userdata,
78 : struct nmb_name *registered_name,
79 : uint16_t nb_flags,
80 : int ttl, struct in_addr registered_ip)
81 : {
82 : unstring regname;
83 : struct work_record *work;
84 : struct server_record *servrec;
85 :
86 13 : pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
87 13 : work = find_workgroup_on_subnet( subrec, regname);
88 :
89 13 : if(!work) {
90 0 : DEBUG(0,("become_domain_master_stage2: Error - cannot find \
91 : workgroup %s on subnet %s\n", regname, subrec->subnet_name));
92 0 : return;
93 : }
94 :
95 13 : if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
96 0 : DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
97 : in workgroup %s on subnet %s\n",
98 : lp_netbios_name(), regname, subrec->subnet_name));
99 0 : work->dom_state = DOMAIN_NONE;
100 0 : return;
101 : }
102 :
103 : /* Set the state in the workgroup structure. */
104 13 : work->dom_state = DOMAIN_MST; /* Become domain master. */
105 :
106 : /* Update our server status. */
107 13 : servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
108 :
109 : /* Tell the namelist writer to write out a change. */
110 13 : subrec->work_changed = True;
111 :
112 13 : if( DEBUGLVL( 0 ) ) {
113 13 : dbgtext( "*****\n\nSamba server %s ", lp_netbios_name() );
114 13 : dbgtext( "is now a domain master browser for " );
115 13 : dbgtext( "workgroup %s ", work->work_group );
116 13 : dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
117 : }
118 :
119 13 : if( subrec == unicast_subnet ) {
120 : struct nmb_name nmbname;
121 : struct in_addr my_first_ip;
122 : const struct in_addr *nip;
123 :
124 : /* Put our name and first IP address into the
125 : workgroup struct as domain master browser. This
126 : will stop us syncing with ourself if we are also
127 : a local master browser. */
128 :
129 0 : make_nmb_name(&nmbname, lp_netbios_name(), 0x20);
130 :
131 0 : work->dmb_name = nmbname;
132 :
133 : /* Pick the first interface IPv4 address as the domain master
134 : * browser ip. */
135 0 : nip = first_ipv4_iface();
136 0 : if (!nip) {
137 0 : DEBUG(0,("become_domain_master_stage2: "
138 : "Error. get_interface returned NULL\n"));
139 0 : return;
140 : }
141 0 : my_first_ip = *nip;
142 :
143 0 : putip((char *)&work->dmb_addr, &my_first_ip);
144 :
145 : /* We successfully registered by unicast with the
146 : WINS server. We now expect to become the domain
147 : master on the local subnets. If this fails, it's
148 : probably a 1.9.16p2 to 1.9.16p11 server's fault.
149 :
150 : This is a configuration issue that should be addressed
151 : by the network administrator - you shouldn't have
152 : several machines configured as a domain master browser
153 : for the same WINS scope (except if they are 1.9.17 or
154 : greater, and you know what you're doing.
155 :
156 : see docs/DOMAIN.txt.
157 :
158 : */
159 0 : become_domain_master_browser_bcast(work->work_group);
160 : } else {
161 : /*
162 : * Now we are a domain master on a broadcast subnet, we need to add
163 : * the WORKGROUP<1b> name to the unicast subnet so that we can answer
164 : * unicast requests sent to this name. This bug wasn't found for a while
165 : * as it is strange to have a DMB without using WINS. JRA.
166 : */
167 13 : insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
168 : }
169 : }
170 :
171 : /****************************************************************************
172 : Start the name registration process when becoming a Domain Master Browser
173 : on a subnet.
174 : ****************************************************************************/
175 :
176 14 : static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name)
177 : {
178 : struct work_record *work;
179 :
180 14 : DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
181 : workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
182 :
183 : /* First, find the workgroup on the subnet. */
184 14 : if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) {
185 0 : DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
186 : wg_name, subrec->subnet_name));
187 0 : return;
188 : }
189 :
190 14 : DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
191 14 : work->dom_state = DOMAIN_WAIT;
192 :
193 : /* WORKGROUP<1b> is the domain master browser name. */
194 14 : register_name(subrec, work->work_group,0x1b,samba_nb_type,
195 : become_domain_master_stage2,
196 : become_domain_master_fail, NULL);
197 : }
198 :
199 : /****************************************************************************
200 : Function called when a query for a WORKGROUP<1b> name succeeds.
201 : This is normally a fail condition as it means there is already
202 : a domain master browser for a workgroup and we were trying to
203 : become one.
204 : ****************************************************************************/
205 :
206 0 : static void become_domain_master_query_success(struct subnet_record *subrec,
207 : struct userdata_struct *userdata,
208 : struct nmb_name *nmbname, struct in_addr ip,
209 : struct res_rec *rrec)
210 : {
211 : unstring name;
212 : struct in_addr allones_ip;
213 :
214 0 : pull_ascii_nstring(name, sizeof(name), nmbname->name);
215 :
216 : /* If the given ip is not ours, then we can't become a domain
217 : controller as the name is already registered.
218 : */
219 :
220 : /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
221 : address or zero ip for this query. Pretend this is ok. */
222 :
223 0 : allones_ip.s_addr = htonl(INADDR_BROADCAST);
224 :
225 0 : if(ismyip_v4(ip) || ip_equal_v4(allones_ip, ip) || is_zero_ip_v4(ip)) {
226 0 : if( DEBUGLVL( 3 ) ) {
227 0 : dbgtext( "become_domain_master_query_success():\n" );
228 0 : dbgtext( "Our address (%s) ", inet_ntoa(ip) );
229 0 : dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
230 0 : dbgtext( "(domain master browser name) " );
231 0 : dbgtext( "on subnet %s.\n", subrec->subnet_name );
232 0 : dbgtext( "Continuing with domain master code.\n" );
233 : }
234 :
235 0 : become_domain_master_stage1(subrec, name);
236 : } else {
237 0 : if( DEBUGLVL( 0 ) ) {
238 0 : dbgtext( "become_domain_master_query_success:\n" );
239 0 : dbgtext( "There is already a domain master browser at " );
240 0 : dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), name );
241 0 : dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
242 : }
243 : }
244 0 : }
245 :
246 : /****************************************************************************
247 : Function called when a query for a WORKGROUP<1b> name fails.
248 : This is normally a success condition as it then allows us to register
249 : our own Domain Master Browser name.
250 : ****************************************************************************/
251 :
252 14 : static void become_domain_master_query_fail(struct subnet_record *subrec,
253 : struct response_record *rrec,
254 : struct nmb_name *question_name, int fail_code)
255 : {
256 : unstring name;
257 :
258 : /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
259 : then this is a failure. Otherwise, not finding the name is what we want. */
260 :
261 14 : if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) {
262 0 : DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
263 : querying WINS server for name %s.\n",
264 : fail_code, nmb_namestr(question_name)));
265 0 : return;
266 : }
267 :
268 : /* Otherwise - not having the name allows us to register it. */
269 14 : pull_ascii_nstring(name, sizeof(name), question_name->name);
270 14 : become_domain_master_stage1(subrec, name);
271 : }
272 :
273 : /****************************************************************************
274 : Attempt to become a domain master browser on all broadcast subnets.
275 : ****************************************************************************/
276 :
277 61 : static void become_domain_master_browser_bcast(const char *workgroup_name)
278 : {
279 : struct subnet_record *subrec;
280 :
281 122 : for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
282 61 : struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
283 :
284 61 : if (work && (work->dom_state == DOMAIN_NONE)) {
285 : struct nmb_name nmbname;
286 14 : make_nmb_name(&nmbname,workgroup_name,0x1b);
287 :
288 : /*
289 : * Check for our name on the given broadcast subnet first, only initiate
290 : * further processing if we cannot find it.
291 : */
292 :
293 14 : if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
294 14 : if( DEBUGLVL( 0 ) ) {
295 14 : dbgtext( "become_domain_master_browser_bcast:\n" );
296 14 : dbgtext( "Attempting to become domain master browser on " );
297 14 : dbgtext( "workgroup %s on subnet %s\n",
298 : workgroup_name, subrec->subnet_name );
299 : }
300 :
301 : /* Send out a query to establish whether there's a
302 : domain controller on the local subnet. If not,
303 : we can become a domain controller.
304 : */
305 :
306 14 : DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
307 : for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
308 :
309 14 : query_name(subrec, workgroup_name, nmbname.name_type,
310 : become_domain_master_query_success,
311 : become_domain_master_query_fail,
312 : NULL);
313 : }
314 : }
315 : }
316 61 : }
317 :
318 : /****************************************************************************
319 : Attempt to become a domain master browser by registering with WINS.
320 : ****************************************************************************/
321 :
322 0 : static void become_domain_master_browser_wins(const char *workgroup_name)
323 : {
324 : struct work_record *work;
325 :
326 0 : work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
327 :
328 0 : if (work && (work->dom_state == DOMAIN_NONE)) {
329 : struct nmb_name nmbname;
330 :
331 0 : make_nmb_name(&nmbname,workgroup_name,0x1b);
332 :
333 : /*
334 : * Check for our name on the unicast subnet first, only initiate
335 : * further processing if we cannot find it.
336 : */
337 :
338 0 : if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) {
339 0 : if( DEBUGLVL( 0 ) ) {
340 0 : dbgtext( "become_domain_master_browser_wins:\n" );
341 0 : dbgtext( "Attempting to become domain master browser " );
342 0 : dbgtext( "on workgroup %s, subnet %s.\n",
343 0 : workgroup_name, unicast_subnet->subnet_name );
344 : }
345 :
346 : /* Send out a query to establish whether there's a
347 : domain master browser registered with WINS. If not,
348 : we can become a domain master browser.
349 : */
350 :
351 0 : DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
352 : for domain master browser name %s on workgroup %s\n",
353 : inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
354 :
355 0 : query_name(unicast_subnet, workgroup_name, nmbname.name_type,
356 : become_domain_master_query_success,
357 : become_domain_master_query_fail,
358 : NULL);
359 : }
360 : }
361 0 : }
362 :
363 : /****************************************************************************
364 : Add the domain logon server and domain master browser names
365 : if we are set up to do so.
366 : **************************************************************************/
367 :
368 17145 : void add_domain_names(time_t t)
369 : {
370 : static time_t lastrun = 0;
371 :
372 17145 : if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
373 17013 : return;
374 :
375 132 : lastrun = t;
376 :
377 : /* Do the "internet group" - <1c> names. */
378 132 : if (IS_DC)
379 61 : add_logon_names();
380 :
381 : /* Do the domain master names. */
382 132 : if(lp_domain_master()) {
383 61 : if(we_are_a_wins_client()) {
384 : /* We register the WORKGROUP<1b> name with the WINS
385 : server first, and call add_domain_master_bcast()
386 : only if this is successful.
387 :
388 : This results in domain logon services being gracefully provided,
389 : as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
390 : 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
391 : cannot provide domain master / domain logon services.
392 : */
393 0 : become_domain_master_browser_wins(lp_workgroup());
394 : } else {
395 61 : become_domain_master_browser_bcast(lp_workgroup());
396 : }
397 : }
398 : }
|