removed two unneeded files after Richard backed out these changes.
[Samba.git] / source / nmbd / nmbd_become_dmb.c
blob7af896e3e034b27daebd6005d70ae412c6caf7d8
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
25 #include "includes.h"
27 extern pstring global_myname;
28 extern fstring global_myworkgroup;
29 extern char **my_netbios_names;
30 extern struct in_addr allones_ip;
32 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
34 static void become_domain_master_browser_bcast(char *);
36 /****************************************************************************
37 Fail to become a Domain Master Browser on a subnet.
38 ****************************************************************************/
40 static void become_domain_master_fail(struct subnet_record *subrec,
41 struct response_record *rrec,
42 struct nmb_name *fail_name)
44 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
45 struct server_record *servrec;
47 if(!work)
49 DEBUG(0,("become_domain_master_fail: Error - cannot find \
50 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
51 return;
54 /* Set the state back to DOMAIN_NONE. */
55 work->dom_state = DOMAIN_NONE;
57 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
59 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
60 in workgroup %s on subnet %s\n",
61 global_myname, work->work_group, subrec->subnet_name));
62 return;
65 /* Update our server status. */
66 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
68 /* Tell the namelist writer to write out a change. */
69 subrec->work_changed = True;
71 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
72 workgroup %s on subnet %s. Couldn't register name %s.\n",
73 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
76 /****************************************************************************
77 Become a Domain Master Browser on a subnet.
78 ****************************************************************************/
80 static void become_domain_master_stage2(struct subnet_record *subrec,
81 struct userdata_struct *userdata,
82 struct nmb_name *registered_name,
83 uint16 nb_flags,
84 int ttl, struct in_addr registered_ip)
86 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
87 struct server_record *servrec;
89 if(!work)
91 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
92 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
93 return;
96 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
98 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
99 in workgroup %s on subnet %s\n",
100 global_myname, registered_name->name, subrec->subnet_name));
101 work->dom_state = DOMAIN_NONE;
102 return;
105 /* Set the state in the workgroup structure. */
106 work->dom_state = DOMAIN_MST; /* Become domain master. */
108 /* Update our server status. */
109 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
111 /* Tell the namelist writer to write out a change. */
112 subrec->work_changed = True;
114 if( DEBUGLVL( 0 ) )
116 dbgtext( "*****\n\nSamba server %s ", global_myname );
117 dbgtext( "is now a domain master browser for " );
118 dbgtext( "workgroup %s ", work->work_group );
119 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
122 if( subrec == unicast_subnet )
124 struct nmb_name nmbname;
125 struct in_addr my_first_ip;
127 /* Put our name and first IP address into the
128 workgroup struct as domain master browser. This
129 will stop us syncing with ourself if we are also
130 a local master browser. */
132 make_nmb_name(&nmbname, global_myname, 0x20);
134 work->dmb_name = nmbname;
135 /* Pick the first interface ip address as the domain master browser ip. */
136 my_first_ip = *iface_n_ip(0);
138 putip((char *)&work->dmb_addr, &my_first_ip);
140 /* We successfully registered by unicast with the
141 WINS server. We now expect to become the domain
142 master on the local subnets. If this fails, it's
143 probably a 1.9.16p2 to 1.9.16p11 server's fault.
145 This is a configuration issue that should be addressed
146 by the network administrator - you shouldn't have
147 several machines configured as a domain master browser
148 for the same WINS scope (except if they are 1.9.17 or
149 greater, and you know what you're doing.
151 see docs/DOMAIN.txt.
154 become_domain_master_browser_bcast(work->work_group);
156 else
159 * Now we are a domain master on a broadcast subnet, we need to add
160 * the WORKGROUP<1b> name to the unicast subnet so that we can answer
161 * unicast requests sent to this name. This bug wasn't found for a while
162 * as it is strange to have a DMB without using WINS. JRA.
164 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
168 /****************************************************************************
169 Start the name registration process when becoming a Domain Master Browser
170 on a subnet.
171 ****************************************************************************/
173 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
175 struct work_record *work;
177 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
178 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
180 /* First, find the workgroup on the subnet. */
181 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
183 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
184 wg_name, subrec->subnet_name));
185 return;
188 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
189 work->dom_state = DOMAIN_WAIT;
191 /* WORKGROUP<1b> is the domain master browser name. */
192 register_name(subrec, work->work_group,0x1b,samba_nb_type,
193 become_domain_master_stage2,
194 become_domain_master_fail, NULL);
197 /****************************************************************************
198 Function called when a query for a WORKGROUP<1b> name succeeds.
199 This is normally a fail condition as it means there is already
200 a domain master browser for a workgroup and we were trying to
201 become one.
202 ****************************************************************************/
204 static void become_domain_master_query_success(struct subnet_record *subrec,
205 struct userdata_struct *userdata,
206 struct nmb_name *nmbname, struct in_addr ip,
207 struct res_rec *rrec)
209 /* If the given ip is not ours, then we can't become a domain
210 controler as the name is already registered.
213 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
214 address or zero ip for this query. Pretend this is ok. */
216 if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
218 if( DEBUGLVL( 3 ) )
220 dbgtext( "become_domain_master_query_success():\n" );
221 dbgtext( "Our address (%s) ", inet_ntoa(ip) );
222 dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
223 dbgtext( "(domain master browser name) " );
224 dbgtext( "on subnet %s.\n", subrec->subnet_name );
225 dbgtext( "Continuing with domain master code.\n" );
228 become_domain_master_stage1(subrec, nmbname->name);
230 else
232 if( DEBUGLVL( 0 ) )
234 dbgtext( "become_domain_master_query_success:\n" );
235 dbgtext( "There is already a domain master browser at " );
236 dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
237 dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
239 become_domain_master_stage1(subrec, nmbname->name);
243 /****************************************************************************
244 Function called when a query for a WORKGROUP<1b> name fails.
245 This is normally a success condition as it then allows us to register
246 our own Domain Master Browser name.
247 ****************************************************************************/
249 static void become_domain_master_query_fail(struct subnet_record *subrec,
250 struct response_record *rrec,
251 struct nmb_name *question_name, int fail_code)
253 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
254 then this is a failure. Otherwise, not finding the name is what we want. */
255 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
257 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
258 querying WINS server for name %s.\n",
259 fail_code, nmb_namestr(question_name)));
260 return;
263 /* Otherwise - not having the name allows us to register it. */
264 become_domain_master_stage1(subrec, question_name->name);
267 /****************************************************************************
268 Attempt to become a domain master browser on all broadcast subnets.
269 ****************************************************************************/
271 static void become_domain_master_browser_bcast(char *workgroup_name)
273 struct subnet_record *subrec;
275 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
277 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
279 if (work && (work->dom_state == DOMAIN_NONE))
281 struct nmb_name nmbname;
282 make_nmb_name(&nmbname,workgroup_name,0x1b);
285 * Check for our name on the given broadcast subnet first, only initiate
286 * further processing if we cannot find it.
289 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
291 if( DEBUGLVL( 0 ) )
293 dbgtext( "become_domain_master_browser_bcast:\n" );
294 dbgtext( "Attempting to become domain master browser on " );
295 dbgtext( "workgroup %s on subnet %s\n",
296 workgroup_name, subrec->subnet_name );
299 /* Send out a query to establish whether there's a
300 domain controller on the local subnet. If not,
301 we can become a domain controller.
304 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
305 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
307 query_name(subrec, nmbname.name, nmbname.name_type,
308 become_domain_master_query_success,
309 become_domain_master_query_fail,
310 NULL);
316 /****************************************************************************
317 Attempt to become a domain master browser by registering with WINS.
318 ****************************************************************************/
320 static void become_domain_master_browser_wins(char *workgroup_name)
322 struct work_record *work;
324 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
326 if (work && (work->dom_state == DOMAIN_NONE))
328 struct nmb_name nmbname;
330 make_nmb_name(&nmbname,workgroup_name,0x1b);
333 * Check for our name on the unicast subnet first, only initiate
334 * further processing if we cannot find it.
337 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
339 if( DEBUGLVL( 0 ) )
341 dbgtext( "become_domain_master_browser_wins:\n" );
342 dbgtext( "Attempting to become domain master browser " );
343 dbgtext( "on workgroup %s, subnet %s.\n",
344 workgroup_name, unicast_subnet->subnet_name );
347 /* Send out a query to establish whether there's a
348 domain master broswer registered with WINS. If not,
349 we can become a domain master browser.
352 DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
353 for domain master browser name %s on workgroup %s\n",
354 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
356 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
357 become_domain_master_query_success,
358 become_domain_master_query_fail,
359 NULL);
364 /****************************************************************************
365 Add the domain logon server and domain master browser names
366 if we are set up to do so.
367 **************************************************************************/
369 void add_domain_names(time_t t)
371 static time_t lastrun = 0;
373 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
374 return;
376 lastrun = t;
378 /* Do the "internet group" - <1c> names. */
379 if (lp_domain_logons())
380 add_logon_names();
382 /* Do the domain master names. */
383 if(lp_domain_master())
385 if(we_are_a_wins_client())
387 /* We register the WORKGROUP<1b> name with the WINS
388 server first, and call add_domain_master_bcast()
389 only if this is successful.
391 This results in domain logon services being gracefully provided,
392 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
393 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
394 cannot provide domain master / domain logon services.
396 become_domain_master_browser_wins(global_myworkgroup);
398 else
399 become_domain_master_browser_bcast(global_myworkgroup);