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