Added Lanman announce patch from Jacco de Leeuw <leeuw@wins.uva.nl>.
[samba.git] / source / nmbd / nmbd_become_lmb.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-1997
6    Copyright (C) Luke Kenneth Casson Leighton 1994-1997 
7    Copyright (C) Jeremy Allison 1994-1997
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 extern pstring scope;
29 extern pstring myname;
30
31 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
32
33 /*******************************************************************
34  Utility function to add a name to the unicast subnet, or add in
35  our IP address if it already exists.
36 ******************************************************************/
37
38 static void insert_permanent_name_into_unicast( struct subnet_record *subrec, 
39                                                 struct nmb_name *nmbname, uint16 nb_type )
40 {
41   struct name_record *namerec;
42
43   if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
44   {
45     /* The name needs to be created on the unicast subnet. */
46     add_name_to_subnet( unicast_subnet, nmbname->name, nmbname->name_type,
47                         nb_type, PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
48   }
49   else
50   {
51     /* The name already exists on the unicast subnet. Add our local
52        IP for the given broadcast subnet to the name. */
53     add_ip_to_name_record( namerec, subrec->myip);
54   }
55 }
56
57 /*******************************************************************
58  Utility function to remove a name from the unicast subnet.
59 ******************************************************************/
60
61 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
62                                                 struct nmb_name *nmbname )
63 {
64   struct name_record *namerec;
65
66   if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
67   {
68     /* Remove this broadcast subnet IP address from the name. */
69     remove_ip_from_name_record( namerec, subrec->myip);
70     if(namerec->num_ips == 0)
71       remove_name_from_namelist( unicast_subnet, namerec);
72   }
73 }
74
75 /*******************************************************************
76  Utility function always called to set our workgroup and server
77  state back to potential browser, or none.
78 ******************************************************************/
79
80 static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name )
81 {
82   struct work_record *work;
83   struct server_record *servrec;
84   struct nmb_name nmbname;
85
86   if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
87   {
88     DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
89 subnet %s.\n", workgroup_name, subrec->subnet_name ));
90     return;
91   }
92
93   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
94   {
95     DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
96 in workgroup %s on subnet %s\n",
97        myname, work->work_group, subrec->subnet_name));
98     work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
99     return;
100   }
101
102   /* Update our server status - remove any master flag and replace
103    it with the potential browser flag. */
104   servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
105   servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
106
107   /* Tell the namelist writer to write out a change. */
108   subrec->work_changed = True;
109
110   /* Reset our election flags. */
111   work->ElectionCriterion &= ~0x4;
112
113   work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
114
115   /* Forget who the local master browser was for
116      this workgroup. */
117
118   set_workgroup_local_master_browser_name( work, "");
119
120   /*
121    * Ensure the IP address of this subnet is not registered as one
122    * of the IP addresses of the WORKGROUP<1d> name on the unicast
123    * subnet. This undoes what we did below when we became a local
124    * master browser.
125    */
126
127   make_nmb_name(&nmbname, work->work_group, 0x1d, scope);
128
129   remove_permanent_name_from_unicast( subrec, &nmbname);
130
131 }
132
133 /*******************************************************************
134   Unbecome the local master browser name release success function.
135 ******************************************************************/
136
137 void unbecome_local_master_success(struct subnet_record *subrec,
138                              struct userdata_struct *userdata,
139                              struct nmb_name *released_name,
140                              struct in_addr released_ip)
141
142   DEBUG(3,("unbecome_local_master_success: released name %s.\n",
143              namestr(released_name)));
144
145   /* Now reset the workgroup and server state. */
146   reset_workgroup_state( subrec, released_name->name );
147
148   DEBUG(0,("\n*****   Samba name server %s has stopped being a local master browser for workgroup %s \
149 on subnet %s *****\n\n", myname, released_name->name, subrec->subnet_name));
150
151 }
152
153 /*******************************************************************
154   Unbecome the local master browser name release fail function.
155 ******************************************************************/
156
157 void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
158                        struct nmb_name *fail_name)
159 {
160   struct name_record *namerec;
161
162   DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
163 Removing from namelist anyway.\n", namestr(fail_name)));
164
165   /* Do it anyway. */
166   namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
167   if(namerec)
168     remove_name_from_namelist(subrec, namerec);
169
170   /* Now reset the workgroup and server state. */
171   reset_workgroup_state( subrec, fail_name->name );
172
173   DEBUG(0,("\n*****   Samba name server %s has stopped being a local master browser for workgroup %s \
174 on subnet %s *****\n\n", myname, fail_name->name, subrec->subnet_name));
175
176 }
177
178 /*******************************************************************
179  Utility function to remove the WORKGROUP<1d> name called by both
180  success and fail of releasing the MSBROWSE name.
181 ******************************************************************/
182
183 void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
184 {
185   struct nmb_name nmbname;
186   struct name_record *namerec;
187
188   make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
189   if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
190   {
191     release_name(subrec, namerec,
192                  unbecome_local_master_success,
193                  unbecome_local_master_fail,
194                  NULL);
195   }
196 }
197
198 /*******************************************************************
199  Unbecome the local master browser MSBROWSE name release success function.
200 ******************************************************************/
201
202 static void release_msbrowse_name_success(struct subnet_record *subrec,
203                       struct userdata_struct *userdata,
204                       struct nmb_name *released_name,
205                       struct in_addr released_ip)
206 {
207   DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
208            namestr(released_name), subrec->subnet_name ));
209
210   /* Remove the permanent MSBROWSE name added into the unicast subnet. */
211   remove_permanent_name_from_unicast( subrec, released_name);
212
213   release_1d_name( subrec, userdata->data );
214 }
215
216 /*******************************************************************
217  Unbecome the local master browser MSBROWSE name release fail function.
218 ******************************************************************/
219
220 static void release_msbrowse_name_fail( struct subnet_record *subrec, 
221                        struct response_record *rrec,
222                        struct nmb_name *fail_name)
223 {
224   struct userdata_struct *userdata = rrec->userdata;
225   struct name_record *namerec;
226
227   DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
228            namestr(fail_name), subrec->subnet_name ));
229
230   /* Release the name anyway. */
231   namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
232   if(namerec)
233     remove_name_from_namelist(subrec, namerec);
234
235   /* Remove the permanent MSBROWSE name added into the unicast subnet. */
236   remove_permanent_name_from_unicast( subrec, fail_name);
237
238   release_1d_name( subrec, userdata->data );
239 }
240
241 /*******************************************************************
242   Unbecome the local master browser.
243 ******************************************************************/
244
245 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work)
246 {
247   struct server_record *servrec;
248   struct name_record *namerec;
249   struct nmb_name nmbname;
250   struct userdata_struct *userdata;
251   char ud[sizeof(struct userdata_struct) + sizeof(fstring)+1];
252
253   /* Sanity check. */
254
255   DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
256 on subnet %s\n",work->work_group, subrec->subnet_name));
257   
258   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
259   {
260     DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
261 in workgroup %s on subnet %s\n",
262        myname, work->work_group, subrec->subnet_name));
263     work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
264     return;
265   }
266   
267   /* Set the state to unbecoming. */
268   work->mst_state = MST_UNBECOMING_MASTER;
269
270   /* Setup the userdata for the MSBROWSE name release. */
271   /* Setup the userdata_struct - this is copied so we can use
272      a stack variable for this. */
273   userdata = (struct userdata_struct *)ud;
274
275   userdata->copy_fn = NULL;
276   userdata->free_fn = NULL;
277   userdata->userdata_len = strlen(work->work_group)+1;
278   strcpy(userdata->data, work->work_group);
279
280   /* Deregister any browser names we may have. */
281   make_nmb_name(&nmbname, MSBROWSE, 0x1, scope);
282   if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
283   {
284     release_name(subrec, namerec,
285                  release_msbrowse_name_success,
286                  release_msbrowse_name_fail,
287                  userdata);
288   }
289 }
290
291 /****************************************************************************
292   Success in registering the WORKGROUP<1d> name.
293   We are now *really* a local master browser.
294   ****************************************************************************/
295
296 static void become_local_master_stage2(struct subnet_record *subrec,
297                                         struct userdata_struct *userdata,
298                                         struct nmb_name *registered_name,
299                                         uint16 nb_flags,
300                                         int ttl, struct in_addr registered_ip)
301 {
302   int i = 0;
303   struct server_record *sl;
304   struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
305   struct server_record *servrec;
306
307   if(!work)
308   {
309     DEBUG(0,("become_local_master_stage2: Error - cannot find \
310 workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
311     return;
312   }
313
314   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
315   {
316     DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
317 in workgroup %s on subnet %s\n",
318        myname, registered_name->name, subrec->subnet_name));
319     work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
320     return;
321   }
322   
323   DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
324 on subnet %s\n", work->work_group, subrec->subnet_name));
325
326   work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
327
328   /* update our server status */
329   servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
330   servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
331
332   /* Tell the namelist writer to write out a change. */
333   subrec->work_changed = True;
334
335   /* Add this name to the workgroup as local master browser. */
336   set_workgroup_local_master_browser_name( work, myname);
337
338   /* Count the number of servers we have on our list. If it's
339      less than 10 (just a heuristic) request the servers
340      to announce themselves.
341    */
342   for( sl = work->serverlist; sl != NULL; sl = sl->next)
343     i++;
344
345   if (i < 10)
346   {
347     /* Ask all servers on our local net to announce to us. */
348     broadcast_announce_request(subrec, work);
349   }
350
351   /*
352    * Now we are a local master on a broadcast subnet, we need to add
353    * the WORKGROUP<1d> name to the unicast subnet so that we can answer
354    * unicast requests sent to this name. We can create this name directly on
355    * the unicast subnet as a WINS server always returns true when registering
356    * this name, and discards the registration. We use the number of IP
357    * addresses registered to this name as a reference count, as we
358    * remove this broadcast subnet IP address from it when we stop becoming a local
359    * master browser for this broadcast subnet.
360    */
361
362   insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
363
364   /* Reset the announce master browser timer so that we try and tell a domain
365      master browser as soon as possible that we are a local master browser. */
366   reset_announce_timer();
367
368   DEBUG(0,("\n*****   Samba name server %s is now a local master browser for workgroup %s \
369 on subnet %s *****\n\n", myname, work->work_group, subrec->subnet_name));
370
371 }
372
373 /****************************************************************************
374   Failed to register the WORKGROUP<1d> name.
375   ****************************************************************************/
376 static void become_local_master_fail2(struct subnet_record *subrec,
377                                       struct response_record *rrec,
378                                       struct nmb_name *fail_name)
379 {
380   struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
381
382   DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
383 Failed to become a local master browser.\n", namestr(fail_name), subrec->subnet_name));
384
385   if(!work)
386   {
387     DEBUG(0,("become_local_master_fail2: Error - cannot find \
388 workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
389     return;
390   }
391
392   /* Roll back all the way by calling unbecome_local_master_browser(). */
393   unbecome_local_master_browser(subrec, work);
394 }
395
396 /****************************************************************************
397   Success in registering the MSBROWSE name.
398   ****************************************************************************/
399
400 static void become_local_master_stage1(struct subnet_record *subrec,
401                                         struct userdata_struct *userdata,
402                                         struct nmb_name *registered_name,
403                                         uint16 nb_flags,
404                                         int ttl, struct in_addr registered_ip)
405 {
406   char *work_name = userdata->data;
407   struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
408
409   if(!work)
410   {
411     DEBUG(0,("become_local_master_stage1: Error - cannot find \
412 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
413     return;
414   }
415
416   DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
417             work->work_group));
418
419   work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
420
421   /*
422    * We registered the MSBROWSE name on a broadcast subnet, now need to add
423    * the MSBROWSE name to the unicast subnet so that we can answer
424    * unicast requests sent to this name. We create this name directly on
425    * the unicast subnet.
426    */
427
428   insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
429
430   /* Attempt to register the WORKGROUP<1d> name. */
431   register_name(subrec, work->work_group,0x1d,samba_nb_type,
432                 become_local_master_stage2,
433                 become_local_master_fail2,
434                 NULL);
435 }
436
437 /****************************************************************************
438   Failed to register the MSBROWSE name.
439   ****************************************************************************/
440
441 static void become_local_master_fail1(struct subnet_record *subrec,
442                                       struct response_record *rrec,
443                                       struct nmb_name *fail_name)
444 {
445   char *work_name = rrec->userdata->data;
446   struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
447   struct server_record *servrec;
448
449   if(!work)
450   {
451     DEBUG(0,("become_local_master_fail1: Error - cannot find \
452 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
453     return;
454   }
455
456   if((servrec = find_server_in_workgroup(work, myname)) == NULL)
457   {
458     DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
459 in workgroup %s on subnet %s\n",
460        myname, work->work_group, subrec->subnet_name));
461     return;
462   }
463
464   reset_workgroup_state( subrec, work->work_group );
465
466   DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
467 workgroup %s on subnet %s. Couldn't register name %s.\n",
468        work->work_group, subrec->subnet_name, namestr(fail_name)));
469 }
470
471 /******************************************************************
472   Become the local master browser on a subnet.
473   This gets called if we win an election on this subnet.
474
475   Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
476   Stage 2: mst_state was MST_BACKUP  - go to MST_MSB  and register WORKGROUP<1d>.
477   Stage 3: mst_state was MST_MSB  - go to MST_BROWSER.
478 ******************************************************************/
479
480 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
481 {
482   struct server_record *servrec;
483   struct userdata_struct *userdata;
484   char ud[sizeof(struct userdata_struct) + sizeof(fstring)+1];
485
486   /* Sanity check. */
487   if (!lp_local_master())
488   { 
489     DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
490     return;
491   }
492
493   if(!AM_POTENTIAL_MASTER_BROWSER(work))
494   {
495     DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
496               work->mst_state ));
497     return;
498   }
499
500   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
501   {
502     DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
503 in workgroup %s on subnet %s\n",
504        myname, work->work_group, subrec->subnet_name));
505     return;
506   }
507
508   DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
509 %s on subnet %s\n", work->work_group, subrec->subnet_name));
510   
511   DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
512   work->mst_state = MST_BACKUP; /* an election win was successful */
513
514   work->ElectionCriterion |= 0x5;
515
516   /* Tell the namelist writer to write out a change. */
517   subrec->work_changed = True;
518
519   /* Setup the userdata_struct - this is copied so we can use
520      a stack variable for this. */
521   userdata = (struct userdata_struct *)ud;
522
523   userdata->copy_fn = NULL;
524   userdata->free_fn = NULL;
525   userdata->userdata_len = strlen(work->work_group)+1;
526   strcpy(userdata->data, work->work_group);
527
528   /* Register the special browser group name. */
529   register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
530                 become_local_master_stage1,
531                 become_local_master_fail1,
532                 userdata);
533 }
534
535 /***************************************************************
536  Utility function to set the local master browser name. Does
537  some sanity checking as old versions of Samba seem to sometimes
538  say that the master browser name for a workgroup is the same
539  as the workgroup name.
540 ****************************************************************/
541
542 void set_workgroup_local_master_browser_name( struct work_record *work, char *newname)
543 {
544   DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
545 for workgroup %s.\n", newname, work->work_group ));
546
547   if(strequal( work->work_group, newname))
548   {
549     DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
550 local_master_browser_name for workgroup %s to workgroup name.\n",
551          work->work_group ));
552     return;
553   }
554
555   StrnCpy(work->local_master_browser_name, newname,
556             sizeof(work->local_master_browser_name)-1);
557 }