dns: Use new DNS debugclass in DNS server
[kai/samba.git] / source3 / nmbd / nmbd_become_dmb.c
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 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 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         pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
44         work = find_workgroup_on_subnet(subrec, failname);
45         if(!work) {
46                 DEBUG(0,("become_domain_master_fail: Error - cannot find \
47 workgroup %s on subnet %s\n", failname, subrec->subnet_name));
48                 return;
49         }
50
51         /* Set the state back to DOMAIN_NONE. */
52         work->dom_state = DOMAIN_NONE;
53
54         if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
55                 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                 return;
59         }
60
61         /* Update our server status. */
62         servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
63
64         /* Tell the namelist writer to write out a change. */
65         subrec->work_changed = True;
66
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)));
70 }
71
72 /****************************************************************************
73   Become a Domain Master Browser on a subnet.
74   ****************************************************************************/
75
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)
81 {
82         unstring regname;
83         struct work_record *work;
84         struct server_record *servrec;
85
86         pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
87         work = find_workgroup_on_subnet( subrec, regname);
88
89         if(!work) {
90                 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
91 workgroup %s on subnet %s\n", regname, subrec->subnet_name));
92                 return;
93         }
94
95         if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) {
96                 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                 work->dom_state = DOMAIN_NONE;
100                 return;
101         }
102
103         /* Set the state in the workgroup structure. */
104         work->dom_state = DOMAIN_MST; /* Become domain master. */
105
106         /* Update our server status. */
107         servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
108
109         /* Tell the namelist writer to write out a change. */
110         subrec->work_changed = True;
111
112         if( DEBUGLVL( 0 ) ) {
113                 dbgtext( "*****\n\nSamba server %s ", lp_netbios_name() );
114                 dbgtext( "is now a domain master browser for " );
115                 dbgtext( "workgroup %s ", work->work_group );
116                 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
117         }
118
119         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                 make_nmb_name(&nmbname, lp_netbios_name(), 0x20);
130
131                 work->dmb_name = nmbname;
132
133                 /* Pick the first interface IPv4 address as the domain master
134                  * browser ip. */
135                 nip = first_ipv4_iface();
136                 if (!nip) {
137                         DEBUG(0,("become_domain_master_stage2: "
138                                 "Error. get_interface returned NULL\n"));
139                         return;
140                 }
141                 my_first_ip = *nip;
142
143                 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                 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                 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 static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name)
177
178         struct work_record *work;
179
180         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         if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) {
185                 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
186                         wg_name, subrec->subnet_name));
187                 return;
188         }
189
190         DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
191         work->dom_state = DOMAIN_WAIT;
192
193         /* WORKGROUP<1b> is the domain master browser name. */
194         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 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         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                 controler 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         allones_ip.s_addr = htonl(INADDR_BROADCAST);
224
225         if(ismyip_v4(ip) || ip_equal_v4(allones_ip, ip) || is_zero_ip_v4(ip)) {
226                 if( DEBUGLVL( 3 ) ) {
227                         dbgtext( "become_domain_master_query_success():\n" );
228                         dbgtext( "Our address (%s) ", inet_ntoa(ip) );
229                         dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
230                         dbgtext( "(domain master browser name) " );
231                         dbgtext( "on subnet %s.\n", subrec->subnet_name );
232                         dbgtext( "Continuing with domain master code.\n" );
233                 }
234
235                 become_domain_master_stage1(subrec, name);
236         } else {
237                 if( DEBUGLVL( 0 ) ) {
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), name );
241                         dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
242                 }
243         }
244 }
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 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         if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) {
262                 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                 return;
266         }
267
268         /* Otherwise - not having the name allows us to register it. */
269         pull_ascii_nstring(name, sizeof(name), question_name->name);
270         become_domain_master_stage1(subrec, name);
271 }
272
273 /****************************************************************************
274   Attempt to become a domain master browser on all broadcast subnets.
275   ****************************************************************************/
276
277 static void become_domain_master_browser_bcast(const char *workgroup_name)
278 {
279         struct subnet_record *subrec;
280
281         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { 
282                 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
283
284                 if (work && (work->dom_state == DOMAIN_NONE)) {
285                         struct nmb_name nmbname;
286                         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                         if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
294                                 if( DEBUGLVL( 0 ) ) {
295                                         dbgtext( "become_domain_master_browser_bcast:\n" );
296                                         dbgtext( "Attempting to become domain master browser on " );
297                                         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                                 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                                 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 }
317
318 /****************************************************************************
319   Attempt to become a domain master browser by registering with WINS.
320   ****************************************************************************/
321
322 static void become_domain_master_browser_wins(const char *workgroup_name)
323 {
324         struct work_record *work;
325
326         work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
327
328         if (work && (work->dom_state == DOMAIN_NONE)) {
329                 struct nmb_name nmbname;
330
331                 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                 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) {
339                         if( DEBUGLVL( 0 ) ) {
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 );
344                         }
345
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. 
349                         */
350
351                         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                         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 }
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 void add_domain_names(time_t t)
369 {
370         static time_t lastrun = 0;
371
372         if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
373                 return;
374
375         lastrun = t;
376
377         /* Do the "internet group" - <1c> names. */
378         if (IS_DC)
379                 add_logon_names();
380
381         /* Do the domain master names. */
382         if(lp_domain_master()) {
383                 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                         become_domain_master_browser_wins(lp_workgroup());
394                 } else {
395                         become_domain_master_browser_bcast(lp_workgroup());
396                 }
397         }
398 }