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