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