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
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.
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.
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.
26 /* This is our local master browser list database. */
27 extern ubi_dlList lmb_browserlist[];
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)
34 struct work_record *work;
36 if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
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 );
48 /* We should only be doing this if we are a domain master browser for
49 the given workgroup. Ensure this is so. */
51 if(!AM_DOMAIN_MASTER_BROWSER(work))
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" );
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 );
72 sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
74 browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
77 /****************************************************************************
78 Sync or expire any local master browsers.
79 **************************************************************************/
80 void dmb_expire_and_sync_browser_lists(time_t t)
82 static time_t last_run = 0;
83 struct browse_cache_record *browc;
85 /* Only do this every 20 seconds. */
86 if (t - last_run < 20)
91 expire_lmb_browsers(t);
93 for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
95 browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
97 if (browc->sync_time < t)
102 /****************************************************************************
103 As a local master browser, send an announce packet to the domain master browser.
104 **************************************************************************/
106 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
112 if(ismyip(work->dmb_addr))
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" );
124 memset(outbuf,'\0',sizeof(outbuf));
126 SCVAL(p,0,ANN_MasterAnnouncement);
129 fstrcpy(myname, global_myname());
132 push_pstring_base(p, myname, outbuf);
134 p = skip_string(p,1);
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),
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);
150 /****************************************************************************
151 As a local master browser, do a sync with a domain master browser.
152 **************************************************************************/
154 static void sync_with_dmb(struct work_record *work)
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 );
165 sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type,
166 work->dmb_addr, False, True);
169 /****************************************************************************
170 Function called when a node status query to a domain master browser IP succeeds.
171 ****************************************************************************/
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)
178 struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
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 );
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) );
198 /* Go through the list of names found at answers->rdata and look for
199 the first SERVER<0x20> name. */
201 if(answers->rdata != NULL)
203 char *p = answers->rdata;
204 int numnames = CVAL(p, 0);
215 name_type = CVAL(p,15);
216 nb_flags = get_nb_flags(&p[16]);
217 trim_string(qname,NULL," ");
221 if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
223 struct nmb_name nmbname;
225 make_nmb_name(&nmbname, qname, name_type);
227 /* Copy the dmb name and IP address
228 into the workgroup struct. */
230 work->dmb_name = nmbname;
231 putip((char *)&work->dmb_addr, &from_ip);
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 );
237 /* Now synchronise lists with the domain master browser. */
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) );
252 /****************************************************************************
253 Function called when a node status query to a domain master browser IP fails.
254 ****************************************************************************/
256 static void domain_master_node_status_fail(struct subnet_record *subrec,
257 struct response_record *rrec)
259 struct userdata_struct *userdata = rrec->userdata;
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" );
271 /****************************************************************************
272 Function called when a query for a WORKGROUP<1b> name succeeds.
273 ****************************************************************************/
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)
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
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;
297 if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
301 dbgtext( "find_domain_master_name_query_success:\n" );
302 dbgtext( "Failed to find workgroup %s\n", q_name->name );
307 /* First check if we already have a dmb for this workgroup. */
309 if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip))
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 );
315 /* Now synchronise lists with the domain master browser. */
320 zero_ip(&work->dmb_addr);
322 /* Now initiate the node status request. */
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.
331 make_nmb_name(&nmbname,work->work_group,0x1b);
333 /* Put the workgroup name into the userdata so we know
334 what workgroup we're talking to when the reply comes
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)
341 DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
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);
350 node_status( subrec, &nmbname, answer_ip,
351 domain_master_node_status_success,
352 domain_master_node_status_fail,
355 zero_free(userdata, size);
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)
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" );
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 **************************************************************************/
381 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
382 struct work_record *work)
384 struct nmb_name nmbname;
386 /* Only do this if we are using a WINS server. */
387 if(we_are_a_wins_client() == False)
391 dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
392 dbgtext( "Ignoring, as we are not a WINS client.\n" );
397 make_nmb_name(&nmbname,work->work_group,0x1b);
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,
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.
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.
417 ****************************************************************************/
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)
424 struct work_record *work;
431 dbgtext( "get_domain_master_name_node_status_success:\n" );
432 dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
436 * Go through the list of names found at answers->rdata and look for
437 * the first WORKGROUP<0x1b> name.
440 if(answers->rdata != NULL)
442 char *p = answers->rdata;
443 int numnames = CVAL(p, 0);
454 name_type = CVAL(p,15);
455 nb_flags = get_nb_flags(&p[16]);
456 trim_string(qname,NULL," ");
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);
467 if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
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 );
478 * If we don't already know about this workgroup, add it
479 * to the workgroup list on the unicast_subnet.
481 if((work = find_workgroup_on_subnet( subrec, qname)) == NULL)
483 struct nmb_name nmbname;
485 * Add it - with an hour in the cache.
487 if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
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;
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) );
509 /****************************************************************************
510 Function called when a node status query to a domain master browser IP fails.
511 ****************************************************************************/
513 static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
514 struct response_record *rrec)
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" );
525 /****************************************************************************
526 Function called when a query for *<1b> name succeeds.
527 ****************************************************************************/
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)
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'
541 struct nmb_name nmbname;
542 struct in_addr send_ip;
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" );
552 for(i = 0; i < rrec->rdlength / 6; i++)
554 /* Initiate the node status requests. */
555 make_nmb_name(&nmbname, "*", 0);
557 putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
560 * Don't send node status requests to ourself.
563 if(ismyip( send_ip ))
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) );
576 dbgtext( "find_all_domain_master_names_query_success:\n" );
577 dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
580 node_status( subrec, &nmbname, send_ip,
581 get_domain_master_name_node_status_success,
582 get_domain_master_name_node_status_fail,
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)
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" );
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)
613 static time_t lastrun = 0;
614 struct work_record *work;
615 struct nmb_name nmbname;
617 /* Only do this if we are using a WINS server. */
618 if(we_are_a_wins_client() == False)
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)
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 );
633 if(!AM_DOMAIN_MASTER_BROWSER(work))
636 if ((lastrun != 0) && (t < lastrun + (15 * 60)))
641 make_nmb_name(&nmbname,"*",0x1b);
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,
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.
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)
661 static time_t lastrun = 0;
662 struct work_record *work;
665 /* Only do this if we are using a WINS server. */
666 if(we_are_a_wins_client() == False)
669 /* Check to see if we are a domain master browser on the
671 work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
674 if (!AM_DOMAIN_MASTER_BROWSER(work))
677 if ((lastrun != 0) && (t < lastrun + (5 * 60)))
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)) {
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;
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,
702 DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
704 inet_ntoa(work->dmb_addr)));
705 sync_browse_lists(work,
707 work->dmb_name.name_type,
708 work->dmb_addr, False, False);