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