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