As per a Andrew's message, I went through and removed the timestring()
[jra/samba/.git] / source3 / nmbd / nmbd_become_dmb.c
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
8    
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.
13    
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.
18    
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.
22    
23 */
24
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28
29 extern pstring scope;
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;
35
36 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
37
38 static void become_domain_master_browser_bcast(char *);
39
40 /*******************************************************************
41   Unbecome a domain master browser - name release success function.
42   ******************************************************************/
43
44 static void unbecome_dmb_success(struct subnet_record *subrec,
45                                  struct userdata_struct *userdata,
46                                  struct nmb_name *released_name,
47                                  struct in_addr released_ip)
48 {
49   struct work_record *work = find_workgroup_on_subnet(subrec, released_name->name);
50   struct server_record *servrec;
51
52   if(!work)
53   {
54     DEBUG(0,("unbecome_dmb_success: Cannot find workgroup %s on subnet %s\n",
55              released_name->name, subrec->subnet_name));
56     return;
57   }
58
59   if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
60   {
61     DEBUG(0,("unbecome_dmb_success: Error - cannot find server %s \
62 in workgroup %s on subnet %s\n",
63        global_myname, released_name->name, subrec->subnet_name));
64     return;
65   }
66
67   /* Set the state in the workgroup structure. */
68   work->dom_state = DOMAIN_NONE;
69
70   /* Update our server status. */
71   servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
72
73   /* Tell the namelist writer to write out a change. */
74   subrec->work_changed = True;
75
76   /* Remove any list of local master browsers we are syncing with. */
77   remove_workgroup_lmb_browsers(released_name->name);
78
79   /* Delete the known domain master browser name from the workgroup
80      struct. */
81   bzero((char *)&work->dmb_name, sizeof(work->dmb_name));
82   putip((char *)&work->dmb_addr, &ipzero);
83
84   if( DEBUGLVL( 0 ) )
85     {
86     dbgtext( "*****\n\nSamba server %s ", global_myname );
87     dbgtext( "has stopped being a domain master browser " );
88     dbgtext( "for workgroup %s ", work->work_group );
89     dbgtext( "on subnet %s.\n\n*****\n", subrec->subnet_name );
90     }
91
92 }
93
94 /*******************************************************************
95   Unbecome a domain master browser - name release fail function.
96   ******************************************************************/
97
98 static void unbecome_dmb_fail(struct subnet_record *subrec,
99                                  struct response_record *rrec,
100                                  struct nmb_name *released_name)
101 {
102   if( DEBUGLVL( 0 ) )
103     {
104     dbgtext( "unbecome_dmb_fail: Failed to unbecome domain master browser " );
105     dbgtext( "for workgroup %s ", released_name->name );
106     dbgtext( "on subnet %s.\n",   subrec->subnet_name );
107     }
108 }
109
110 /*******************************************************************
111   Unbecome a domain master browser.
112   ******************************************************************/
113
114 void unbecome_domain_master(char *workgroup_name)
115 {   
116   struct subnet_record *subrec;
117
118   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
119   {
120     struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
121
122     if(work && (work->dom_state == DOMAIN_MST))
123     {
124       struct name_record *namerec;
125       struct nmb_name nmbname;
126       make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
127
128       /* We can only do this if we are a domain master already. */
129       DEBUG(2,("unbecome_domain_master: attempting to stop being a domain \
130 master browser for workgroup %s on subnet %s\n",
131               work->work_group, subrec->subnet_name));
132    
133       /* Find the WORKGROUP<1b> name on the subnet namelist. */
134       if((namerec = find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME))==NULL)
135       {
136         DEBUG(0,("unbecome_domain_master: Cannot find name %s on subnet %s.\n",
137                 namestr(&nmbname), subrec->subnet_name));
138         continue;
139       }
140       release_name(subrec, namerec, 
141                    unbecome_dmb_success,
142                    unbecome_dmb_fail,
143                    NULL);
144     }
145   }
146
147
148 /****************************************************************************
149   Fail to become a Domain Master Browser on a subnet.
150   ****************************************************************************/
151
152 static void become_domain_master_fail(struct subnet_record *subrec,
153                                       struct response_record *rrec,
154                                       struct nmb_name *fail_name)
155 {
156   struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
157   struct server_record *servrec;
158
159   if(!work)
160   {
161     DEBUG(0,("become_domain_master_fail: Error - cannot find \
162 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
163     return;
164   }
165
166   /* Set the state back to DOMAIN_NONE. */
167   work->dom_state = DOMAIN_NONE;
168
169   if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
170   {
171     DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
172 in workgroup %s on subnet %s\n",
173        global_myname, work->work_group, subrec->subnet_name));
174     return;
175   }
176
177   /* Update our server status. */
178   servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
179
180   /* Tell the namelist writer to write out a change. */
181   subrec->work_changed = True;
182
183   DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
184 workgroup %s on subnet %s. Couldn't register name %s.\n",
185        work->work_group, subrec->subnet_name, namestr(fail_name)));
186 }
187
188 /****************************************************************************
189   Become a Domain Master Browser on a subnet.
190   ****************************************************************************/
191
192 static void become_domain_master_stage2(struct subnet_record *subrec, 
193                                         struct userdata_struct *userdata,
194                                         struct nmb_name *registered_name,
195                                         uint16 nb_flags,
196                                         int ttl, struct in_addr registered_ip)
197 {
198   struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
199   struct server_record *servrec;
200
201   if(!work)
202   {
203     DEBUG(0,("become_domain_master_stage2: Error - cannot find \
204 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
205     return;
206   }
207
208   if((servrec = find_server_in_workgroup( work, global_myname)) == NULL)
209   {
210     DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
211 in workgroup %s on subnet %s\n", 
212        global_myname, registered_name->name, subrec->subnet_name));
213     work->dom_state = DOMAIN_NONE;
214     return;
215   }
216
217   /* Set the state in the workgroup structure. */
218   work->dom_state = DOMAIN_MST; /* Become domain master. */
219
220   /* Update our server status. */
221   servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
222
223   /* Tell the namelist writer to write out a change. */
224   subrec->work_changed = True;
225
226   if( DEBUGLVL( 0 ) )
227     {
228     dbgtext( "*****\n\nSamba server %s ", global_myname );
229     dbgtext( "is now a domain master browser for " );
230     dbgtext( "workgroup %s ", work->work_group );
231     dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
232     }
233
234   if( subrec == unicast_subnet )
235   {
236     struct nmb_name nmbname;
237     struct in_addr my_first_ip;
238
239     /* Put our name and first IP address into the 
240        workgroup struct as domain master browser. This
241        will stop us syncing with ourself if we are also
242        a local master browser. */
243
244     make_nmb_name(&nmbname, global_myname, 0x20, scope);
245
246     work->dmb_name = nmbname;
247     /* Pick the first interface ip address as the domain master browser ip. */
248     my_first_ip = *iface_n_ip(0);
249
250     putip((char *)&work->dmb_addr, &my_first_ip);
251
252     /* We successfully registered by unicast with the
253        WINS server.  We now expect to become the domain
254        master on the local subnets. If this fails, it's
255        probably a 1.9.16p2 to 1.9.16p11 server's fault.
256
257        This is a configuration issue that should be addressed
258        by the network administrator - you shouldn't have
259        several machines configured as a domain master browser
260        for the same WINS scope (except if they are 1.9.17 or
261        greater, and you know what you're doing.
262
263        see docs/DOMAIN.txt.
264
265      */
266     become_domain_master_browser_bcast(work->work_group);
267   }
268 }
269
270 /****************************************************************************
271   Start the name registration process when becoming a Domain Master Browser
272   on a subnet.
273   ****************************************************************************/
274
275 static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
276
277   struct work_record *work;
278
279   DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
280 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
281
282   /* First, find the workgroup on the subnet. */
283   if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
284   {
285     DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
286           wg_name, subrec->subnet_name));
287     return;
288   }
289
290   DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
291   work->dom_state = DOMAIN_WAIT;
292
293   /* WORKGROUP<1b> is the domain master browser name. */
294   register_name(subrec, work->work_group,0x1b,samba_nb_type,
295                 become_domain_master_stage2,
296                 become_domain_master_fail, NULL);
297 }
298
299 /****************************************************************************
300   Function called when a query for a WORKGROUP<1b> name succeeds.
301   This is normally a fail condition as it means there is already
302   a domain master browser for a workgroup and we were trying to
303   become one.
304 ****************************************************************************/
305
306 static void become_domain_master_query_success(struct subnet_record *subrec,
307                         struct userdata_struct *userdata,
308                         struct nmb_name *nmbname, struct in_addr ip, 
309                         struct res_rec *rrec)
310 {
311   /* If the given ip is not ours, then we can't become a domain
312      controler as the name is already registered.
313    */
314
315  /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
316     address or zero ip for this query. Pretend this is ok. */
317
318   if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
319   {
320     DEBUG(3,("become_domain_master_query_success: Our address (%s) returned \
321 in query for name %s (domain master browser name) on subnet %s. \
322 Continuing with domain master code.\n", 
323            inet_ntoa(ip), namestr(nmbname), subrec->subnet_name));
324
325     become_domain_master_stage1(subrec, nmbname->name);
326   }
327   else
328   {
329     if( DEBUGLVL( 0 ) )
330       {
331       dbgtext( "become_domain_master_query_success:\n" );
332       dbgtext( "There is already a domain master browser at " );
333       dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
334       dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
335       }
336   }
337 }
338
339 /****************************************************************************
340   Function called when a query for a WORKGROUP<1b> name fails.
341   This is normally a success condition as it then allows us to register
342   our own Domain Master Browser name.
343   ****************************************************************************/
344
345 static void become_domain_master_query_fail(struct subnet_record *subrec,
346                                     struct response_record *rrec,
347                                     struct nmb_name *question_name, int fail_code)
348 {
349   /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
350      then this is a failure. Otherwise, not finding the name is what we want. */
351   if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
352   {
353     DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
354 querying WINS server for name %s.\n", 
355                   fail_code, namestr(question_name)));
356     return;
357   }
358
359   /* Otherwise - not having the name allows us to register it. */
360   become_domain_master_stage1(subrec, question_name->name);
361 }
362
363 /****************************************************************************
364   Attempt to become a domain master browser on all broadcast subnets.
365   ****************************************************************************/
366
367 static void become_domain_master_browser_bcast(char *workgroup_name)
368 {
369   struct subnet_record *subrec;
370
371   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
372   { 
373     struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
374
375     if (work && (work->dom_state == DOMAIN_NONE))
376     {
377       struct nmb_name nmbname;
378       make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
379
380       /*
381        * Check for our name on the given broadcast subnet first, only initiate
382        * further processing if we cannot find it.
383        */
384
385       if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
386       {
387         if( DEBUGLVL( 0 ) )
388           {
389           dbgtext( "become_domain_master_browser_bcast:\n" );
390           dbgtext( "Attempting to become domain master browser on " );
391           dbgtext( "workgroup %s on subnet %s\n",
392                     workgroup_name, subrec->subnet_name );
393           }
394
395         /* Send out a query to establish whether there's a 
396            domain controller on the local subnet. If not,
397            we can become a domain controller. 
398          */
399
400         DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
401 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
402
403         query_name(subrec, nmbname.name, nmbname.name_type,
404                    become_domain_master_query_success, 
405                    become_domain_master_query_fail,
406                    NULL);
407       }
408     }
409   }
410 }
411
412 /****************************************************************************
413   Attempt to become a domain master browser by registering with WINS.
414   ****************************************************************************/
415
416 static void become_domain_master_browser_wins(char *workgroup_name)
417 {
418   struct work_record *work;
419
420   work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
421
422   if (work && (work->dom_state == DOMAIN_NONE))
423   {
424     struct nmb_name nmbname;
425
426     make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
427
428     /*
429      * Check for our name on the unicast subnet first, only initiate
430      * further processing if we cannot find it.
431      */
432
433     if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
434     {
435       if( DEBUGLVL( 0 ) )
436         {
437         dbgtext( "become_domain_master_browser_wins:\n" );
438         dbgtext( "Attempting to become domain master browser " );
439         dbgtext( "on workgroup %s, subnet %s.\n",
440                   workgroup_name, unicast_subnet->subnet_name );
441         }
442
443       /* Send out a query to establish whether there's a 
444          domain master broswer registered with WINS. If not,
445          we can become a domain master browser. 
446        */
447
448       DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
449 for domain master browser name %s on workgroup %s\n",
450          inet_ntoa(unicast_subnet->myip), namestr(&nmbname), workgroup_name));
451
452       query_name(unicast_subnet, nmbname.name, nmbname.name_type,
453                    become_domain_master_query_success,
454                    become_domain_master_query_fail,
455                    NULL);
456     }
457   }
458 }
459
460 /****************************************************************************
461   Add the domain logon server and domain master browser names
462   if we are set up to do so.
463   **************************************************************************/
464
465 void add_domain_names(time_t t)
466 {
467   static time_t lastrun = 0;
468
469   if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
470     return;
471
472   lastrun = t;
473
474   /* Do the "internet group" - <1c> names. */
475   if (lp_domain_logons())
476     add_logon_names();
477
478   /* Do the domain master names. */
479   if(lp_domain_master())
480   {
481     if(we_are_a_wins_client())
482     {
483       /* We register the WORKGROUP<1b> name with the WINS
484          server first, and call add_domain_master_bcast()
485          only if this is successful.
486
487          This results in domain logon services being gracefully provided,
488          as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
489          1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
490          cannot provide domain master / domain logon services.
491        */
492       become_domain_master_browser_wins(global_myworkgroup);
493     }
494     else
495       become_domain_master_browser_bcast(global_myworkgroup);
496   }
497 }