1997-12-13 17:16:07 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1997-12-13 17:16:07 +03:00
NBT netbios routines and daemon - version 2
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1994 - 1998
2003-08-23 05:59:14 +04:00
Copyright ( C ) Jeremy Allison 1994 - 2003
1997-12-13 17:16:07 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
/* This is our local master browser list database. */
1999-12-13 16:27:58 +03:00
extern ubi_dlList lmb_browserlist [ ] ;
1997-12-13 17:16:07 +03:00
/****************************************************************************
As a domain master browser , do a sync with a local master browser .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
1997-12-13 17:16:07 +03:00
static void sync_with_lmb ( struct browse_cache_record * browc )
{
2003-08-23 05:59:14 +04:00
struct work_record * work ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
if ( ! ( work = find_workgroup_on_subnet ( unicast_subnet , browc - > work_group ) ) ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " sync_with_lmb: \n " ) ;
dbgtext ( " Failed to get a workgroup for a local master browser " ) ;
dbgtext ( " cache entry workgroup " ) ;
dbgtext ( " %s, server %s \n " , browc - > work_group , browc - > lmb_name ) ;
}
return ;
}
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* We should only be doing this if we are a domain master browser for
the given workgroup . Ensure this is so . */
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
if ( ! AM_DOMAIN_MASTER_BROWSER ( work ) ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " sync_with_lmb: \n " ) ;
dbgtext ( " We are trying to sync with a local master browser " ) ;
dbgtext ( " %s for workgroup %s \n " , browc - > lmb_name , browc - > work_group ) ;
dbgtext ( " and we are not a domain master browser on this workgroup. \n " ) ;
dbgtext ( " Error! \n " ) ;
}
return ;
}
if ( DEBUGLVL ( 2 ) ) {
dbgtext ( " sync_with_lmb: \n " ) ;
dbgtext ( " Initiating sync with local master browser " ) ;
dbgtext ( " %s<0x20> at IP %s " , browc - > lmb_name , inet_ntoa ( browc - > ip ) ) ;
dbgtext ( " for workgroup %s \n " , browc - > work_group ) ;
}
sync_browse_lists ( work , browc - > lmb_name , 0x20 , browc - > ip , True , True ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
browc - > sync_time + = ( CHECK_TIME_DMB_TO_LMB_SYNC * 60 ) ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Sync or expire any local master browsers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
1997-12-13 17:16:07 +03:00
void dmb_expire_and_sync_browser_lists ( time_t t )
{
2003-08-23 05:59:14 +04:00
static time_t last_run = 0 ;
struct browse_cache_record * browc ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Only do this every 20 seconds. */
if ( t - last_run < 20 )
return ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
last_run = t ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
expire_lmb_browsers ( t ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
for ( browc = ( struct browse_cache_record * ) ubi_dlFirst ( lmb_browserlist ) ;
browc ;
browc = ( struct browse_cache_record * ) ubi_dlNext ( browc ) ) {
if ( browc - > sync_time < t )
sync_with_lmb ( browc ) ;
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
As a local master browser , send an announce packet to the domain master browser .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void announce_local_master_browser_to_domain_master_browser ( struct work_record * work )
{
2003-08-23 05:59:14 +04:00
pstring outbuf ;
2004-03-16 00:45:45 +03:00
unstring myname ;
2004-05-28 02:57:50 +04:00
unstring dmb_name ;
2003-08-23 05:59:14 +04:00
char * p ;
if ( ismyip ( work - > dmb_addr ) ) {
if ( DEBUGLVL ( 2 ) ) {
dbgtext ( " announce_local_master_browser_to_domain_master_browser: \n " ) ;
dbgtext ( " We are both a domain and a local master browser for " ) ;
dbgtext ( " workgroup %s. " , work - > work_group ) ;
dbgtext ( " Do not announce to ourselves. \n " ) ;
}
return ;
}
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
p = outbuf ;
SCVAL ( p , 0 , ANN_MasterAnnouncement ) ;
p + + ;
1997-12-13 17:16:07 +03:00
2004-03-16 00:45:45 +03:00
unstrcpy ( myname , global_myname ( ) ) ;
2003-08-23 05:59:14 +04:00
strupper_m ( myname ) ;
myname [ 15 ] = ' \0 ' ;
/* The call below does CH_UNIX -> CH_DOS conversion. JRA */
push_pstring_base ( p , myname , outbuf ) ;
2003-04-23 17:27:35 +04:00
2003-08-23 05:59:14 +04:00
p = skip_string ( p , 1 ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 4 ) ) {
dbgtext ( " announce_local_master_browser_to_domain_master_browser: \n " ) ;
dbgtext ( " Sending local master announce to " ) ;
dbgtext ( " %s for workgroup %s. \n " , nmb_namestr ( & work - > dmb_name ) ,
work - > work_group ) ;
}
1997-12-13 17:16:07 +03:00
2004-05-28 02:57:50 +04:00
/* Target name for send_mailslot must be in UNIX charset. */
pull_ascii_nstring ( dmb_name , sizeof ( dmb_name ) , work - > dmb_name . name ) ;
2003-08-23 05:59:14 +04:00
send_mailslot ( True , BROWSE_MAILSLOT , outbuf , PTR_DIFF ( p , outbuf ) ,
2004-05-28 02:57:50 +04:00
global_myname ( ) , 0x0 , dmb_name , 0x0 ,
1998-08-30 21:04:24 +04:00
work - > dmb_addr , FIRST_SUBNET - > myip , DGRAM_PORT ) ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
As a local master browser , do a sync with a domain master browser .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void sync_with_dmb ( struct work_record * work )
{
2004-03-16 00:45:45 +03:00
unstring dmb_name ;
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 2 ) ) {
dbgtext ( " sync_with_dmb: \n " ) ;
dbgtext ( " Initiating sync with domain master browser " ) ;
dbgtext ( " %s " , nmb_namestr ( & work - > dmb_name ) ) ;
dbgtext ( " at IP %s " , inet_ntoa ( work - > dmb_addr ) ) ;
dbgtext ( " for workgroup %s \n " , work - > work_group ) ;
}
1997-12-13 17:16:07 +03:00
2004-03-16 00:45:45 +03:00
pull_ascii_nstring ( dmb_name , sizeof ( dmb_name ) , work - > dmb_name . name ) ;
2003-08-23 05:59:14 +04:00
sync_browse_lists ( work , dmb_name , work - > dmb_name . name_type ,
work - > dmb_addr , False , True ) ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function called when a node status query to a domain master browser IP succeeds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void domain_master_node_status_success ( struct subnet_record * subrec ,
struct userdata_struct * userdata ,
struct res_rec * answers ,
struct in_addr from_ip )
{
2003-08-23 05:59:14 +04:00
struct work_record * work = find_workgroup_on_subnet ( subrec , userdata - > data ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
if ( work = = NULL ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " domain_master_node_status_success: \n " ) ;
dbgtext ( " Unable to find workgroup " ) ;
dbgtext ( " %s on subnet %s. \n " , userdata - > data , subrec - > subnet_name ) ;
}
return ;
}
if ( DEBUGLVL ( 3 ) ) {
dbgtext ( " domain_master_node_status_success: \n " ) ;
dbgtext ( " Success in node status for workgroup " ) ;
dbgtext ( " %s from ip %s \n " , work - > work_group , inet_ntoa ( from_ip ) ) ;
}
1997-12-13 17:16:07 +03:00
/* Go through the list of names found at answers->rdata and look for
the first SERVER < 0x20 > name . */
2003-08-23 05:59:14 +04:00
if ( answers - > rdata ! = NULL ) {
char * p = answers - > rdata ;
int numnames = CVAL ( p , 0 ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
p + = 1 ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
while ( numnames - - ) {
2004-03-16 00:45:45 +03:00
unstring qname ;
2003-08-23 05:59:14 +04:00
uint16 nb_flags ;
int name_type ;
1997-12-13 17:16:07 +03:00
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( qname , sizeof ( qname ) , p ) ;
2003-08-23 05:59:14 +04:00
name_type = CVAL ( p , 15 ) ;
nb_flags = get_nb_flags ( & p [ 16 ] ) ;
2003-09-05 23:59:55 +04:00
trim_char ( qname , ' \0 ' , ' ' ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
p + = 18 ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
if ( ! ( nb_flags & NB_GROUP ) & & ( name_type = = 0x20 ) ) {
struct nmb_name nmbname ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
make_nmb_name ( & nmbname , qname , name_type ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Copy the dmb name and IP address
into the workgroup struct . */
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
work - > dmb_name = nmbname ;
putip ( ( char * ) & work - > dmb_addr , & from_ip ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Do the local master browser announcement to the domain
master browser name and IP . */
announce_local_master_browser_to_domain_master_browser ( work ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Now synchronise lists with the domain master browser. */
sync_with_dmb ( work ) ;
break ;
}
}
} else if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " domain_master_node_status_success: \n " ) ;
dbgtext ( " Failed to find a SERVER<0x20> name in reply from IP " ) ;
dbgtext ( " %s. \n " , inet_ntoa ( from_ip ) ) ;
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function called when a node status query to a domain master browser IP fails .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void domain_master_node_status_fail ( struct subnet_record * subrec ,
struct response_record * rrec )
{
2003-08-23 05:59:14 +04:00
struct userdata_struct * userdata = rrec - > userdata ;
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " domain_master_node_status_fail: \n " ) ;
dbgtext ( " Doing a node status request to the domain master browser \n " ) ;
dbgtext ( " for workgroup %s " , userdata ? userdata - > data : " NULL " ) ;
dbgtext ( " at IP %s failed. \n " , inet_ntoa ( rrec - > packet - > ip ) ) ;
dbgtext ( " Cannot sync browser lists. \n " ) ;
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function called when a query for a WORKGROUP < 1 b > name succeeds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void find_domain_master_name_query_success ( struct subnet_record * subrec ,
struct userdata_struct * userdata_in ,
struct nmb_name * q_name , struct in_addr answer_ip , struct res_rec * rrec )
{
2003-08-23 05:59:14 +04:00
/*
* Unfortunately , finding the IP address of the Domain Master Browser ,
* as we have here , is not enough . We need to now do a sync to the
* SERVERNAME < 0x20 > NetBIOS name , as only recent NT servers will
* respond to the SMBSERVER name . To get this name from IP
* address we do a Node status request , and look for the first
* NAME < 0x20 > in the response , and take that as the server name .
* We also keep a cache of the Domain Master Browser name for this
* workgroup in the Workgroup struct , so that if the same IP addess
* is returned every time , we don ' t need to do the node status
* request .
*/
struct work_record * work ;
struct nmb_name nmbname ;
struct userdata_struct * userdata ;
size_t size = sizeof ( struct userdata_struct ) + sizeof ( fstring ) + 1 ;
2004-03-16 00:45:45 +03:00
unstring qname ;
2003-08-23 05:59:14 +04:00
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( qname , sizeof ( qname ) , q_name - > name ) ;
2003-08-23 05:59:14 +04:00
if ( ! ( work = find_workgroup_on_subnet ( subrec , qname ) ) ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " find_domain_master_name_query_success: \n " ) ;
dbgtext ( " Failed to find workgroup %s \n " , qname ) ;
}
return ;
1997-12-13 17:16:07 +03:00
}
/* First check if we already have a dmb for this workgroup. */
2003-08-23 05:59:14 +04:00
if ( ! is_zero_ip ( work - > dmb_addr ) & & ip_equal ( work - > dmb_addr , answer_ip ) ) {
/* Do the local master browser announcement to the domain
master browser name and IP . */
announce_local_master_browser_to_domain_master_browser ( work ) ;
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Now synchronise lists with the domain master browser. */
sync_with_dmb ( work ) ;
return ;
} else {
zero_ip ( & work - > dmb_addr ) ;
}
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* Now initiate the node status request. */
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* We used to use the name "*",0x0 here, but some Windows
* servers don ' t answer that name . However we * know * they
* have the name workgroup # 1 b ( as we just looked it up ) .
* So do the node status request on this name instead .
* Found at LBL labs . JRA .
*/
1998-01-09 08:33:27 +03:00
2003-08-23 05:59:14 +04:00
make_nmb_name ( & nmbname , work - > work_group , 0x1b ) ;
/* Put the workgroup name into the userdata so we know
what workgroup we ' re talking to when the reply comes
back . */
/* Setup the userdata_struct - this is copied so we can use
a stack variable for this . */
2004-12-07 21:25:53 +03:00
if ( ( userdata = ( struct userdata_struct * ) SMB_MALLOC ( size ) ) = = NULL ) {
2003-08-23 05:59:14 +04:00
DEBUG ( 0 , ( " find_domain_master_name_query_success: malloc fail. \n " ) ) ;
return ;
}
userdata - > copy_fn = NULL ;
userdata - > free_fn = NULL ;
userdata - > userdata_len = strlen ( work - > work_group ) + 1 ;
overmalloc_safe_strcpy ( userdata - > data , work - > work_group , size - sizeof ( * userdata ) - 1 ) ;
node_status ( subrec , & nmbname , answer_ip ,
domain_master_node_status_success ,
domain_master_node_status_fail ,
userdata ) ;
zero_free ( userdata , size ) ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function called when a query for a WORKGROUP < 1 b > name fails .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
1997-12-13 17:16:07 +03:00
static void find_domain_master_name_query_fail ( struct subnet_record * subrec ,
struct response_record * rrec ,
struct nmb_name * question_name , int fail_code )
{
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " find_domain_master_name_query_fail: \n " ) ;
dbgtext ( " Unable to find the Domain Master Browser name " ) ;
dbgtext ( " %s for the workgroup %s. \n " ,
nmb_namestr ( question_name ) , question_name - > name ) ;
dbgtext ( " Unable to sync browse lists in this workgroup. \n " ) ;
}
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
As a local master browser for a workgroup find the domain master browser
name , announce ourselves as local master browser to it and then pull the
full domain browse lists from it onto the given subnet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void announce_and_sync_with_domain_master_browser ( struct subnet_record * subrec ,
struct work_record * work )
{
2003-08-23 05:59:14 +04:00
/* Only do this if we are using a WINS server. */
if ( we_are_a_wins_client ( ) = = False ) {
if ( DEBUGLVL ( 10 ) ) {
dbgtext ( " announce_and_sync_with_domain_master_browser: \n " ) ;
dbgtext ( " Ignoring, as we are not a WINS client. \n " ) ;
}
return ;
}
1997-12-13 17:16:07 +03:00
2003-08-23 05:59:14 +04:00
/* First, query for the WORKGROUP<1b> name from the WINS server. */
query_name ( unicast_subnet , work - > work_group , 0x1b ,
1997-12-13 17:16:07 +03:00
find_domain_master_name_query_success ,
find_domain_master_name_query_fail ,
NULL ) ;
}
1997-12-24 10:10:04 +03:00
/****************************************************************************
Function called when a node status query to a domain master browser IP succeeds .
This function is only called on query to a Samba 1.9 .18 or above WINS server .
Note that adding the workgroup name is enough for this workgroup to be
browsable by clients , as clients query the WINS server or broadcast
nets for the WORKGROUP < 1 b > name when they want to browse a workgroup
they are not in . We do not need to do a sync with this Domain Master
Browser in order for our browse clients to see machines in this workgroup .
JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void get_domain_master_name_node_status_success ( struct subnet_record * subrec ,
struct userdata_struct * userdata ,
struct res_rec * answers ,
struct in_addr from_ip )
{
2003-08-23 05:59:14 +04:00
struct work_record * work ;
2004-03-16 00:45:45 +03:00
unstring server_name ;
1998-08-30 13:50:45 +04:00
2003-08-23 05:59:14 +04:00
server_name [ 0 ] = 0 ;
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 3 ) ) {
dbgtext ( " get_domain_master_name_node_status_success: \n " ) ;
dbgtext ( " Success in node status from ip %s \n " , inet_ntoa ( from_ip ) ) ;
}
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
/*
* Go through the list of names found at answers - > rdata and look for
* the first WORKGROUP < 0x1b > name .
*/
if ( answers - > rdata ! = NULL ) {
char * p = answers - > rdata ;
int numnames = CVAL ( p , 0 ) ;
p + = 1 ;
while ( numnames - - ) {
2004-03-16 00:45:45 +03:00
unstring qname ;
2003-08-23 05:59:14 +04:00
uint16 nb_flags ;
int name_type ;
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( qname , sizeof ( qname ) , p ) ;
2003-08-23 05:59:14 +04:00
name_type = CVAL ( p , 15 ) ;
nb_flags = get_nb_flags ( & p [ 16 ] ) ;
2003-09-05 23:59:55 +04:00
trim_char ( qname , ' \0 ' , ' ' ) ;
2003-08-23 05:59:14 +04:00
p + = 18 ;
if ( ! ( nb_flags & NB_GROUP ) & & ( name_type = = 0x00 ) & &
server_name [ 0 ] = = 0 ) {
/* this is almost certainly the server netbios name */
2004-03-16 00:45:45 +03:00
unstrcpy ( server_name , qname ) ;
2003-08-23 05:59:14 +04:00
continue ;
}
if ( ! ( nb_flags & NB_GROUP ) & & ( name_type = = 0x1b ) ) {
if ( DEBUGLVL ( 5 ) ) {
dbgtext ( " get_domain_master_name_node_status_success: \n " ) ;
dbgtext ( " %s(%s) " , server_name , inet_ntoa ( from_ip ) ) ;
dbgtext ( " is a domain master browser for workgroup " ) ;
dbgtext ( " %s. Adding this name. \n " , qname ) ;
}
/*
* If we don ' t already know about this workgroup , add it
* to the workgroup list on the unicast_subnet .
*/
if ( ( work = find_workgroup_on_subnet ( subrec , qname ) ) = = NULL ) {
struct nmb_name nmbname ;
/*
* Add it - with an hour in the cache .
*/
if ( ! ( work = create_workgroup_on_subnet ( subrec , qname , 60 * 60 ) ) )
return ;
/* remember who the master is */
2004-03-16 00:45:45 +03:00
unstrcpy ( work - > local_master_browser_name , server_name ) ;
2003-08-23 05:59:14 +04:00
make_nmb_name ( & nmbname , server_name , 0x20 ) ;
work - > dmb_name = nmbname ;
work - > dmb_addr = from_ip ;
}
break ;
}
}
} else if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " get_domain_master_name_node_status_success: \n " ) ;
dbgtext ( " Failed to find a WORKGROUP<0x1b> name in reply from IP " ) ;
dbgtext ( " %s. \n " , inet_ntoa ( from_ip ) ) ;
}
1997-12-24 10:10:04 +03:00
}
/****************************************************************************
Function called when a node status query to a domain master browser IP fails .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void get_domain_master_name_node_status_fail ( struct subnet_record * subrec ,
struct response_record * rrec )
{
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " get_domain_master_name_node_status_fail: \n " ) ;
dbgtext ( " Doing a node status request to the domain master browser " ) ;
dbgtext ( " at IP %s failed. \n " , inet_ntoa ( rrec - > packet - > ip ) ) ;
dbgtext ( " Cannot get workgroup name. \n " ) ;
}
1997-12-24 10:10:04 +03:00
}
1998-10-21 21:26:54 +04:00
1997-12-24 10:10:04 +03:00
/****************************************************************************
Function called when a query for * < 1 b > name succeeds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void find_all_domain_master_names_query_success ( struct subnet_record * subrec ,
struct userdata_struct * userdata_in ,
struct nmb_name * q_name , struct in_addr answer_ip , struct res_rec * rrec )
{
2003-08-23 05:59:14 +04:00
/*
* We now have a list of all the domain master browsers for all workgroups
* that have registered with the WINS server . Now do a node status request
* to each one and look for the first 1 b name in the reply . This will be
* the workgroup name that we will add to the unicast subnet as a ' non - local '
* workgroup .
*/
struct nmb_name nmbname ;
struct in_addr send_ip ;
int i ;
if ( DEBUGLVL ( 5 ) ) {
dbgtext ( " find_all_domain_master_names_query_succes: \n " ) ;
dbgtext ( " Got answer from WINS server of %d " , ( rrec - > rdlength / 6 ) ) ;
dbgtext ( " IP addresses for Domain Master Browsers. \n " ) ;
}
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
for ( i = 0 ; i < rrec - > rdlength / 6 ; i + + ) {
/* Initiate the node status requests. */
make_nmb_name ( & nmbname , " * " , 0 ) ;
putip ( ( char * ) & send_ip , ( char * ) & rrec - > rdata [ ( i * 6 ) + 2 ] ) ;
/*
* Don ' t send node status requests to ourself .
*/
if ( ismyip ( send_ip ) ) {
if ( DEBUGLVL ( 5 ) ) {
dbgtext ( " find_all_domain_master_names_query_succes: \n " ) ;
dbgtext ( " Not sending node status to our own IP " ) ;
dbgtext ( " %s. \n " , inet_ntoa ( send_ip ) ) ;
}
continue ;
}
if ( DEBUGLVL ( 5 ) ) {
dbgtext ( " find_all_domain_master_names_query_success: \n " ) ;
dbgtext ( " Sending node status request to IP %s. \n " , inet_ntoa ( send_ip ) ) ;
}
node_status ( subrec , & nmbname , send_ip ,
get_domain_master_name_node_status_success ,
get_domain_master_name_node_status_fail ,
NULL ) ;
}
1997-12-24 10:10:04 +03:00
}
/****************************************************************************
Function called when a query for * < 1 b > name fails .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void find_all_domain_master_names_query_fail ( struct subnet_record * subrec ,
struct response_record * rrec ,
struct nmb_name * question_name , int fail_code )
{
2003-08-23 05:59:14 +04:00
if ( DEBUGLVL ( 10 ) ) {
dbgtext ( " find_domain_master_name_query_fail: \n " ) ;
dbgtext ( " WINS server did not reply to a query for name " ) ;
dbgtext ( " %s. \n This means it " , nmb_namestr ( question_name ) ) ;
dbgtext ( " is probably not a Samba 1.9.18 or above WINS server. \n " ) ;
}
1997-12-24 10:10:04 +03:00
}
/****************************************************************************
If we are a domain master browser on the unicast subnet , do a query to the
WINS server for the * < 1 b > name . This will only work to a Samba WINS server ,
so ignore it if we fail . If we succeed , contact each of the IP addresses in
turn and do a node status request to them . If this succeeds then look for a
< 1 b > name in the reply - this is the workgroup name . Add this to the unicast
subnet . This is expensive , so we only do this every 15 minutes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
1997-12-24 10:10:04 +03:00
void collect_all_workgroup_names_from_wins_server ( time_t t )
{
2003-08-23 05:59:14 +04:00
static time_t lastrun = 0 ;
struct work_record * work ;
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
/* Only do this if we are using a WINS server. */
if ( we_are_a_wins_client ( ) = = False )
return ;
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
/* Check to see if we are a domain master browser on the unicast subnet. */
if ( ( work = find_workgroup_on_subnet ( unicast_subnet , lp_workgroup ( ) ) ) = = NULL ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " collect_all_workgroup_names_from_wins_server: \n " ) ;
dbgtext ( " Cannot find my workgroup %s " , lp_workgroup ( ) ) ;
dbgtext ( " on subnet %s. \n " , unicast_subnet - > subnet_name ) ;
}
return ;
}
if ( ! AM_DOMAIN_MASTER_BROWSER ( work ) )
return ;
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
if ( ( lastrun ! = 0 ) & & ( t < lastrun + ( 15 * 60 ) ) )
return ;
lastrun = t ;
1997-12-24 10:10:04 +03:00
2003-08-23 05:59:14 +04:00
/* First, query for the *<1b> name from the WINS server. */
query_name ( unicast_subnet , " * " , 0x1b ,
find_all_domain_master_names_query_success ,
find_all_domain_master_names_query_fail ,
NULL ) ;
1997-12-24 10:10:04 +03:00
}
1998-08-30 19:58:17 +04:00
/****************************************************************************
If we are a domain master browser on the unicast subnet , do a regular sync
1998-08-31 10:59:23 +04:00
with all other DMBs that we know of on that subnet .
To prevent exponential network traffic with large numbers of workgroups
we use a randomised system where sync probability is inversely proportional
to the number of known workgroups
1998-08-30 19:58:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-23 05:59:14 +04:00
1998-08-30 19:58:17 +04:00
void sync_all_dmbs ( time_t t )
{
static time_t lastrun = 0 ;
struct work_record * work ;
1998-08-31 10:59:23 +04:00
int count = 0 ;
1998-08-30 19:58:17 +04:00
/* Only do this if we are using a WINS server. */
if ( we_are_a_wins_client ( ) = = False )
return ;
/* Check to see if we are a domain master browser on the
unicast subnet . */
2002-11-13 02:20:50 +03:00
work = find_workgroup_on_subnet ( unicast_subnet , lp_workgroup ( ) ) ;
2003-08-23 05:59:14 +04:00
if ( ! work )
return ;
1998-08-30 19:58:17 +04:00
if ( ! AM_DOMAIN_MASTER_BROWSER ( work ) )
return ;
1998-08-31 10:59:23 +04:00
if ( ( lastrun ! = 0 ) & & ( t < lastrun + ( 5 * 60 ) ) )
1998-08-30 19:58:17 +04:00
return ;
1998-08-31 10:59:23 +04:00
/* count how many syncs we might need to do */
for ( work = unicast_subnet - > workgrouplist ; work ; work = work - > next ) {
2004-03-13 05:47:21 +03:00
if ( strcmp ( lp_workgroup ( ) , work - > work_group ) ) {
1998-08-31 10:59:23 +04:00
count + + ;
}
}
1998-08-30 19:58:17 +04:00
1998-08-31 10:59:23 +04:00
/* sync with a probability of 1/count */
1998-08-30 19:58:17 +04:00
for ( work = unicast_subnet - > workgrouplist ; work ; work = work - > next ) {
2004-03-13 05:47:21 +03:00
if ( strcmp ( lp_workgroup ( ) , work - > work_group ) ) {
2004-03-16 00:45:45 +03:00
unstring dmb_name ;
2003-08-23 05:59:14 +04:00
if ( ( ( unsigned ) sys_random ( ) ) % count ! = 0 )
continue ;
1998-08-31 10:59:23 +04:00
1998-08-30 19:58:17 +04:00
lastrun = t ;
1998-08-31 11:23:11 +04:00
if ( ! work - > dmb_name . name [ 0 ] ) {
/* we don't know the DMB - assume it is
the same as the unicast local master */
make_nmb_name ( & work - > dmb_name ,
work - > local_master_browser_name ,
2000-01-07 09:55:36 +03:00
0x20 ) ;
1998-08-31 11:23:11 +04:00
}
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( dmb_name , sizeof ( dmb_name ) , work - > dmb_name . name ) ;
2003-08-23 05:59:14 +04:00
1998-10-21 21:26:54 +04:00
DEBUG ( 3 , ( " Initiating DMB<->DMB sync with %s(%s) \n " ,
2003-08-23 05:59:14 +04:00
dmb_name , inet_ntoa ( work - > dmb_addr ) ) ) ;
1998-08-30 19:58:17 +04:00
sync_browse_lists ( work ,
2003-08-23 05:59:14 +04:00
dmb_name ,
1998-08-30 19:58:17 +04:00
work - > dmb_name . name_type ,
work - > dmb_addr , False , False ) ;
}
}
2003-08-23 05:59:14 +04:00
}