s3-param Remove special case for global_myname(), rename to lp_netbios_name()
[gd/samba-autobuild/.git] / source3 / 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 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
26 /* This is our local master browser list database. */
27 extern struct browse_cache_record *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 = lmb_browserlist; browc; browc = browc->next ) {
91                 if (browc->sync_time < t)
92                         sync_with_lmb(browc);
93         }
94 }
95
96 /****************************************************************************
97 As a local master browser, send an announce packet to the domain master browser.
98 **************************************************************************/
99
100 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
101 {
102         char outbuf[1024];
103         unstring myname;
104         unstring dmb_name;
105         char *p;
106
107         if(ismyip_v4(work->dmb_addr)) {
108                 if( DEBUGLVL( 2 ) ) {
109                         dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
110                         dbgtext( "We are both a domain and a local master browser for " );
111                         dbgtext( "workgroup %s.  ", work->work_group );
112                         dbgtext( "Do not announce to ourselves.\n" );
113                 }
114                 return;
115         }
116
117         memset(outbuf,'\0',sizeof(outbuf));
118         p = outbuf;
119         SCVAL(p,0,ANN_MasterAnnouncement);
120         p++;
121
122         unstrcpy(myname, lp_netbios_name());
123         strupper_m(myname);
124         myname[15]='\0';
125         /* The call below does CH_UNIX -> CH_DOS conversion. JRA */
126         push_ascii(p, myname, sizeof(outbuf)-PTR_DIFF(p,outbuf)-1, STR_TERMINATE);
127
128         p = skip_string(outbuf,sizeof(outbuf),p);
129
130         if( DEBUGLVL( 4 ) ) {
131                 dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
132                 dbgtext( "Sending local master announce to " );
133                 dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
134                                         work->work_group );
135         }
136
137         /* Target name for send_mailslot must be in UNIX charset. */
138         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
139         send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
140                 lp_netbios_name(), 0x0, dmb_name, 0x0,
141                 work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
142 }
143
144 /****************************************************************************
145 As a local master browser, do a sync with a domain master browser.
146 **************************************************************************/
147
148 static void sync_with_dmb(struct work_record *work)
149 {
150         unstring dmb_name;
151
152         if( DEBUGLVL( 2 ) ) {
153                 dbgtext( "sync_with_dmb:\n" );
154                 dbgtext( "Initiating sync with domain master browser " );
155                 dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
156                 dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
157                 dbgtext( "for workgroup %s\n", work->work_group );
158         }
159
160         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
161         sync_browse_lists(work, dmb_name, work->dmb_name.name_type, 
162                 work->dmb_addr, False, True);
163 }
164
165 /****************************************************************************
166   Function called when a node status query to a domain master browser IP succeeds.
167 ****************************************************************************/
168
169 static void domain_master_node_status_success(struct subnet_record *subrec,
170                                               struct userdata_struct *userdata,
171                                               struct res_rec *answers,
172                                               struct in_addr from_ip)
173 {
174         struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
175
176         if( work == NULL ) {
177                 if( DEBUGLVL( 0 ) ) {
178                         dbgtext( "domain_master_node_status_success:\n" );
179                         dbgtext( "Unable to find workgroup " );
180                         dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
181                 }
182                 return;
183         }
184
185         if( DEBUGLVL( 3 ) ) {
186                 dbgtext( "domain_master_node_status_success:\n" );
187                 dbgtext( "Success in node status for workgroup " );
188                 dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
189         }
190
191   /* Go through the list of names found at answers->rdata and look for
192      the first SERVER<0x20> name. */
193
194         if(answers->rdata != NULL) {
195                 char *p = answers->rdata;
196                 int numnames = CVAL(p, 0);
197
198                 p += 1;
199
200                 while (numnames--) {
201                         unstring qname;
202                         uint16 nb_flags;
203                         int name_type;
204
205                         pull_ascii_nstring(qname, sizeof(qname), p);
206                         name_type = CVAL(p,15);
207                         nb_flags = get_nb_flags(&p[16]);
208                         trim_char(qname,'\0',' ');
209
210                         p += 18;
211
212                         if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
213                                 struct nmb_name nmbname;
214
215                                 make_nmb_name(&nmbname, qname, name_type);
216
217                                 /* Copy the dmb name and IP address
218                                         into the workgroup struct. */
219
220                                 work->dmb_name = nmbname;
221                                 putip((char *)&work->dmb_addr, &from_ip);
222
223                                 /* Do the local master browser announcement to the domain
224                                         master browser name and IP. */
225                                 announce_local_master_browser_to_domain_master_browser( work );
226
227                                 /* Now synchronise lists with the domain master browser. */
228                                 sync_with_dmb(work);
229                                 break;
230                         }
231                 }
232         } else if( DEBUGLVL( 0 ) ) {
233                 dbgtext( "domain_master_node_status_success:\n" );
234                 dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
235                 dbgtext( "%s.\n", inet_ntoa(from_ip) );
236         }
237 }
238
239 /****************************************************************************
240   Function called when a node status query to a domain master browser IP fails.
241 ****************************************************************************/
242
243 static void domain_master_node_status_fail(struct subnet_record *subrec,
244                        struct response_record *rrec)
245 {
246         struct userdata_struct *userdata = rrec->userdata;
247
248         if( DEBUGLVL( 0 ) ) {
249                 dbgtext( "domain_master_node_status_fail:\n" );
250                 dbgtext( "Doing a node status request to the domain master browser\n" );
251                 dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
252                 dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
253                 dbgtext( "Cannot sync browser lists.\n" );
254         }
255 }
256
257 /****************************************************************************
258   Function called when a query for a WORKGROUP<1b> name succeeds.
259 ****************************************************************************/
260
261 static void find_domain_master_name_query_success(struct subnet_record *subrec,
262                         struct userdata_struct *userdata_in,
263                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
264 {
265         /* 
266          * Unfortunately, finding the IP address of the Domain Master Browser,
267          * as we have here, is not enough. We need to now do a sync to the
268          * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
269          * respond to the SMBSERVER name. To get this name from IP
270          * address we do a Node status request, and look for the first
271          * NAME<0x20> in the response, and take that as the server name.
272          * We also keep a cache of the Domain Master Browser name for this
273          * workgroup in the Workgroup struct, so that if the same IP addess
274          * is returned every time, we don't need to do the node status
275          * request.
276          */
277
278         struct work_record *work;
279         struct nmb_name nmbname;
280         struct userdata_struct *userdata;
281         size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
282         unstring qname;
283
284         pull_ascii_nstring(qname, sizeof(qname), q_name->name);
285         if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
286                 if( DEBUGLVL( 0 ) ) {
287                         dbgtext( "find_domain_master_name_query_success:\n" );
288                         dbgtext( "Failed to find workgroup %s\n", qname);
289                 }
290         return;
291   }
292
293   /* First check if we already have a dmb for this workgroup. */
294
295         if(!is_zero_ip_v4(work->dmb_addr) && ip_equal_v4(work->dmb_addr, answer_ip)) {
296                 /* Do the local master browser announcement to the domain
297                         master browser name and IP. */
298                 announce_local_master_browser_to_domain_master_browser( work );
299
300                 /* Now synchronise lists with the domain master browser. */
301                 sync_with_dmb(work);
302                 return;
303         } else {
304                 zero_ip_v4(&work->dmb_addr);
305         }
306
307         /* Now initiate the node status request. */
308
309         /* We used to use the name "*",0x0 here, but some Windows
310          * servers don't answer that name. However we *know* they
311          * have the name workgroup#1b (as we just looked it up).
312          * So do the node status request on this name instead.
313          * Found at LBL labs. JRA.
314          */
315
316         make_nmb_name(&nmbname,work->work_group,0x1b);
317
318         /* Put the workgroup name into the userdata so we know
319          what workgroup we're talking to when the reply comes
320          back. */
321
322         /* Setup the userdata_struct - this is copied so we can use
323         a stack variable for this. */
324
325         if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
326                 DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
327                 return;
328         }
329
330         userdata->copy_fn = NULL;
331         userdata->free_fn = NULL;
332         userdata->userdata_len = strlen(work->work_group)+1;
333         strlcpy(userdata->data, work->work_group, size - sizeof(*userdata));
334
335         node_status( subrec, &nmbname, answer_ip, 
336                 domain_master_node_status_success,
337                 domain_master_node_status_fail,
338                 userdata);
339
340         zero_free(userdata, size);
341 }
342
343 /****************************************************************************
344   Function called when a query for a WORKGROUP<1b> name fails.
345   ****************************************************************************/
346
347 static void find_domain_master_name_query_fail(struct subnet_record *subrec,
348                                     struct response_record *rrec,
349                                     struct nmb_name *question_name, int fail_code)
350 {
351         if( DEBUGLVL( 0 ) ) {
352                 dbgtext( "find_domain_master_name_query_fail:\n" );
353                 dbgtext( "Unable to find the Domain Master Browser name " );
354                 dbgtext( "%s for the workgroup %s.\n",
355                         nmb_namestr(question_name), question_name->name );
356                 dbgtext( "Unable to sync browse lists in this workgroup.\n" );
357         }
358 }
359
360 /****************************************************************************
361 As a local master browser for a workgroup find the domain master browser
362 name, announce ourselves as local master browser to it and then pull the
363 full domain browse lists from it onto the given subnet.
364 **************************************************************************/
365
366 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
367                                                    struct work_record *work)
368 {
369         /* Only do this if we are using a WINS server. */
370         if(we_are_a_wins_client() == False) {
371                 if( DEBUGLVL( 10 ) ) {
372                         dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
373                         dbgtext( "Ignoring, as we are not a WINS client.\n" );
374                 }
375                 return;
376         }
377
378         /* First, query for the WORKGROUP<1b> name from the WINS server. */
379         query_name(unicast_subnet, work->work_group, 0x1b,
380              find_domain_master_name_query_success,
381              find_domain_master_name_query_fail,
382              NULL);
383 }
384
385 /****************************************************************************
386   Function called when a node status query to a domain master browser IP succeeds.
387   This function is only called on query to a Samba 1.9.18 or above WINS server.
388
389   Note that adding the workgroup name is enough for this workgroup to be
390   browsable by clients, as clients query the WINS server or broadcast 
391   nets for the WORKGROUP<1b> name when they want to browse a workgroup
392   they are not in. We do not need to do a sync with this Domain Master
393   Browser in order for our browse clients to see machines in this workgroup.
394   JRA.
395 ****************************************************************************/
396
397 static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
398                                               struct userdata_struct *userdata,
399                                               struct res_rec *answers,
400                                               struct in_addr from_ip)
401 {
402         struct work_record *work;
403         unstring server_name;
404
405         server_name[0] = 0;
406
407         if( DEBUGLVL( 3 ) ) {
408                 dbgtext( "get_domain_master_name_node_status_success:\n" );
409                 dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
410         }
411
412         /* 
413          * Go through the list of names found at answers->rdata and look for
414          * the first WORKGROUP<0x1b> name.
415          */
416
417         if(answers->rdata != NULL) {
418                 char *p = answers->rdata;
419                 int numnames = CVAL(p, 0);
420
421                 p += 1;
422
423                 while (numnames--) {
424                         unstring qname;
425                         uint16 nb_flags;
426                         int name_type;
427
428                         pull_ascii_nstring(qname, sizeof(qname), p);
429                         name_type = CVAL(p,15);
430                         nb_flags = get_nb_flags(&p[16]);
431                         trim_char(qname,'\0',' ');
432
433                         p += 18;
434
435                         if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
436                                         server_name[0] == 0) {
437                                 /* this is almost certainly the server netbios name */
438                                 strlcpy(server_name, qname, sizeof(server_name));
439                                 continue;
440                         }
441
442                         if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
443                                 if( DEBUGLVL( 5 ) ) {
444                                         dbgtext( "get_domain_master_name_node_status_success:\n" );
445                                         dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
446                                         dbgtext( "is a domain master browser for workgroup " );
447                                         dbgtext( "%s. Adding this name.\n", qname );
448                                 }
449
450                                 /* 
451                                  * If we don't already know about this workgroup, add it
452                                  * to the workgroup list on the unicast_subnet.
453                                  */
454
455                                 if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
456                                         struct nmb_name nmbname;
457                                         /* 
458                                          * Add it - with an hour in the cache.
459                                          */
460                                         if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
461                                                 return;
462
463                                         /* remember who the master is */
464                                         strlcpy(work->local_master_browser_name,
465                                                 server_name,
466                                                 sizeof(work->local_master_browser_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_v4( 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         /* leave if we don't have to do any syncs */
651         if (count == 0) {
652                 return;
653         }
654
655         /* sync with a probability of 1/count */
656         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
657                 if (strcmp(lp_workgroup(), work->work_group)) {
658                         unstring dmb_name;
659
660                         if (((unsigned)sys_random()) % count != 0)
661                                 continue;
662
663                         lastrun = t;
664
665                         if (!work->dmb_name.name[0]) {
666                                 /* we don't know the DMB - assume it is
667                                    the same as the unicast local master */
668                                 make_nmb_name(&work->dmb_name, 
669                                               work->local_master_browser_name,
670                                               0x20);
671                         }
672
673                         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
674
675                         DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
676                                  dmb_name, inet_ntoa(work->dmb_addr)));
677
678                         sync_browse_lists(work, 
679                                           dmb_name,
680                                           work->dmb_name.name_type, 
681                                           work->dmb_addr, False, False);
682                 }
683         }
684 }