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
Copyright ( C ) Jeremy Allison 1994 - 1998
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"
1997-12-16 12:20:34 +03:00
extern BOOL found_lm_clients ;
1997-12-13 17:16:07 +03:00
#if 0
/* XXXX note: This function is currently unsuitable for use, as it
does not properly check that a server is in a fit state to become
a backup browser before asking it to be one .
The code is left here to be worked on at a later date .
*/
/****************************************************************************
Tell a server to become a backup browser
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void tell_become_backup ( void )
{
struct subnet_record * subrec ;
for ( subrec = FIRST_SUBNET ; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST ( subrec ) )
{
struct work_record * work ;
for ( work = subrec - > workgrouplist ; work ; work = work - > next )
{
struct server_record * servrec ;
int num_servers = 0 ;
int num_backups = 0 ;
for ( servrec = work - > serverlist ; servrec ; servrec = servrec - > next )
{
num_servers + + ;
if ( is_myname ( servrec - > serv . name ) )
continue ;
if ( servrec - > serv . type & SV_TYPE_BACKUP_BROWSER )
{
num_backups + + ;
continue ;
}
if ( servrec - > serv . type & SV_TYPE_MASTER_BROWSER )
continue ;
if ( ! ( servrec - > serv . type & SV_TYPE_POTENTIAL_BROWSER ) )
continue ;
DEBUG ( 3 , ( " num servers: %d num backups: %d \n " ,
num_servers , num_backups ) ) ;
/* make first server a backup server. thereafter make every
tenth server a backup server */
if ( num_backups ! = 0 & & ( num_servers + 9 ) / num_backups > 10 )
continue ;
DEBUG ( 2 , ( " sending become backup to %s %s for %s \n " ,
servrec - > serv . name , inet_ntoa ( subrec - > bcast_ip ) ,
work - > work_group ) ) ;
/* type 11 request from MYNAME(20) to WG(1e) for SERVER */
do_announce_request ( servrec - > serv . name , work - > work_group ,
ANN_BecomeBackup , 0x20 , 0x1e , subrec - > bcast_ip ) ;
}
}
}
}
# endif
/*******************************************************************
Process an incoming host announcement packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_host_announce ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
int ttl = IVAL ( buf , 1 ) / 1000 ;
char * announce_name = buf + 5 ;
uint32 servertype = IVAL ( buf , 23 ) ;
char * comment = buf + 31 ;
struct work_record * work ;
struct server_record * servrec ;
2002-11-13 02:20:50 +03:00
const char * work_name ;
1997-12-13 17:16:07 +03:00
char * source_name = dgram - > source_name . name ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( host_announce ) ;
1997-12-13 17:16:07 +03:00
comment [ 43 ] = 0 ;
DEBUG ( 3 , ( " process_host_announce: from %s<%02x> IP %s to \
% s for server % s . \ n " , source_name, source_name[15], inet_ntoa(p->ip),
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > dest_name ) , announce_name ) ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 5 , ( " process_host_announce: ttl=%d server type=%08x comment=%s \n " ,
ttl , servertype , comment ) ) ;
/* Filter servertype to remove impossible bits. */
servertype & = ~ ( SV_TYPE_LOCAL_LIST_ONLY | SV_TYPE_DOMAIN_ENUM ) ;
/* A host announcement must be sent to the name WORKGROUP<1d>. */
if ( dgram - > dest_name . name_type ! = 0x1d )
{
DEBUG ( 2 , ( " process_host_announce: incorrect name type for destination from IP %s \
( was % 02 x ) should be 0x1d . Allowing packet anyway . \ n " ,
inet_ntoa ( p - > ip ) , dgram - > dest_name . name_type ) ) ;
/* Change it so it was. */
dgram - > dest_name . name_type = 0x1d ;
}
/* For a host announce the workgroup name is the destination name. */
work_name = dgram - > dest_name . name ;
1997-12-16 10:30:25 +03:00
/*
* Syntax servers version 5.1 send HostAnnounce packets to
* * THE WRONG NAME * . They send to LOCAL_MASTER_BROWSER_NAME < 00 >
* instead of WORKGROUP < 1 d > name . So to fix this we check if
* the workgroup name is our own name , and if so change it
* to be our primary workgroup name .
*/
2002-11-13 02:20:50 +03:00
if ( strequal ( work_name , global_myname ( ) ) )
work_name = lp_workgroup ( ) ;
1997-12-16 10:30:25 +03:00
1997-12-13 17:16:07 +03:00
/*
* We are being very agressive here in adding a workgroup
* name on the basis of a host announcing itself as being
* in that workgroup . Maybe we should wait for the workgroup
* announce instead ? JRA .
*/
1997-12-24 11:49:44 +03:00
work = find_workgroup_on_subnet ( subrec , work_name ) ;
if ( servertype ! = 0 )
1997-12-13 17:16:07 +03:00
{
1997-12-24 11:49:44 +03:00
if ( work = = NULL )
{
/* We have no record of this workgroup. Add it. */
if ( ( work = create_workgroup_on_subnet ( subrec , work_name , ttl ) ) = = NULL )
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-24 11:49:44 +03:00
}
1997-12-13 17:16:07 +03:00
1997-12-24 11:49:44 +03:00
if ( ( servrec = find_server_in_workgroup ( work , announce_name ) ) = = NULL )
{
/* If this server is not already in the workgroup, add it. */
create_server_on_workgroup ( work , announce_name ,
servertype | SV_TYPE_LOCAL_LIST_ONLY ,
ttl , comment ) ;
}
else
{
/* Update the record. */
servrec - > serv . type = servertype | SV_TYPE_LOCAL_LIST_ONLY ;
update_server_ttl ( servrec , ttl ) ;
StrnCpy ( servrec - > serv . comment , comment , sizeof ( servrec - > serv . comment ) - 1 ) ;
}
1997-12-13 17:16:07 +03:00
}
else
{
1997-12-24 11:49:44 +03:00
/*
* This server is announcing it is going down . Remove it from the
* workgroup .
*/
if ( ! is_myname ( announce_name ) & & ( work ! = NULL ) & &
( ( servrec = find_server_in_workgroup ( work , announce_name ) ) ! = NULL )
)
{
remove_server_from_workgroup ( work , servrec ) ;
}
1997-12-13 17:16:07 +03:00
}
subrec - > work_changed = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( host_announce ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Process an incoming WORKGROUP announcement packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_workgroup_announce ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
int ttl = IVAL ( buf , 1 ) / 1000 ;
char * workgroup_announce_name = buf + 5 ;
uint32 servertype = IVAL ( buf , 23 ) ;
char * master_name = buf + 31 ;
struct work_record * work ;
char * source_name = dgram - > source_name . name ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( workgroup_announce ) ;
1997-12-13 17:16:07 +03:00
master_name [ 43 ] = 0 ;
DEBUG ( 3 , ( " process_workgroup_announce: from %s<%02x> IP %s to \
% s for workgroup % s . \ n " , source_name, source_name[15], inet_ntoa(p->ip),
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > dest_name ) , workgroup_announce_name ) ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 5 , ( " process_workgroup_announce: ttl=%d server type=%08x master browser=%s \n " ,
ttl , servertype , master_name ) ) ;
/* Workgroup announcements must only go to the MSBROWSE name. */
if ( ! strequal ( dgram - > dest_name . name , MSBROWSE ) | | ( dgram - > dest_name . name_type ! = 0x1 ) )
{
DEBUG ( 0 , ( " process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s \n " ,
1998-11-14 04:04:13 +03:00
inet_ntoa ( p - > ip ) , nmb_namestr ( & dgram - > dest_name ) ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
if ( ( work = find_workgroup_on_subnet ( subrec , workgroup_announce_name ) ) = = NULL )
{
/* We have no record of this workgroup. Add it. */
if ( ( work = create_workgroup_on_subnet ( subrec , workgroup_announce_name , ttl ) ) = = NULL )
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
else
{
/* Update the workgroup death_time. */
update_workgroup_ttl ( work , ttl ) ;
}
if ( * work - > local_master_browser_name = = ' \0 ' )
{
/* Set the master browser name. */
1997-12-16 12:20:34 +03:00
set_workgroup_local_master_browser_name ( work , master_name ) ;
1997-12-13 17:16:07 +03:00
}
subrec - > work_changed = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( workgroup_announce ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Process an incoming local master browser announcement packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_local_master_announce ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
int ttl = IVAL ( buf , 1 ) / 1000 ;
char * server_name = buf + 5 ;
uint32 servertype = IVAL ( buf , 23 ) ;
char * comment = buf + 31 ;
char * work_name ;
struct work_record * work ;
struct server_record * servrec ;
char * source_name = dgram - > source_name . name ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( local_master_announce ) ;
1997-12-13 17:16:07 +03:00
comment [ 43 ] = 0 ;
DEBUG ( 3 , ( " process_local_master_announce: from %s<%02x> IP %s to \
% s for server % s . \ n " , source_name, source_name[15], inet_ntoa(p->ip),
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > dest_name ) , server_name ) ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 5 , ( " process_local_master_announce: ttl=%d server type=%08x comment=%s \n " ,
ttl , servertype , comment ) ) ;
/* A local master announcement must be sent to the name WORKGROUP<1e>. */
if ( dgram - > dest_name . name_type ! = 0x1e )
{
DEBUG ( 0 , ( " process_local_master_announce: incorrect name type for destination from IP %s \
( was % 02 x ) should be 0x1e . Ignoring packet . \ n " ,
inet_ntoa ( p - > ip ) , dgram - > dest_name . name_type ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
/* Filter servertype to remove impossible bits. */
servertype & = ~ ( SV_TYPE_LOCAL_LIST_ONLY | SV_TYPE_DOMAIN_ENUM ) ;
/* For a local master announce the workgroup name is the destination name. */
work_name = dgram - > dest_name . name ;
if ( ( work = find_workgroup_on_subnet ( subrec , work_name ) ) = = NULL )
{
1997-12-24 11:49:44 +03:00
/* Don't bother adding if it's a local master release announce. */
if ( servertype = = 0 )
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-24 11:49:44 +03:00
1997-12-13 17:16:07 +03:00
/* We have no record of this workgroup. Add it. */
if ( ( work = create_workgroup_on_subnet ( subrec , work_name , ttl ) ) = = NULL )
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
/* If we think we're the local master browser for this workgroup,
we should never have got this packet . We don ' t see our own
packets .
*/
if ( AM_LOCAL_MASTER_BROWSER ( work ) )
{
DEBUG ( 0 , ( " process_local_master_announce: Server %s at IP %s is announcing itself as \
a local master browser for workgroup % s and we think we are master . Forcing election . \ n " ,
server_name , inet_ntoa ( p - > ip ) , work_name ) ) ;
/* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
they have become a local master browser once , they will never
stop sending local master announcements . To fix this we send
them a reset browser packet , with level 0x2 on the __SAMBA__
name that only they should be listening to . */
send_browser_reset ( 0x2 , " __SAMBA__ " , 0x20 , p - > ip ) ;
/* We should demote ourself and force an election. */
1998-06-27 04:27:44 +04:00
unbecome_local_master_browser ( subrec , work , True ) ;
1997-12-13 17:16:07 +03:00
/* The actual election requests are handled in
nmbd_election . c */
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
/* Find the server record on this workgroup. If it doesn't exist, add it. */
1997-12-24 11:49:44 +03:00
if ( servertype ! = 0 )
1997-12-13 17:16:07 +03:00
{
1997-12-24 11:49:44 +03:00
if ( ( servrec = find_server_in_workgroup ( work , server_name ) ) = = NULL )
{
/* If this server is not already in the workgroup, add it. */
create_server_on_workgroup ( work , server_name ,
servertype | SV_TYPE_LOCAL_LIST_ONLY ,
ttl , comment ) ;
}
else
{
/* Update the record. */
servrec - > serv . type = servertype | SV_TYPE_LOCAL_LIST_ONLY ;
update_server_ttl ( servrec , ttl ) ;
StrnCpy ( servrec - > serv . comment , comment , sizeof ( servrec - > serv . comment ) - 1 ) ;
}
set_workgroup_local_master_browser_name ( work , server_name ) ;
1997-12-13 17:16:07 +03:00
}
else
{
1997-12-24 11:49:44 +03:00
/*
* This server is announcing it is going down . Remove it from the
* workgroup .
*/
if ( ! is_myname ( server_name ) & & ( work ! = NULL ) & &
( ( servrec = find_server_in_workgroup ( work , server_name ) ) ! = NULL )
)
{
remove_server_from_workgroup ( work , servrec ) ;
}
1997-12-13 17:16:07 +03:00
}
subrec - > work_changed = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( local_master_announce ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Process a domain master announcement frame .
Domain master browsers receive these from local masters . The Domain
master should then issue a sync with the local master , asking for
that machines local server list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_master_browser_announce ( struct subnet_record * subrec ,
struct packet_struct * p , char * buf )
{
char * local_master_name = buf ;
struct work_record * work ;
struct browse_cache_record * browrec ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( master_browser_announce ) ;
1997-12-13 17:16:07 +03:00
local_master_name [ 15 ] = 0 ;
DEBUG ( 3 , ( " process_master_browser_announce: Local master announce from %s IP %s. \n " ,
local_master_name , inet_ntoa ( p - > ip ) ) ) ;
if ( ! lp_domain_master ( ) )
{
DEBUG ( 0 , ( " process_master_browser_announce: Not configured as domain \
master - ignoring master announce . \ n " ));
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
2002-11-13 02:20:50 +03:00
if ( ( work = find_workgroup_on_subnet ( subrec , lp_workgroup ( ) ) ) = = NULL )
1997-12-13 17:16:07 +03:00
{
DEBUG ( 0 , ( " process_master_browser_announce: Cannot find workgroup %s on subnet %s \n " ,
2002-11-13 02:20:50 +03:00
lp_workgroup ( ) , subrec - > subnet_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
if ( ! AM_DOMAIN_MASTER_BROWSER ( work ) )
{
DEBUG ( 0 , ( " process_master_browser_announce: Local master announce made to us from \
% s IP % s and we are not a domain master browser . \ n " , local_master_name, inet_ntoa(p->ip)));
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
/* Add this host as a local master browser entry on the browse lists.
This causes a sync request to be made to it at a later date .
*/
if ( ( browrec = find_browser_in_lmb_cache ( local_master_name ) ) = = NULL )
{
/* Add it. */
create_browser_in_lmb_cache ( work - > work_group , local_master_name , p - > ip ) ;
}
else
update_browser_death_time ( browrec ) ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( master_browser_announce ) ;
1997-12-13 17:16:07 +03:00
}
1997-12-16 12:20:34 +03:00
/*******************************************************************
Process an incoming LanMan host announcement packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_lm_host_announce ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
uint32 servertype = IVAL ( buf , 1 ) ;
int osmajor = CVAL ( buf , 5 ) ; /* major version of node software */
int osminor = CVAL ( buf , 6 ) ; /* minor version of node software */
int ttl = SVAL ( buf , 7 ) ;
char * announce_name = buf + 9 ;
struct work_record * work ;
struct server_record * servrec ;
2002-11-13 02:20:50 +03:00
const char * work_name ;
1997-12-16 12:20:34 +03:00
char * source_name = dgram - > source_name . name ;
pstring comment ;
char * s = buf + 9 ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( lm_host_announce ) ;
1997-12-16 12:20:34 +03:00
s = skip_string ( s , 1 ) ;
StrnCpy ( comment , s , 43 ) ;
DEBUG ( 3 , ( " process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \
% s for server % s . \ n " , source_name, source_name[15], inet_ntoa(p->ip),
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > dest_name ) , announce_name ) ) ;
1997-12-16 12:20:34 +03:00
DEBUG ( 5 , ( " process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s \n " ,
osmajor , osminor , ttl , servertype , comment ) ) ;
if ( ( osmajor < 36 ) | | ( osmajor > 38 ) | | ( osminor ! = 0 ) )
{
1998-02-24 20:59:34 +03:00
DEBUG ( 5 , ( " process_lm_host_announce: LM Announcement packet does not \
originate from OS / 2 Warp client . Ignoring packet . \ n " ));
1997-12-16 12:20:34 +03:00
/* Could have been from a Windows machine (with its LM Announce enabled),
or a Samba server . Then don ' t disrupt the current browse list . */
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-16 12:20:34 +03:00
}
/* Filter servertype to remove impossible bits. */
servertype & = ~ ( SV_TYPE_LOCAL_LIST_ONLY | SV_TYPE_DOMAIN_ENUM ) ;
/* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
if ( dgram - > dest_name . name_type ! = 0x00 )
{
DEBUG ( 2 , ( " process_lm_host_announce: incorrect name type for destination from IP %s \
( was % 02 x ) should be 0x00 . Allowing packet anyway . \ n " ,
inet_ntoa ( p - > ip ) , dgram - > dest_name . name_type ) ) ;
/* Change it so it was. */
dgram - > dest_name . name_type = 0x00 ;
}
/* For a LanMan host announce the workgroup name is the destination name. */
work_name = dgram - > dest_name . name ;
/*
* Syntax servers version 5.1 send HostAnnounce packets to
* * THE WRONG NAME * . They send to LOCAL_MASTER_BROWSER_NAME < 00 >
* instead of WORKGROUP < 1 d > name . So to fix this we check if
* the workgroup name is our own name , and if so change it
* to be our primary workgroup name . This code is probably
* not needed in the LanMan announce code , but it won ' t hurt .
*/
2002-11-13 02:20:50 +03:00
if ( strequal ( work_name , global_myname ( ) ) )
work_name = lp_workgroup ( ) ;
1997-12-16 12:20:34 +03:00
/*
* We are being very agressive here in adding a workgroup
* name on the basis of a host announcing itself as being
* in that workgroup . Maybe we should wait for the workgroup
* announce instead ? JRA .
*/
1997-12-24 11:49:44 +03:00
work = find_workgroup_on_subnet ( subrec , work_name ) ;
1997-12-16 12:20:34 +03:00
1997-12-24 11:49:44 +03:00
if ( servertype ! = 0 )
1997-12-16 12:20:34 +03:00
{
1997-12-24 11:49:44 +03:00
if ( work = = NULL )
{
/* We have no record of this workgroup. Add it. */
if ( ( work = create_workgroup_on_subnet ( subrec , work_name , ttl ) ) = = NULL )
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-24 11:49:44 +03:00
}
if ( ( servrec = find_server_in_workgroup ( work , announce_name ) ) = = NULL )
{
/* If this server is not already in the workgroup, add it. */
create_server_on_workgroup ( work , announce_name ,
servertype | SV_TYPE_LOCAL_LIST_ONLY ,
ttl , comment ) ;
}
else
{
/* Update the record. */
servrec - > serv . type = servertype | SV_TYPE_LOCAL_LIST_ONLY ;
update_server_ttl ( servrec , ttl ) ;
StrnCpy ( servrec - > serv . comment , comment , sizeof ( servrec - > serv . comment ) - 1 ) ;
}
1997-12-16 12:20:34 +03:00
}
else
{
1997-12-24 11:49:44 +03:00
/*
* This server is announcing it is going down . Remove it from the
* workgroup .
*/
if ( ! is_myname ( announce_name ) & & ( work ! = NULL ) & &
( ( servrec = find_server_in_workgroup ( work , announce_name ) ) ! = NULL )
)
{
remove_server_from_workgroup ( work , servrec ) ;
}
1997-12-16 12:20:34 +03:00
}
subrec - > work_changed = True ;
found_lm_clients = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( lm_host_announce ) ;
1997-12-16 12:20:34 +03:00
}
1997-12-13 17:16:07 +03:00
/****************************************************************************
Send a backup list response .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void send_backup_list_response ( struct subnet_record * subrec ,
1998-08-30 21:04:24 +04:00
struct work_record * work ,
struct nmb_name * send_to_name ,
unsigned char max_number_requested ,
uint32 token , struct in_addr sendto_ip ,
int port )
1997-12-13 17:16:07 +03:00
{
char outbuf [ 1024 ] ;
1998-09-29 01:43:48 +04:00
char * p , * countptr ;
1998-01-09 08:33:27 +03:00
unsigned int count = 0 ;
1999-12-13 16:27:58 +03:00
#if 0
1997-12-13 17:16:07 +03:00
struct server_record * servrec ;
1999-12-13 16:27:58 +03:00
# endif
1997-12-13 17:16:07 +03:00
1999-12-13 16:27:58 +03:00
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 3 , ( " send_backup_list_response: sending backup list for workgroup %s to %s IP %s \n " ,
1998-11-14 04:04:13 +03:00
work - > work_group , nmb_namestr ( send_to_name ) , inet_ntoa ( sendto_ip ) ) ) ;
1997-12-13 17:16:07 +03:00
p = outbuf ;
SCVAL ( p , 0 , ANN_GetBackupListResp ) ; /* Backup list response opcode. */
p + + ;
countptr = p ;
p + + ;
SIVAL ( p , 0 , token ) ; /* The sender's unique info. */
p + = 4 ;
/* We always return at least one name - our own. */
count = 1 ;
2002-11-13 02:20:50 +03:00
StrnCpy ( p , global_myname ( ) , 15 ) ;
1997-12-13 17:16:07 +03:00
strupper ( p ) ;
p = skip_string ( p , 1 ) ;
/* Look for backup browsers in this workgroup. */
1999-12-13 16:27:58 +03:00
#if 0
/* we don't currently send become_backup requests so we should never
send any other servers names out as backups for our
workgroup . That ' s why this is commented out ( tridge ) */
/*
* NB . Note that the struct work_record here is not neccessarily
* attached to the subnet * subrec .
*/
1997-12-13 17:16:07 +03:00
for ( servrec = work - > serverlist ; servrec ; servrec = servrec - > next )
{
1999-12-13 16:27:58 +03:00
int len = PTR_DIFF ( p , outbuf ) ;
1997-12-13 17:16:07 +03:00
if ( ( sizeof ( outbuf ) - len ) < 16 )
break ;
1998-01-09 08:33:27 +03:00
if ( count > = ( unsigned int ) max_number_requested )
1997-12-13 17:16:07 +03:00
break ;
2002-11-13 02:20:50 +03:00
if ( strnequal ( servrec - > serv . name , global_myname ( ) , 15 ) )
1997-12-13 17:16:07 +03:00
continue ;
if ( ! ( servrec - > serv . type & SV_TYPE_BACKUP_BROWSER ) )
continue ;
StrnCpy ( p , servrec - > serv . name , 15 ) ;
strupper ( p ) ;
count + + ;
DEBUG ( 5 , ( " send_backup_list_response: Adding server %s number %d \n " ,
p , count ) ) ;
p = skip_string ( p , 1 ) ;
}
1999-12-13 16:27:58 +03:00
# endif
1997-12-13 17:16:07 +03:00
SCVAL ( countptr , 0 , count ) ;
DEBUG ( 4 , ( " send_backup_list_response: sending response to %s<00> IP %s with %d servers. \n " ,
send_to_name - > name , inet_ntoa ( sendto_ip ) , count ) ) ;
send_mailslot ( True , BROWSE_MAILSLOT ,
outbuf , PTR_DIFF ( p , outbuf ) ,
2002-11-13 02:20:50 +03:00
global_myname ( ) , 0 ,
1997-12-13 17:16:07 +03:00
send_to_name - > name , 0 ,
1998-08-30 21:04:24 +04:00
sendto_ip , subrec - > myip , port ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Process a send backup list request packet .
A client sends a backup list request to ask for a list of servers on
the net that maintain server lists for a domain . A server is then
chosen from this list to send NetServerEnum commands to to list
available servers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_get_backup_list_request ( struct subnet_record * subrec ,
struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
struct work_record * work ;
unsigned char max_number_requested = CVAL ( buf , 0 ) ;
uint32 token = IVAL ( buf , 1 ) ; /* Sender's key index for the workgroup. */
int name_type = dgram - > dest_name . name_type ;
char * workgroup_name = dgram - > dest_name . name ;
1999-12-13 16:27:58 +03:00
struct subnet_record * search_subrec = subrec ;
1997-12-13 17:16:07 +03:00
2001-09-05 22:43:55 +04:00
START_PROFILE ( get_backup_list ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 3 , ( " process_get_backup_list_request: request from %s IP %s to %s. \n " ,
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > source_name ) , inet_ntoa ( p - > ip ) ,
nmb_namestr ( & dgram - > dest_name ) ) ) ;
1997-12-13 17:16:07 +03:00
/* We have to be a master browser, or a domain master browser
for the requested workgroup . That means it must be our
workgroup . */
2002-11-13 02:20:50 +03:00
if ( strequal ( workgroup_name , lp_workgroup ( ) ) = = False )
1997-12-13 17:16:07 +03:00
{
DEBUG ( 7 , ( " process_get_backup_list_request: Ignoring announce request for workgroup %s. \n " ,
workgroup_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
1999-12-13 16:27:58 +03:00
if ( ( work = find_workgroup_on_subnet ( search_subrec , workgroup_name ) ) = = NULL )
1997-12-13 17:16:07 +03:00
{
DEBUG ( 0 , ( " process_get_backup_list_request: Cannot find workgroup %s on \
1999-12-13 16:27:58 +03:00
subnet % s . \ n " , workgroup_name, search_subrec->subnet_name));
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
1999-12-13 16:27:58 +03:00
/*
* If the packet was sent to WORKGROUP < 1 b > instead
* of WORKGROUP < 1 d > then it was unicast to us a domain master
* browser . Change search subrec to unicast .
*/
1997-12-13 17:16:07 +03:00
if ( name_type = = 0x1b )
{
/* We must be a domain master browser in order to
process this packet . */
if ( ! AM_DOMAIN_MASTER_BROWSER ( work ) )
{
DEBUG ( 0 , ( " process_get_backup_list_request: domain list requested for workgroup %s \
and I am not a domain master browser . \ n " , workgroup_name));
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
1999-12-13 16:27:58 +03:00
search_subrec = unicast_subnet ;
1997-12-13 17:16:07 +03:00
}
else if ( name_type = = 0x1d )
{
/* We must be a local master browser in order to
process this packet . */
if ( ! AM_LOCAL_MASTER_BROWSER ( work ) )
{
DEBUG ( 0 , ( " process_get_backup_list_request: domain list requested for workgroup %s \
and I am not a local master browser . \ n " , workgroup_name));
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
}
else
{
DEBUG ( 0 , ( " process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d. \n " ,
name_type ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
send_backup_list_response ( subrec , work , & dgram - > source_name ,
1998-08-30 21:04:24 +04:00
max_number_requested , token , p - > ip , p - > port ) ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( get_backup_list ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
Process a reset browser state packet .
Diagnostic packet :
0x1 - Stop being a master browser and become a backup browser .
0x2 - Discard browse lists , stop being a master browser , try again .
0x4 - Stop being a master browser forever .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_reset_browser ( struct subnet_record * subrec ,
struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
int state = CVAL ( buf , 0 ) ;
struct subnet_record * sr ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( reset_browser ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 1 , ( " process_reset_browser: received diagnostic browser reset \
request from % s IP % s state = 0 x % X \ n " ,
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > source_name ) , inet_ntoa ( p - > ip ) , state ) ) ;
1997-12-13 17:16:07 +03:00
/* Stop being a local master browser on all our broadcast subnets. */
if ( state & 0x1 )
{
for ( sr = FIRST_SUBNET ; sr ; sr = NEXT_SUBNET_EXCLUDING_UNICAST ( sr ) )
{
struct work_record * work ;
for ( work = sr - > workgrouplist ; work ; work = work - > next )
{
if ( AM_LOCAL_MASTER_BROWSER ( work ) )
1998-06-27 04:27:44 +04:00
unbecome_local_master_browser ( sr , work , True ) ;
1997-12-13 17:16:07 +03:00
}
}
}
/* Discard our browse lists. */
if ( state & 0x2 )
{
/*
* Calling expire_workgroups_and_servers with a - 1
* time causes all servers not marked with a PERMANENT_TTL
* on the workgroup lists to be discarded , and all
* workgroups with empty server lists to be discarded .
* This means we keep our own server names and workgroup
* as these have a PERMANENT_TTL .
*/
expire_workgroups_and_servers ( - 1 ) ;
}
/* Request to stop browsing altogether. */
if ( state & 0x4 )
DEBUG ( 1 , ( " process_reset_browser: ignoring request to stop being a browser. \n " ) ) ;
2001-09-07 02:08:19 +04:00
2001-09-05 22:43:55 +04:00
END_PROFILE ( reset_browser ) ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
1997-12-16 12:20:34 +03:00
Process an announcement request packet .
1997-12-13 17:16:07 +03:00
We don ' t respond immediately , we just check it ' s a request for
1997-12-16 12:20:34 +03:00
our workgroup and then set the flag telling the announce code
1997-12-13 17:16:07 +03:00
in nmbd_sendannounce . c : announce_my_server_names that an
announcement is needed soon .
1997-12-16 12:20:34 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
void process_announce_request ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
struct work_record * work ;
char * workgroup_name = dgram - > dest_name . name ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( announce_request ) ;
1997-12-13 17:16:07 +03:00
DEBUG ( 3 , ( " process_announce_request: Announce request from %s IP %s to %s. \n " ,
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > source_name ) , inet_ntoa ( p - > ip ) ,
nmb_namestr ( & dgram - > dest_name ) ) ) ;
1997-12-13 17:16:07 +03:00
/* We only send announcement requests on our workgroup. */
2002-11-13 02:20:50 +03:00
if ( strequal ( workgroup_name , lp_workgroup ( ) ) = = False )
1997-12-13 17:16:07 +03:00
{
DEBUG ( 7 , ( " process_announce_request: Ignoring announce request for workgroup %s. \n " ,
workgroup_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
if ( ( work = find_workgroup_on_subnet ( subrec , workgroup_name ) ) = = NULL )
{
DEBUG ( 0 , ( " process_announce_request: Unable to find workgroup %s on subnet ! \n " ,
workgroup_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-13 17:16:07 +03:00
}
work - > needannounce = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( lm_host_announce ) ;
1997-12-13 17:16:07 +03:00
}
1997-12-16 12:20:34 +03:00
/*******************************************************************
Process a LanMan announcement request packet .
We don ' t respond immediately , we just check it ' s a request for
our workgroup and then set the flag telling that we have found
a LanMan client ( DOS or OS / 2 ) and that we will have to start
sending LanMan announcements ( unless specifically disabled
1997-12-24 10:10:04 +03:00
through the " lm announce " parameter in smb . conf )
1997-12-16 12:20:34 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_lm_announce_request ( struct subnet_record * subrec , struct packet_struct * p , char * buf )
{
struct dgram_packet * dgram = & p - > packet . dgram ;
char * workgroup_name = dgram - > dest_name . name ;
2001-09-05 22:43:55 +04:00
START_PROFILE ( lm_announce_request ) ;
1997-12-16 12:20:34 +03:00
DEBUG ( 3 , ( " process_lm_announce_request: Announce request from %s IP %s to %s. \n " ,
1998-11-14 04:04:13 +03:00
nmb_namestr ( & dgram - > source_name ) , inet_ntoa ( p - > ip ) ,
nmb_namestr ( & dgram - > dest_name ) ) ) ;
1997-12-16 12:20:34 +03:00
/* We only send announcement requests on our workgroup. */
2002-11-13 02:20:50 +03:00
if ( strequal ( workgroup_name , lp_workgroup ( ) ) = = False )
1997-12-16 12:20:34 +03:00
{
DEBUG ( 7 , ( " process_lm_announce_request: Ignoring announce request for workgroup %s. \n " ,
workgroup_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-16 12:20:34 +03:00
}
1998-09-29 01:43:48 +04:00
if ( find_workgroup_on_subnet ( subrec , workgroup_name ) = = NULL )
1997-12-16 12:20:34 +03:00
{
DEBUG ( 0 , ( " process_announce_request: Unable to find workgroup %s on subnet ! \n " ,
workgroup_name ) ) ;
2001-09-05 22:43:55 +04:00
goto done ;
1997-12-16 12:20:34 +03:00
}
found_lm_clients = True ;
2001-09-05 22:43:55 +04:00
done :
END_PROFILE ( lm_host_announce ) ;
1997-12-16 12:20:34 +03:00
}