2 Unix SMB/Netbios implementation.
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.
27 extern int DEBUGLEVEL;
30 extern pstring global_myname;
31 extern fstring global_myworkgroup;
32 extern char **my_netbios_names;
33 extern struct in_addr ipzero;
34 extern struct in_addr allones_ip;
36 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
38 static void become_domain_master_browser_bcast(char *);
40 /****************************************************************************
41 Fail to become a Domain Master Browser on a subnet.
42 ****************************************************************************/
44 static void become_domain_master_fail(struct subnet_record *subrec,
45 struct response_record *rrec,
46 struct nmb_name *fail_name)
48 struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
49 struct server_record *servrec;
53 DEBUG(0,("become_domain_master_fail: Error - cannot find \
54 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
58 /* Set the state back to DOMAIN_NONE. */
59 work->dom_state = DOMAIN_NONE;
61 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
63 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
64 in workgroup %s on subnet %s\n",
65 global_myname, work->work_group, subrec->subnet_name));
69 /* Update our server status. */
70 servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
72 /* Tell the namelist writer to write out a change. */
73 subrec->work_changed = True;
75 DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
76 workgroup %s on subnet %s. Couldn't register name %s.\n",
77 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
80 /****************************************************************************
81 Become a Domain Master Browser on a subnet.
82 ****************************************************************************/
84 static void become_domain_master_stage2(struct subnet_record *subrec,
85 struct userdata_struct *userdata,
86 struct nmb_name *registered_name,
88 int ttl, struct in_addr registered_ip)
90 struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
91 struct server_record *servrec;
95 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
96 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
100 if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
102 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
103 in workgroup %s on subnet %s\n",
104 global_myname, registered_name->name, subrec->subnet_name));
105 work->dom_state = DOMAIN_NONE;
109 /* Set the state in the workgroup structure. */
110 work->dom_state = DOMAIN_MST; /* Become domain master. */
112 /* Update our server status. */
113 servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
115 /* Tell the namelist writer to write out a change. */
116 subrec->work_changed = True;
120 dbgtext( "*****\n\nSamba server %s ", global_myname );
121 dbgtext( "is now a domain master browser for " );
122 dbgtext( "workgroup %s ", work->work_group );
123 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
126 if( subrec == unicast_subnet )
128 struct nmb_name nmbname;
129 struct in_addr my_first_ip;
131 /* Put our name and first IP address into the
132 workgroup struct as domain master browser. This
133 will stop us syncing with ourself if we are also
134 a local master browser. */
136 make_nmb_name(&nmbname, global_myname, 0x20, scope);
138 work->dmb_name = nmbname;
139 /* Pick the first interface ip address as the domain master browser ip. */
140 my_first_ip = *iface_n_ip(0);
142 putip((char *)&work->dmb_addr, &my_first_ip);
144 /* We successfully registered by unicast with the
145 WINS server. We now expect to become the domain
146 master on the local subnets. If this fails, it's
147 probably a 1.9.16p2 to 1.9.16p11 server's fault.
149 This is a configuration issue that should be addressed
150 by the network administrator - you shouldn't have
151 several machines configured as a domain master browser
152 for the same WINS scope (except if they are 1.9.17 or
153 greater, and you know what you're doing.
158 become_domain_master_browser_bcast(work->work_group);
163 * Now we are a domain master on a broadcast subnet, we need to add
164 * the WORKGROUP<1b> name to the unicast subnet so that we can answer
165 * unicast requests sent to this name. This bug wasn't found for a while
166 * as it is strange to have a DMB without using WINS. JRA.
168 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
172 /****************************************************************************
173 Start the name registration process when becoming a Domain Master Browser
175 ****************************************************************************/
177 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
179 struct work_record *work;
181 DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
182 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
184 /* First, find the workgroup on the subnet. */
185 if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
187 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
188 wg_name, subrec->subnet_name));
192 DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
193 work->dom_state = DOMAIN_WAIT;
195 /* WORKGROUP<1b> is the domain master browser name. */
196 register_name(subrec, work->work_group,0x1b,samba_nb_type,
197 become_domain_master_stage2,
198 become_domain_master_fail, NULL);
201 /****************************************************************************
202 Function called when a query for a WORKGROUP<1b> name succeeds.
203 This is normally a fail condition as it means there is already
204 a domain master browser for a workgroup and we were trying to
206 ****************************************************************************/
208 static void become_domain_master_query_success(struct subnet_record *subrec,
209 struct userdata_struct *userdata,
210 struct nmb_name *nmbname, struct in_addr ip,
211 struct res_rec *rrec)
213 /* If the given ip is not ours, then we can't become a domain
214 controler as the name is already registered.
217 /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
218 address or zero ip for this query. Pretend this is ok. */
220 if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
224 dbgtext( "become_domain_master_query_success():\n" );
225 dbgtext( "Our address (%s) ", inet_ntoa(ip) );
226 dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
227 dbgtext( "(domain master browser name) " );
228 dbgtext( "on subnet %s.\n", subrec->subnet_name );
229 dbgtext( "Continuing with domain master code.\n" );
232 become_domain_master_stage1(subrec, nmbname->name);
238 dbgtext( "become_domain_master_query_success:\n" );
239 dbgtext( "There is already a domain master browser at " );
240 dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
241 dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
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 ****************************************************************************/
252 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)
256 /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
257 then this is a failure. Otherwise, not finding the name is what we want. */
258 if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
260 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
261 querying WINS server for name %s.\n",
262 fail_code, nmb_namestr(question_name)));
266 /* Otherwise - not having the name allows us to register it. */
267 become_domain_master_stage1(subrec, question_name->name);
270 /****************************************************************************
271 Attempt to become a domain master browser on all broadcast subnets.
272 ****************************************************************************/
274 static void become_domain_master_browser_bcast(char *workgroup_name)
276 struct subnet_record *subrec;
278 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
280 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
282 if (work && (work->dom_state == DOMAIN_NONE))
284 struct nmb_name nmbname;
285 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
288 * Check for our name on the given broadcast subnet first, only initiate
289 * further processing if we cannot find it.
292 if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
296 dbgtext( "become_domain_master_browser_bcast:\n" );
297 dbgtext( "Attempting to become domain master browser on " );
298 dbgtext( "workgroup %s on subnet %s\n",
299 workgroup_name, subrec->subnet_name );
302 /* Send out a query to establish whether there's a
303 domain controller on the local subnet. If not,
304 we can become a domain controller.
307 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
308 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
310 query_name(subrec, nmbname.name, nmbname.name_type,
311 become_domain_master_query_success,
312 become_domain_master_query_fail,
319 /****************************************************************************
320 Attempt to become a domain master browser by registering with WINS.
321 ****************************************************************************/
323 static void become_domain_master_browser_wins(char *workgroup_name)
325 struct work_record *work;
327 work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
329 if (work && (work->dom_state == DOMAIN_NONE))
331 struct nmb_name nmbname;
333 make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
336 * Check for our name on the unicast subnet first, only initiate
337 * further processing if we cannot find it.
340 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
344 dbgtext( "become_domain_master_browser_wins:\n" );
345 dbgtext( "Attempting to become domain master browser " );
346 dbgtext( "on workgroup %s, subnet %s.\n",
347 workgroup_name, unicast_subnet->subnet_name );
350 /* Send out a query to establish whether there's a
351 domain master broswer registered with WINS. If not,
352 we can become a domain master browser.
355 DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
356 for domain master browser name %s on workgroup %s\n",
357 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
359 query_name(unicast_subnet, nmbname.name, nmbname.name_type,
360 become_domain_master_query_success,
361 become_domain_master_query_fail,
367 /****************************************************************************
368 Add the domain logon server and domain master browser names
369 if we are set up to do so.
370 **************************************************************************/
372 void add_domain_names(time_t t)
374 static time_t lastrun = 0;
376 if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
381 /* Do the "internet group" - <1c> names. */
382 if (lp_domain_logons())
385 /* Do the domain master names. */
386 if(lp_domain_master())
388 if(we_are_a_wins_client())
390 /* We register the WORKGROUP<1b> name with the WINS
391 server first, and call add_domain_master_bcast()
392 only if this is successful.
394 This results in domain logon services being gracefully provided,
395 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
396 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
397 cannot provide domain master / domain logon services.
399 become_domain_master_browser_wins(global_myworkgroup);
402 become_domain_master_browser_bcast(global_myworkgroup);