typo
[Samba.git] / source3 / nmbd / nmbd_become_dmb.c
blob6b92f4c3c0f936f29659a750495cd8267d894d0b
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-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.
24 #include "includes.h"
26 extern struct in_addr allones_ip;
28 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
30 static void become_domain_master_browser_bcast(const char *);
32 /****************************************************************************
33 Fail to become a Domain Master Browser on a subnet.
34 ****************************************************************************/
36 static void become_domain_master_fail(struct subnet_record *subrec,
37 struct response_record *rrec,
38 struct nmb_name *fail_name)
40 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
41 struct server_record *servrec;
43 if(!work)
45 DEBUG(0,("become_domain_master_fail: Error - cannot find \
46 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
47 return;
50 /* Set the state back to DOMAIN_NONE. */
51 work->dom_state = DOMAIN_NONE;
53 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
55 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
56 in workgroup %s on subnet %s\n",
57 global_myname(), work->work_group, subrec->subnet_name));
58 return;
61 /* Update our server status. */
62 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
64 /* Tell the namelist writer to write out a change. */
65 subrec->work_changed = True;
67 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)));
72 /****************************************************************************
73 Become a Domain Master Browser on a subnet.
74 ****************************************************************************/
76 static void become_domain_master_stage2(struct subnet_record *subrec,
77 struct userdata_struct *userdata,
78 struct nmb_name *registered_name,
79 uint16 nb_flags,
80 int ttl, struct in_addr registered_ip)
82 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
83 struct server_record *servrec;
85 if(!work)
87 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
88 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
89 return;
92 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
94 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
95 in workgroup %s on subnet %s\n",
96 global_myname(), registered_name->name, subrec->subnet_name));
97 work->dom_state = DOMAIN_NONE;
98 return;
101 /* Set the state in the workgroup structure. */
102 work->dom_state = DOMAIN_MST; /* Become domain master. */
104 /* Update our server status. */
105 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
107 /* Tell the namelist writer to write out a change. */
108 subrec->work_changed = True;
110 if( DEBUGLVL( 0 ) )
112 dbgtext( "*****\n\nSamba server %s ", global_myname() );
113 dbgtext( "is now a domain master browser for " );
114 dbgtext( "workgroup %s ", work->work_group );
115 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
118 if( subrec == unicast_subnet )
120 struct nmb_name nmbname;
121 struct in_addr my_first_ip;
123 /* Put our name and first IP address into the
124 workgroup struct as domain master browser. This
125 will stop us syncing with ourself if we are also
126 a local master browser. */
128 make_nmb_name(&nmbname, global_myname(), 0x20);
130 work->dmb_name = nmbname;
131 /* Pick the first interface ip address as the domain master browser ip. */
132 my_first_ip = *iface_n_ip(0);
134 putip((char *)&work->dmb_addr, &my_first_ip);
136 /* We successfully registered by unicast with the
137 WINS server. We now expect to become the domain
138 master on the local subnets. If this fails, it's
139 probably a 1.9.16p2 to 1.9.16p11 server's fault.
141 This is a configuration issue that should be addressed
142 by the network administrator - you shouldn't have
143 several machines configured as a domain master browser
144 for the same WINS scope (except if they are 1.9.17 or
145 greater, and you know what you're doing.
147 see docs/DOMAIN.txt.
150 become_domain_master_browser_bcast(work->work_group);
152 else
155 * Now we are a domain master on a broadcast subnet, we need to add
156 * the WORKGROUP<1b> name to the unicast subnet so that we can answer
157 * unicast requests sent to this name. This bug wasn't found for a while
158 * as it is strange to have a DMB without using WINS. JRA.
160 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
164 /****************************************************************************
165 Start the name registration process when becoming a Domain Master Browser
166 on a subnet.
167 ****************************************************************************/
169 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
171 struct work_record *work;
173 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
174 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
176 /* First, find the workgroup on the subnet. */
177 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
179 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
180 wg_name, subrec->subnet_name));
181 return;
184 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
185 work->dom_state = DOMAIN_WAIT;
187 /* WORKGROUP<1b> is the domain master browser name. */
188 register_name(subrec, work->work_group,0x1b,samba_nb_type,
189 become_domain_master_stage2,
190 become_domain_master_fail, NULL);
193 /****************************************************************************
194 Function called when a query for a WORKGROUP<1b> name succeeds.
195 This is normally a fail condition as it means there is already
196 a domain master browser for a workgroup and we were trying to
197 become one.
198 ****************************************************************************/
200 static void become_domain_master_query_success(struct subnet_record *subrec,
201 struct userdata_struct *userdata,
202 struct nmb_name *nmbname, struct in_addr ip,
203 struct res_rec *rrec)
205 /* If the given ip is not ours, then we can't become a domain
206 controler as the name is already registered.
209 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
210 address or zero ip for this query. Pretend this is ok. */
212 if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
214 if( DEBUGLVL( 3 ) )
216 dbgtext( "become_domain_master_query_success():\n" );
217 dbgtext( "Our address (%s) ", inet_ntoa(ip) );
218 dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
219 dbgtext( "(domain master browser name) " );
220 dbgtext( "on subnet %s.\n", subrec->subnet_name );
221 dbgtext( "Continuing with domain master code.\n" );
224 become_domain_master_stage1(subrec, nmbname->name);
226 else
228 if( DEBUGLVL( 0 ) )
230 dbgtext( "become_domain_master_query_success:\n" );
231 dbgtext( "There is already a domain master browser at " );
232 dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
233 dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
238 /****************************************************************************
239 Function called when a query for a WORKGROUP<1b> name fails.
240 This is normally a success condition as it then allows us to register
241 our own Domain Master Browser name.
242 ****************************************************************************/
244 static void become_domain_master_query_fail(struct subnet_record *subrec,
245 struct response_record *rrec,
246 struct nmb_name *question_name, int fail_code)
248 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
249 then this is a failure. Otherwise, not finding the name is what we want. */
250 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
252 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
253 querying WINS server for name %s.\n",
254 fail_code, nmb_namestr(question_name)));
255 return;
258 /* Otherwise - not having the name allows us to register it. */
259 become_domain_master_stage1(subrec, question_name->name);
262 /****************************************************************************
263 Attempt to become a domain master browser on all broadcast subnets.
264 ****************************************************************************/
266 static void become_domain_master_browser_bcast(const char *workgroup_name)
268 struct subnet_record *subrec;
270 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
272 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
274 if (work && (work->dom_state == DOMAIN_NONE))
276 struct nmb_name nmbname;
277 make_nmb_name(&nmbname,workgroup_name,0x1b);
280 * Check for our name on the given broadcast subnet first, only initiate
281 * further processing if we cannot find it.
284 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
286 if( DEBUGLVL( 0 ) )
288 dbgtext( "become_domain_master_browser_bcast:\n" );
289 dbgtext( "Attempting to become domain master browser on " );
290 dbgtext( "workgroup %s on subnet %s\n",
291 workgroup_name, subrec->subnet_name );
294 /* Send out a query to establish whether there's a
295 domain controller on the local subnet. If not,
296 we can become a domain controller.
299 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
300 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
302 query_name(subrec, nmbname.name, nmbname.name_type,
303 become_domain_master_query_success,
304 become_domain_master_query_fail,
305 NULL);
311 /****************************************************************************
312 Attempt to become a domain master browser by registering with WINS.
313 ****************************************************************************/
315 static void become_domain_master_browser_wins(const char *workgroup_name)
317 struct work_record *work;
319 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
321 if (work && (work->dom_state == DOMAIN_NONE))
323 struct nmb_name nmbname;
325 make_nmb_name(&nmbname,workgroup_name,0x1b);
328 * Check for our name on the unicast subnet first, only initiate
329 * further processing if we cannot find it.
332 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
334 if( DEBUGLVL( 0 ) )
336 dbgtext( "become_domain_master_browser_wins:\n" );
337 dbgtext( "Attempting to become domain master browser " );
338 dbgtext( "on workgroup %s, subnet %s.\n",
339 workgroup_name, unicast_subnet->subnet_name );
342 /* Send out a query to establish whether there's a
343 domain master broswer registered with WINS. If not,
344 we can become a domain master browser.
347 DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
348 for domain master browser name %s on workgroup %s\n",
349 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
351 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
352 become_domain_master_query_success,
353 become_domain_master_query_fail,
354 NULL);
359 /****************************************************************************
360 Add the domain logon server and domain master browser names
361 if we are set up to do so.
362 **************************************************************************/
364 void add_domain_names(time_t t)
366 static time_t lastrun = 0;
368 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
369 return;
371 lastrun = t;
373 /* Do the "internet group" - <1c> names. */
374 if (lp_domain_logons())
375 add_logon_names();
377 /* Do the domain master names. */
378 if(lp_server_role() == ROLE_DOMAIN_PDC)
380 if(we_are_a_wins_client())
382 /* We register the WORKGROUP<1b> name with the WINS
383 server first, and call add_domain_master_bcast()
384 only if this is successful.
386 This results in domain logon services being gracefully provided,
387 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
388 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
389 cannot provide domain master / domain logon services.
391 become_domain_master_browser_wins(lp_workgroup());
393 else
394 become_domain_master_browser_bcast(lp_workgroup());