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