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