dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / samba / source / nmbd / nmbd_become_dmb.c
blob17014d309e279d23b2e3cfe6142e159f465b115d
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 int DEBUGLEVEL;
29 extern pstring global_myname;
30 extern fstring global_myworkgroup;
31 extern char **my_netbios_names;
32 extern struct in_addr ipzero;
33 extern struct in_addr allones_ip;
35 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
37 static void become_domain_master_browser_bcast(char *);
39 /****************************************************************************
40 Fail to become a Domain Master Browser on a subnet.
41 ****************************************************************************/
43 static void become_domain_master_fail(struct subnet_record *subrec,
44 struct response_record *rrec,
45 struct nmb_name *fail_name)
47 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
48 struct server_record *servrec;
50 if(!work)
52 DEBUG(0,("become_domain_master_fail: Error - cannot find \
53 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
54 return;
57 /* Set the state back to DOMAIN_NONE. */
58 work->dom_state = DOMAIN_NONE;
60 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
62 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
63 in workgroup %s on subnet %s\n",
64 global_myname, work->work_group, subrec->subnet_name));
65 return;
68 /* Update our server status. */
69 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
71 /* Tell the namelist writer to write out a change. */
72 subrec->work_changed = True;
74 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
75 workgroup %s on subnet %s. Couldn't register name %s.\n",
76 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
79 /****************************************************************************
80 Become a Domain Master Browser on a subnet.
81 ****************************************************************************/
83 static void become_domain_master_stage2(struct subnet_record *subrec,
84 struct userdata_struct *userdata,
85 struct nmb_name *registered_name,
86 uint16 nb_flags,
87 int ttl, struct in_addr registered_ip)
89 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
90 struct server_record *servrec;
92 if(!work)
94 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
95 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
96 return;
99 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
101 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
102 in workgroup %s on subnet %s\n",
103 global_myname, registered_name->name, subrec->subnet_name));
104 work->dom_state = DOMAIN_NONE;
105 return;
108 /* Set the state in the workgroup structure. */
109 work->dom_state = DOMAIN_MST; /* Become domain master. */
111 /* Update our server status. */
112 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
114 /* Tell the namelist writer to write out a change. */
115 subrec->work_changed = True;
117 if( DEBUGLVL( 0 ) )
119 dbgtext( "Samba server %s is now a domain master browser for workgroup %s "
120 "on subnet %s\n", global_myname, work->work_group, subrec->subnet_name );
123 if( subrec == unicast_subnet )
125 struct nmb_name nmbname;
126 struct in_addr my_first_ip;
128 /* Put our name and first IP address into the
129 workgroup struct as domain master browser. This
130 will stop us syncing with ourself if we are also
131 a local master browser. */
133 make_nmb_name(&nmbname, global_myname, 0x20);
135 work->dmb_name = nmbname;
136 /* Pick the first interface ip address as the domain master browser ip. */
137 my_first_ip = *iface_n_ip(0);
139 putip((char *)&work->dmb_addr, &my_first_ip);
141 /* We successfully registered by unicast with the
142 WINS server. We now expect to become the domain
143 master on the local subnets. If this fails, it's
144 probably a 1.9.16p2 to 1.9.16p11 server's fault.
146 This is a configuration issue that should be addressed
147 by the network administrator - you shouldn't have
148 several machines configured as a domain master browser
149 for the same WINS scope (except if they are 1.9.17 or
150 greater, and you know what you're doing.
152 see docs/DOMAIN.txt.
155 become_domain_master_browser_bcast(work->work_group);
157 else
160 * Now we are a domain master on a broadcast subnet, we need to add
161 * the WORKGROUP<1b> name to the unicast subnet so that we can answer
162 * unicast requests sent to this name. This bug wasn't found for a while
163 * as it is strange to have a DMB without using WINS. JRA.
165 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
169 /****************************************************************************
170 Start the name registration process when becoming a Domain Master Browser
171 on a subnet.
172 ****************************************************************************/
174 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
176 struct work_record *work;
178 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
179 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
181 /* First, find the workgroup on the subnet. */
182 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
184 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
185 wg_name, subrec->subnet_name));
186 return;
189 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
190 work->dom_state = DOMAIN_WAIT;
192 /* WORKGROUP<1b> is the domain master browser name. */
193 register_name(subrec, work->work_group,0x1b,samba_nb_type,
194 become_domain_master_stage2,
195 become_domain_master_fail, NULL);
198 /****************************************************************************
199 Function called when a query for a WORKGROUP<1b> name succeeds.
200 This is normally a fail condition as it means there is already
201 a domain master browser for a workgroup and we were trying to
202 become one.
203 ****************************************************************************/
205 static void become_domain_master_query_success(struct subnet_record *subrec,
206 struct userdata_struct *userdata,
207 struct nmb_name *nmbname, struct in_addr ip,
208 struct res_rec *rrec)
210 /* If the given ip is not ours, then we can't become a domain
211 controler as the name is already registered.
214 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
215 address or zero ip for this query. Pretend this is ok. */
217 if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
219 if( DEBUGLVL( 3 ) )
221 dbgtext( "become_domain_master_query_success():\n" );
222 dbgtext( "Our address (%s) ", inet_ntoa(ip) );
223 dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
224 dbgtext( "(domain master browser name) " );
225 dbgtext( "on subnet %s.\n", subrec->subnet_name );
226 dbgtext( "Continuing with domain master code.\n" );
229 become_domain_master_stage1(subrec, nmbname->name);
231 else
233 if( DEBUGLVL( 0 ) )
235 dbgtext( "There is already a domain master browser at IP %s for workgroup %s "
236 "registered on subnet %s.\n",
237 inet_ntoa(ip), nmbname->name, subrec->subnet_name );
242 /****************************************************************************
243 Function called when a query for a WORKGROUP<1b> name fails.
244 This is normally a success condition as it then allows us to register
245 our own Domain Master Browser name.
246 ****************************************************************************/
248 static void become_domain_master_query_fail(struct subnet_record *subrec,
249 struct response_record *rrec,
250 struct nmb_name *question_name, int fail_code)
252 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
253 then this is a failure. Otherwise, not finding the name is what we want. */
254 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
256 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
257 querying WINS server for name %s.\n",
258 fail_code, nmb_namestr(question_name)));
259 return;
262 /* Otherwise - not having the name allows us to register it. */
263 become_domain_master_stage1(subrec, question_name->name);
266 /****************************************************************************
267 Attempt to become a domain master browser on all broadcast subnets.
268 ****************************************************************************/
270 static void become_domain_master_browser_bcast(char *workgroup_name)
272 struct subnet_record *subrec;
274 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
276 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
278 if (work && (work->dom_state == DOMAIN_NONE))
280 struct nmb_name nmbname;
281 make_nmb_name(&nmbname,workgroup_name,0x1b);
284 * Check for our name on the given broadcast subnet first, only initiate
285 * further processing if we cannot find it.
288 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
290 if( DEBUGLVL( 1 ) )
292 dbgtext( "become_domain_master_browser_bcast:\n" );
293 dbgtext( "Attempting to become domain master browser on " );
294 dbgtext( "workgroup %s on subnet %s\n",
295 workgroup_name, subrec->subnet_name );
298 /* Send out a query to establish whether there's a
299 domain controller on the local subnet. If not,
300 we can become a domain controller.
303 DEBUG(1,("become_domain_master_browser_bcast: querying subnet %s \
304 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
306 query_name(subrec, nmbname.name, nmbname.name_type,
307 become_domain_master_query_success,
308 become_domain_master_query_fail,
309 NULL);
315 /****************************************************************************
316 Attempt to become a domain master browser by registering with WINS.
317 ****************************************************************************/
319 static void become_domain_master_browser_wins(char *workgroup_name)
321 struct work_record *work;
323 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
325 if (work && (work->dom_state == DOMAIN_NONE))
327 struct nmb_name nmbname;
329 make_nmb_name(&nmbname,workgroup_name,0x1b);
332 * Check for our name on the unicast subnet first, only initiate
333 * further processing if we cannot find it.
336 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
338 if( DEBUGLVL( 1 ) )
340 dbgtext( "become_domain_master_browser_wins:\n" );
341 dbgtext( "Attempting to become domain master browser " );
342 dbgtext( "on workgroup %s, subnet %s.\n",
343 workgroup_name, unicast_subnet->subnet_name );
346 /* Send out a query to establish whether there's a
347 domain master broswer registered with WINS. If not,
348 we can become a domain master browser.
351 DEBUG(1,("become_domain_master_browser_wins: querying WINS server at IP %s \
352 for domain master browser name %s on workgroup %s\n",
353 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
355 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
356 become_domain_master_query_success,
357 become_domain_master_query_fail,
358 NULL);
363 /****************************************************************************
364 Add the domain logon server and domain master browser names
365 if we are set up to do so.
366 **************************************************************************/
368 void add_domain_names(time_t t)
370 static time_t lastrun = 0;
372 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
373 return;
375 lastrun = t;
377 /* Do the "internet group" - <1c> names. */
378 if (lp_domain_logons())
379 add_logon_names();
381 /* Do the domain master names. */
382 if(lp_domain_master())
384 if(we_are_a_wins_client())
386 /* We register the WORKGROUP<1b> name with the WINS
387 server first, and call add_domain_master_bcast()
388 only if this is successful.
390 This results in domain logon services being gracefully provided,
391 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
392 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
393 cannot provide domain master / domain logon services.
395 become_domain_master_browser_wins(global_myworkgroup);
397 else
398 become_domain_master_browser_bcast(global_myworkgroup);