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