r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/samba.git] / source / nmbd / nmbd_browsesync.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 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 /* This is our local master browser list database. */
27 extern ubi_dlList lmb_browserlist[];
28
29 /****************************************************************************
30 As a domain master browser, do a sync with a local master browser.
31 **************************************************************************/
32
33 static void sync_with_lmb(struct browse_cache_record *browc)
34 {                     
35         struct work_record *work;
36
37         if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) {
38                 if( DEBUGLVL( 0 ) ) {
39                         dbgtext( "sync_with_lmb:\n" );
40                         dbgtext( "Failed to get a workgroup for a local master browser " );
41                         dbgtext( "cache entry workgroup " );
42                         dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
43                 }
44                 return;
45         }
46
47         /* We should only be doing this if we are a domain master browser for
48                 the given workgroup. Ensure this is so. */
49
50         if(!AM_DOMAIN_MASTER_BROWSER(work)) {
51                 if( DEBUGLVL( 0 ) ) {
52                         dbgtext( "sync_with_lmb:\n" );
53                         dbgtext( "We are trying to sync with a local master browser " );
54                         dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
55                         dbgtext( "and we are not a domain master browser on this workgroup.\n" );
56                         dbgtext( "Error!\n" );
57                 }
58                 return;
59         }
60
61         if( DEBUGLVL( 2 ) ) {
62                 dbgtext( "sync_with_lmb:\n" );
63                 dbgtext( "Initiating sync with local master browser " );
64                 dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
65                 dbgtext( "for workgroup %s\n", browc->work_group );
66         }
67
68         sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
69
70         browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
71 }
72
73 /****************************************************************************
74 Sync or expire any local master browsers.
75 **************************************************************************/
76
77 void dmb_expire_and_sync_browser_lists(time_t t)
78 {
79         static time_t last_run = 0;
80         struct browse_cache_record *browc;
81
82         /* Only do this every 20 seconds. */  
83         if (t - last_run < 20) 
84                 return;
85
86         last_run = t;
87
88         expire_lmb_browsers(t);
89
90         for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
91                         browc;
92                         browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
93                 if (browc->sync_time < t)
94                         sync_with_lmb(browc);
95         }
96 }
97
98 /****************************************************************************
99 As a local master browser, send an announce packet to the domain master browser.
100 **************************************************************************/
101
102 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
103 {
104         pstring outbuf;
105         unstring myname;
106         unstring dmb_name;
107         char *p;
108
109         if(ismyip(work->dmb_addr)) {
110                 if( DEBUGLVL( 2 ) ) {
111                         dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
112                         dbgtext( "We are both a domain and a local master browser for " );
113                         dbgtext( "workgroup %s.  ", work->work_group );
114                         dbgtext( "Do not announce to ourselves.\n" );
115                 }
116                 return;
117         }
118
119         memset(outbuf,'\0',sizeof(outbuf));
120         p = outbuf;
121         SCVAL(p,0,ANN_MasterAnnouncement);
122         p++;
123
124         unstrcpy(myname, global_myname());
125         strupper_m(myname);
126         myname[15]='\0';
127         /* The call below does CH_UNIX -> CH_DOS conversion. JRA */
128         push_pstring_base(p, myname, outbuf);
129
130         p = skip_string(p,1);
131
132         if( DEBUGLVL( 4 ) ) {
133                 dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
134                 dbgtext( "Sending local master announce to " );
135                 dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
136                                         work->work_group );
137         }
138
139         /* Target name for send_mailslot must be in UNIX charset. */
140         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
141         send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
142                 global_myname(), 0x0, dmb_name, 0x0, 
143                 work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
144 }
145
146 /****************************************************************************
147 As a local master browser, do a sync with a domain master browser.
148 **************************************************************************/
149
150 static void sync_with_dmb(struct work_record *work)
151 {
152         unstring dmb_name;
153
154         if( DEBUGLVL( 2 ) ) {
155                 dbgtext( "sync_with_dmb:\n" );
156                 dbgtext( "Initiating sync with domain master browser " );
157                 dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
158                 dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
159                 dbgtext( "for workgroup %s\n", work->work_group );
160         }
161
162         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
163         sync_browse_lists(work, dmb_name, work->dmb_name.name_type, 
164                 work->dmb_addr, False, True);
165 }
166
167 /****************************************************************************
168   Function called when a node status query to a domain master browser IP succeeds.
169 ****************************************************************************/
170
171 static void domain_master_node_status_success(struct subnet_record *subrec,
172                                               struct userdata_struct *userdata,
173                                               struct res_rec *answers,
174                                               struct in_addr from_ip)
175 {
176         struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
177
178         if( work == NULL ) {
179                 if( DEBUGLVL( 0 ) ) {
180                         dbgtext( "domain_master_node_status_success:\n" );
181                         dbgtext( "Unable to find workgroup " );
182                         dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
183                 }
184                 return;
185         }
186
187         if( DEBUGLVL( 3 ) ) {
188                 dbgtext( "domain_master_node_status_success:\n" );
189                 dbgtext( "Success in node status for workgroup " );
190                 dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
191         }
192
193   /* Go through the list of names found at answers->rdata and look for
194      the first SERVER<0x20> name. */
195
196         if(answers->rdata != NULL) {
197                 char *p = answers->rdata;
198                 int numnames = CVAL(p, 0);
199
200                 p += 1;
201
202                 while (numnames--) {
203                         unstring qname;
204                         uint16 nb_flags;
205                         int name_type;
206
207                         pull_ascii_nstring(qname, sizeof(qname), p);
208                         name_type = CVAL(p,15);
209                         nb_flags = get_nb_flags(&p[16]);
210                         trim_char(qname,'\0',' ');
211
212                         p += 18;
213
214                         if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
215                                 struct nmb_name nmbname;
216
217                                 make_nmb_name(&nmbname, qname, name_type);
218
219                                 /* Copy the dmb name and IP address
220                                         into the workgroup struct. */
221
222                                 work->dmb_name = nmbname;
223                                 putip((char *)&work->dmb_addr, &from_ip);
224
225                                 /* Do the local master browser announcement to the domain
226                                         master browser name and IP. */
227                                 announce_local_master_browser_to_domain_master_browser( work );
228
229                                 /* Now synchronise lists with the domain master browser. */
230                                 sync_with_dmb(work);
231                                 break;
232                         }
233                 }
234         } else if( DEBUGLVL( 0 ) ) {
235                 dbgtext( "domain_master_node_status_success:\n" );
236                 dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
237                 dbgtext( "%s.\n", inet_ntoa(from_ip) );
238         }
239 }
240
241 /****************************************************************************
242   Function called when a node status query to a domain master browser IP fails.
243 ****************************************************************************/
244
245 static void domain_master_node_status_fail(struct subnet_record *subrec,
246                        struct response_record *rrec)
247 {
248         struct userdata_struct *userdata = rrec->userdata;
249
250         if( DEBUGLVL( 0 ) ) {
251                 dbgtext( "domain_master_node_status_fail:\n" );
252                 dbgtext( "Doing a node status request to the domain master browser\n" );
253                 dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
254                 dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
255                 dbgtext( "Cannot sync browser lists.\n" );
256         }
257 }
258
259 /****************************************************************************
260   Function called when a query for a WORKGROUP<1b> name succeeds.
261 ****************************************************************************/
262
263 static void find_domain_master_name_query_success(struct subnet_record *subrec,
264                         struct userdata_struct *userdata_in,
265                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
266 {
267         /* 
268          * Unfortunately, finding the IP address of the Domain Master Browser,
269          * as we have here, is not enough. We need to now do a sync to the
270          * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
271          * respond to the SMBSERVER name. To get this name from IP
272          * address we do a Node status request, and look for the first
273          * NAME<0x20> in the response, and take that as the server name.
274          * We also keep a cache of the Domain Master Browser name for this
275          * workgroup in the Workgroup struct, so that if the same IP addess
276          * is returned every time, we don't need to do the node status
277          * request.
278          */
279
280         struct work_record *work;
281         struct nmb_name nmbname;
282         struct userdata_struct *userdata;
283         size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
284         unstring qname;
285
286         pull_ascii_nstring(qname, sizeof(qname), q_name->name);
287         if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
288                 if( DEBUGLVL( 0 ) ) {
289                         dbgtext( "find_domain_master_name_query_success:\n" );
290                         dbgtext( "Failed to find workgroup %s\n", qname);
291                 }
292         return;
293   }
294
295   /* First check if we already have a dmb for this workgroup. */
296
297         if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) {
298                 /* Do the local master browser announcement to the domain
299                         master browser name and IP. */
300                 announce_local_master_browser_to_domain_master_browser( work );
301
302                 /* Now synchronise lists with the domain master browser. */
303                 sync_with_dmb(work);
304                 return;
305         } else {
306                 zero_ip(&work->dmb_addr);
307         }
308
309         /* Now initiate the node status request. */
310
311         /* We used to use the name "*",0x0 here, but some Windows
312          * servers don't answer that name. However we *know* they
313          * have the name workgroup#1b (as we just looked it up).
314          * So do the node status request on this name instead.
315          * Found at LBL labs. JRA.
316          */
317
318         make_nmb_name(&nmbname,work->work_group,0x1b);
319
320         /* Put the workgroup name into the userdata so we know
321          what workgroup we're talking to when the reply comes
322          back. */
323
324         /* Setup the userdata_struct - this is copied so we can use
325         a stack variable for this. */
326
327         if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
328                 DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
329                 return;
330         }
331
332         userdata->copy_fn = NULL;
333         userdata->free_fn = NULL;
334         userdata->userdata_len = strlen(work->work_group)+1;
335         overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
336
337         node_status( subrec, &nmbname, answer_ip, 
338                 domain_master_node_status_success,
339                 domain_master_node_status_fail,
340                 userdata);
341
342         zero_free(userdata, size);
343 }
344
345 /****************************************************************************
346   Function called when a query for a WORKGROUP<1b> name fails.
347   ****************************************************************************/
348
349 static void find_domain_master_name_query_fail(struct subnet_record *subrec,
350                                     struct response_record *rrec,
351                                     struct nmb_name *question_name, int fail_code)
352 {
353         if( DEBUGLVL( 0 ) ) {
354                 dbgtext( "find_domain_master_name_query_fail:\n" );
355                 dbgtext( "Unable to find the Domain Master Browser name " );
356                 dbgtext( "%s for the workgroup %s.\n",
357                         nmb_namestr(question_name), question_name->name );
358                 dbgtext( "Unable to sync browse lists in this workgroup.\n" );
359         }
360 }
361
362 /****************************************************************************
363 As a local master browser for a workgroup find the domain master browser
364 name, announce ourselves as local master browser to it and then pull the
365 full domain browse lists from it onto the given subnet.
366 **************************************************************************/
367
368 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
369                                                    struct work_record *work)
370 {
371         /* Only do this if we are using a WINS server. */
372         if(we_are_a_wins_client() == False) {
373                 if( DEBUGLVL( 10 ) ) {
374                         dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
375                         dbgtext( "Ignoring, as we are not a WINS client.\n" );
376                 }
377                 return;
378         }
379
380         /* First, query for the WORKGROUP<1b> name from the WINS server. */
381         query_name(unicast_subnet, work->work_group, 0x1b,
382              find_domain_master_name_query_success,
383              find_domain_master_name_query_fail,
384              NULL);
385 }
386
387 /****************************************************************************
388   Function called when a node status query to a domain master browser IP succeeds.
389   This function is only called on query to a Samba 1.9.18 or above WINS server.
390
391   Note that adding the workgroup name is enough for this workgroup to be
392   browsable by clients, as clients query the WINS server or broadcast 
393   nets for the WORKGROUP<1b> name when they want to browse a workgroup
394   they are not in. We do not need to do a sync with this Domain Master
395   Browser in order for our browse clients to see machines in this workgroup.
396   JRA.
397 ****************************************************************************/
398
399 static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
400                                               struct userdata_struct *userdata,
401                                               struct res_rec *answers,
402                                               struct in_addr from_ip)
403 {
404         struct work_record *work;
405         unstring server_name;
406
407         server_name[0] = 0;
408
409         if( DEBUGLVL( 3 ) ) {
410                 dbgtext( "get_domain_master_name_node_status_success:\n" );
411                 dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
412         }
413
414         /* 
415          * Go through the list of names found at answers->rdata and look for
416          * the first WORKGROUP<0x1b> name.
417          */
418
419         if(answers->rdata != NULL) {
420                 char *p = answers->rdata;
421                 int numnames = CVAL(p, 0);
422
423                 p += 1;
424
425                 while (numnames--) {
426                         unstring qname;
427                         uint16 nb_flags;
428                         int name_type;
429
430                         pull_ascii_nstring(qname, sizeof(qname), p);
431                         name_type = CVAL(p,15);
432                         nb_flags = get_nb_flags(&p[16]);
433                         trim_char(qname,'\0',' ');
434
435                         p += 18;
436
437                         if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
438                                         server_name[0] == 0) {
439                                 /* this is almost certainly the server netbios name */
440                                 unstrcpy(server_name, qname);
441                                 continue;
442                         }
443
444                         if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
445                                 if( DEBUGLVL( 5 ) ) {
446                                         dbgtext( "get_domain_master_name_node_status_success:\n" );
447                                         dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
448                                         dbgtext( "is a domain master browser for workgroup " );
449                                         dbgtext( "%s. Adding this name.\n", qname );
450                                 }
451
452                                 /* 
453                                  * If we don't already know about this workgroup, add it
454                                  * to the workgroup list on the unicast_subnet.
455                                  */
456
457                                 if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
458                                         struct nmb_name nmbname;
459                                         /* 
460                                          * Add it - with an hour in the cache.
461                                          */
462                                         if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
463                                                 return;
464
465                                         /* remember who the master is */
466                                         unstrcpy(work->local_master_browser_name, server_name);
467                                         make_nmb_name(&nmbname, server_name, 0x20);
468                                         work->dmb_name = nmbname;
469                                         work->dmb_addr = from_ip;
470                                 }
471                                 break;
472                         }
473                 }
474         } else if( DEBUGLVL( 0 ) ) {
475                 dbgtext( "get_domain_master_name_node_status_success:\n" );
476                 dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
477                 dbgtext( "%s.\n", inet_ntoa(from_ip) );
478         }
479 }
480
481 /****************************************************************************
482   Function called when a node status query to a domain master browser IP fails.
483 ****************************************************************************/
484
485 static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
486                        struct response_record *rrec)
487 {
488         if( DEBUGLVL( 0 ) ) {
489                 dbgtext( "get_domain_master_name_node_status_fail:\n" );
490                 dbgtext( "Doing a node status request to the domain master browser " );
491                 dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
492                 dbgtext( "Cannot get workgroup name.\n" );
493         }
494 }
495
496 /****************************************************************************
497   Function called when a query for *<1b> name succeeds.
498 ****************************************************************************/
499
500 static void find_all_domain_master_names_query_success(struct subnet_record *subrec,
501                         struct userdata_struct *userdata_in,
502                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
503 {
504         /* 
505          * We now have a list of all the domain master browsers for all workgroups
506          * that have registered with the WINS server. Now do a node status request
507          * to each one and look for the first 1b name in the reply. This will be
508          * the workgroup name that we will add to the unicast subnet as a 'non-local'
509          * workgroup.
510          */
511
512         struct nmb_name nmbname;
513         struct in_addr send_ip;
514         int i;
515
516         if( DEBUGLVL( 5 ) ) {
517                 dbgtext( "find_all_domain_master_names_query_succes:\n" );
518                 dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
519                 dbgtext( "IP addresses for Domain Master Browsers.\n" );
520         }
521
522         for(i = 0; i < rrec->rdlength / 6; i++) {
523                 /* Initiate the node status requests. */
524                 make_nmb_name(&nmbname, "*", 0);
525
526                 putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
527
528                 /* 
529                  * Don't send node status requests to ourself.
530                  */
531
532                 if(ismyip( send_ip )) {
533                         if( DEBUGLVL( 5 ) ) {
534                                 dbgtext( "find_all_domain_master_names_query_succes:\n" );
535                                 dbgtext( "Not sending node status to our own IP " );
536                                 dbgtext( "%s.\n", inet_ntoa(send_ip) );
537                         }
538                         continue;
539                 }
540
541                 if( DEBUGLVL( 5 ) ) {
542                         dbgtext( "find_all_domain_master_names_query_success:\n" );
543                         dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
544                 }
545
546                 node_status( subrec, &nmbname, send_ip, 
547                                 get_domain_master_name_node_status_success,
548                                 get_domain_master_name_node_status_fail,
549                                 NULL);
550         }
551 }
552
553 /****************************************************************************
554   Function called when a query for *<1b> name fails.
555   ****************************************************************************/
556 static void find_all_domain_master_names_query_fail(struct subnet_record *subrec,
557                                     struct response_record *rrec,
558                                     struct nmb_name *question_name, int fail_code)
559 {
560         if( DEBUGLVL( 10 ) ) {
561                 dbgtext( "find_domain_master_name_query_fail:\n" );
562                 dbgtext( "WINS server did not reply to a query for name " );
563                 dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
564                 dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
565         }
566 }
567
568 /****************************************************************************
569  If we are a domain master browser on the unicast subnet, do a query to the
570  WINS server for the *<1b> name. This will only work to a Samba WINS server,
571  so ignore it if we fail. If we succeed, contact each of the IP addresses in
572  turn and do a node status request to them. If this succeeds then look for a
573  <1b> name in the reply - this is the workgroup name. Add this to the unicast
574  subnet. This is expensive, so we only do this every 15 minutes.
575 **************************************************************************/
576
577 void collect_all_workgroup_names_from_wins_server(time_t t)
578 {
579         static time_t lastrun = 0;
580         struct work_record *work;
581
582         /* Only do this if we are using a WINS server. */
583         if(we_are_a_wins_client() == False)
584                 return;
585
586         /* Check to see if we are a domain master browser on the unicast subnet. */
587         if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
588                 if( DEBUGLVL( 0 ) ) {
589                         dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
590                         dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
591                         dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
592                 }
593                 return;
594         }
595
596         if(!AM_DOMAIN_MASTER_BROWSER(work))
597                 return;
598
599         if ((lastrun != 0) && (t < lastrun + (15 * 60)))
600                 return;
601      
602         lastrun = t;
603
604         /* First, query for the *<1b> name from the WINS server. */
605         query_name(unicast_subnet, "*", 0x1b,
606                 find_all_domain_master_names_query_success,
607                 find_all_domain_master_names_query_fail,
608                 NULL);
609
610
611
612 /****************************************************************************
613  If we are a domain master browser on the unicast subnet, do a regular sync
614  with all other DMBs that we know of on that subnet.
615
616 To prevent exponential network traffic with large numbers of workgroups
617 we use a randomised system where sync probability is inversely proportional
618 to the number of known workgroups
619 **************************************************************************/
620
621 void sync_all_dmbs(time_t t)
622 {
623         static time_t lastrun = 0;
624         struct work_record *work;
625         int count=0;
626
627         /* Only do this if we are using a WINS server. */
628         if(we_are_a_wins_client() == False)
629                 return;
630
631         /* Check to see if we are a domain master browser on the
632            unicast subnet. */
633         work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
634         if (!work)
635                 return;
636
637         if (!AM_DOMAIN_MASTER_BROWSER(work))
638                 return;
639
640         if ((lastrun != 0) && (t < lastrun + (5 * 60)))
641                 return;
642      
643         /* count how many syncs we might need to do */
644         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
645                 if (strcmp(lp_workgroup(), work->work_group)) {
646                         count++;
647                 }
648         }
649
650         /* sync with a probability of 1/count */
651         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
652                 if (strcmp(lp_workgroup(), work->work_group)) {
653                         unstring dmb_name;
654
655                         if (((unsigned)sys_random()) % count != 0)
656                                 continue;
657
658                         lastrun = t;
659
660                         if (!work->dmb_name.name[0]) {
661                                 /* we don't know the DMB - assume it is
662                                    the same as the unicast local master */
663                                 make_nmb_name(&work->dmb_name, 
664                                               work->local_master_browser_name,
665                                               0x20);
666                         }
667
668                         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
669
670                         DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
671                                  dmb_name, inet_ntoa(work->dmb_addr)));
672
673                         sync_browse_lists(work, 
674                                           dmb_name,
675                                           work->dmb_name.name_type, 
676                                           work->dmb_addr, False, False);
677                 }
678         }
679 }