source: vendor/current/source3/nmbd/nmbd_browsesync.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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