1996-07-07 13:29:56 +00:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
NBT netbios routines and daemon - version 2
1997-05-08 01:14:17 +00:00
Copyright ( C ) Andrew Tridgell 1994 - 1997
1996-07-07 13:29:56 +00: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 .
Revision History :
14 jan 96 : lkcl @ pires . co . uk
added multiple workgroup domain master support
04 jul 96 : lkcl @ pires . co . uk
created module namedbsubnet containing subnet database functions
*/
# include "includes.h"
# include "smb.h"
extern int ClientNMB ;
extern int ClientDGRAM ;
extern int DEBUGLEVEL ;
1997-04-09 01:19:25 +00:00
extern struct in_addr wins_ip ;
1996-07-07 13:29:56 +00:00
extern struct in_addr ipzero ;
extern pstring myname ;
1997-05-20 00:32:51 +00:00
extern fstring myworkgroup ;
1996-07-07 13:29:56 +00:00
BOOL updatedlists = True ;
int updatecount = 0 ;
/* local interfaces structure */
extern struct interface * local_interfaces ;
/* this is our domain/workgroup/server database */
struct subnet_record * subnetlist = NULL ;
1997-05-08 01:14:17 +00:00
/* WINS subnet - keep this separate so enumeration code doesn't
run onto it by mistake . */
1997-05-20 00:32:51 +00:00
struct subnet_record * wins_subnet = NULL ;
1997-05-08 01:14:17 +00:00
1996-08-01 17:49:40 +00:00
extern uint16 nb_type ; /* samba's NetBIOS name type */
1996-07-07 13:29:56 +00:00
/****************************************************************************
add a domain into the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void add_subnet ( struct subnet_record * d )
{
struct subnet_record * d2 ;
if ( ! subnetlist )
{
subnetlist = d ;
d - > prev = NULL ;
d - > next = NULL ;
return ;
}
for ( d2 = subnetlist ; d2 - > next ; d2 = d2 - > next ) ;
d2 - > next = d ;
d - > next = NULL ;
d - > prev = d2 ;
}
/****************************************************************************
1997-05-08 01:14:17 +00:00
find a subnet in the subnetlist - not including WINS .
1996-07-07 13:29:56 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct subnet_record * find_subnet ( struct in_addr bcast_ip )
{
struct subnet_record * d ;
/* search through subnet list for broadcast/netmask that matches
1997-05-08 01:14:17 +00:00
the source ip address . */
1996-07-07 13:29:56 +00:00
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_EXCLUDING_WINS ( d ) )
1996-07-07 13:29:56 +00:00
{
1997-05-08 01:14:17 +00:00
if ( same_net ( bcast_ip , d - > bcast_ip , d - > mask_ip ) )
return d ;
1996-07-07 13:29:56 +00:00
}
1997-04-09 01:19:25 +00:00
return ( NULL ) ;
1996-07-07 13:29:56 +00:00
}
/****************************************************************************
finds the appropriate subnet structure . directed packets ( non - bcast ) are
assumed to come from a point - to - point ( P or M node ) , and so the subnet we
return in this instance is the WINS ' pseudo - subnet ' with ip 255.255 .255 .255
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct subnet_record * find_req_subnet ( struct in_addr ip , BOOL bcast )
{
if ( bcast )
{
/* identify the subnet the broadcast request came from */
return find_subnet ( * iface_bcast ( ip ) ) ;
}
1997-05-08 01:14:17 +00:00
/* Return the subnet with the pseudo-ip of 255.255.255.255 */
return wins_subnet ;
1996-07-07 13:29:56 +00:00
}
1997-04-09 01:19:25 +00:00
/****************************************************************************
find a subnet in the subnetlist - if the subnet is not found
then return the WINS subnet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct subnet_record * find_subnet_all ( struct in_addr bcast_ip )
{
struct subnet_record * d = find_subnet ( bcast_ip ) ;
if ( ! d )
1997-05-08 01:14:17 +00:00
return wins_subnet ;
1997-05-20 00:32:51 +00:00
return d ;
1997-04-09 01:19:25 +00:00
}
1996-07-07 13:29:56 +00:00
/****************************************************************************
create a domain entry
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-05-08 01:14:17 +00:00
static struct subnet_record * make_subnet ( struct in_addr bcast_ip , struct in_addr mask_ip , BOOL add )
1996-07-07 13:29:56 +00:00
{
struct subnet_record * d ;
d = ( struct subnet_record * ) malloc ( sizeof ( * d ) ) ;
if ( ! d ) return ( NULL ) ;
bzero ( ( char * ) d , sizeof ( * d ) ) ;
1996-07-22 12:04:56 +00:00
DEBUG ( 4 , ( " making subnet %s " , inet_ntoa ( bcast_ip ) ) ) ;
1996-07-07 13:29:56 +00:00
DEBUG ( 4 , ( " %s \n " , inet_ntoa ( mask_ip ) ) ) ;
d - > bcast_ip = bcast_ip ;
d - > mask_ip = mask_ip ;
d - > workgrouplist = NULL ;
1997-05-08 01:14:17 +00:00
if ( add )
add_subnet ( d ) ;
1996-07-07 13:29:56 +00:00
return d ;
}
/****************************************************************************
1997-05-20 00:32:51 +00:00
add a domain entry . creates a workgroup , if necessary , and adds the domain
to the named a workgroup .
1996-07-07 13:29:56 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-05-20 00:32:51 +00:00
static struct subnet_record * add_subnet_entry ( struct in_addr bcast_ip ,
struct in_addr mask_ip , char * name ,
BOOL create_subnets , BOOL add )
1996-07-07 13:29:56 +00:00
{
1997-05-20 00:32:51 +00:00
struct subnet_record * d = NULL ;
1996-10-02 15:41:30 +00:00
1997-05-20 00:32:51 +00:00
if ( zero_ip ( bcast_ip ) )
bcast_ip = * iface_bcast ( bcast_ip ) ;
/* Note that we should also add into the WINS subnet as add_subnet_entry
should be called to add NetBIOS names and server entries on all
interfaces , including the WINS interface
*/
1996-10-02 15:41:30 +00:00
1997-05-20 00:32:51 +00:00
if ( create_subnets = = True )
{
/* Create new subnets. */
if ( ( d = make_subnet ( bcast_ip , mask_ip , add ) ) = = NULL )
1996-07-07 13:29:56 +00:00
{
1997-05-20 00:32:51 +00:00
DEBUG ( 0 , ( " add_subnet_entry: Unable to create subnet %s \n " ,
inet_ntoa ( bcast_ip ) ) ) ;
return NULL ;
1996-07-07 13:29:56 +00:00
}
1997-05-20 00:32:51 +00:00
return d ;
}
if ( ip_equal ( bcast_ip , wins_ip ) )
return wins_subnet ;
return find_subnet ( bcast_ip ) ;
1996-07-07 13:29:56 +00:00
}
/****************************************************************************
1997-05-20 00:32:51 +00:00
Add a workgroup into a subnet , and if it ' s our primary workgroup ,
add the required names to it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void add_workgroup_to_subnet ( struct subnet_record * d , char * group )
1996-07-07 13:29:56 +00:00
{
1997-05-20 00:32:51 +00:00
struct work_record * w = NULL ;
1996-07-07 13:29:56 +00:00
1997-05-20 00:32:51 +00:00
DEBUG ( 5 , ( " add_workgroup_to_subnet: Adding workgroup %s to subnet %s \n " ,
group , inet_ntoa ( d - > bcast_ip ) ) ) ;
1996-07-07 13:29:56 +00:00
1997-05-20 00:32:51 +00:00
/* This next statement creates the workgroup struct if it doesn't
already exist .
*/
if ( ( w = find_workgroupstruct ( d , group , True ) ) = = NULL )
{
DEBUG ( 0 , ( " add_workgroup_to_subnet: Unable to add workgroup %s to subnet %s \n " ,
group , inet_ntoa ( d - > bcast_ip ) ) ) ;
return ;
}
1997-05-08 01:14:17 +00:00
1997-05-30 20:40:48 +00:00
/* add WORKGROUP(00) entries into name database
or register with WINS server , if it ' s our workgroup .
1997-05-20 00:32:51 +00:00
*/
if ( strequal ( myworkgroup , group ) )
{
1997-05-30 20:40:48 +00:00
add_my_name_entry ( d , group , 0x0 , nb_type | NB_ACTIVE | NB_GROUP , False ) ;
1997-05-30 23:15:17 +00:00
add_my_name_entry ( d , group , 0x1e , nb_type | NB_ACTIVE | NB_GROUP , False ) ;
1997-05-20 00:32:51 +00:00
/* add samba server name to workgroup list. */
1997-07-01 01:23:34 +00:00
add_server_entry ( d , w , myname , w - > ServerType | SV_TYPE_LOCAL_LIST_ONLY , 0 ,
lp_serverstring ( ) , True ) ;
1997-05-20 00:32:51 +00:00
DEBUG ( 3 , ( " add_workgroup_to_subnet: Added server name entry %s to subnet %s \n " ,
myname , inet_ntoa ( d - > bcast_ip ) ) ) ;
}
1996-07-07 13:29:56 +00:00
}
/****************************************************************************
1997-05-20 00:32:51 +00:00
create subnet / workgroup / server entries
- add or create the subnet lists
- add or create the workgroup entries in each subnet entry
- register appropriate NetBIOS names for the workgroup entries
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void add_my_subnets ( char * group )
{
static BOOL create_subnets = True ;
struct subnet_record * d = NULL ;
struct interface * i = NULL ;
if ( * group = = ' * ' ) return ;
1996-07-07 13:29:56 +00:00
1997-05-20 00:32:51 +00:00
/* Create subnets from all the local interfaces and thread them onto
the linked list .
*/
for ( i = local_interfaces ; i ; i = i - > next )
{
add_subnet_entry ( i - > bcast , i - > nmask , group , create_subnets , True ) ;
}
1996-07-07 13:29:56 +00:00
1997-05-20 00:32:51 +00:00
/* If we are using WINS, then we must add the workgroup to the WINS
subnet . This is used as a place to keep collated server lists .
*/
1996-10-02 15:41:30 +00:00
1997-05-20 00:32:51 +00:00
/* Create the WINS subnet if we are using WINS - but don't thread it
onto the linked subnet list .
*/
if ( lp_wins_support ( ) | | lp_wins_server ( ) )
{
struct in_addr wins_nmask = ipzero ;
wins_subnet = add_subnet_entry ( wins_ip , wins_nmask , group , create_subnets , False ) ;
}
1996-10-02 15:41:30 +00:00
1997-05-20 00:32:51 +00:00
/* Ensure we only create the subnets once. */
create_subnets = False ;
1996-07-07 13:29:56 +00:00
1997-05-20 00:32:51 +00:00
/* Now we have created all the subnets - we can add the names
that make us a client member in the workgroup .
*/
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
add_workgroup_to_subnet ( d , group ) ;
}
1996-07-07 13:29:56 +00:00
/*******************************************************************
write out browse . dat
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-07 01:56:21 +00:00
void write_browse_list ( time_t t )
1996-07-07 13:29:56 +00:00
{
struct subnet_record * d ;
pstring fname , fnamenew ;
FILE * f ;
1996-07-09 18:01:46 +00:00
static time_t lasttime = 0 ;
if ( ! lasttime ) lasttime = t ;
if ( ! updatedlists | | t - lasttime < 5 ) return ;
1996-07-07 13:29:56 +00:00
1996-07-09 18:01:46 +00:00
lasttime = t ;
updatedlists = False ;
updatecount + + ;
1996-07-07 13:29:56 +00:00
dump_names ( ) ;
dump_workgroups ( ) ;
strcpy ( fname , lp_lockdir ( ) ) ;
trim_string ( fname , NULL , " / " ) ;
strcat ( fname , " / " ) ;
strcat ( fname , SERVER_LIST ) ;
strcpy ( fnamenew , fname ) ;
strcat ( fnamenew , " . " ) ;
f = fopen ( fnamenew , " w " ) ;
if ( ! f )
{
DEBUG ( 4 , ( " Can't open %s - %s \n " , fnamenew , strerror ( errno ) ) ) ;
return ;
}
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
1996-07-07 13:29:56 +00:00
{
struct work_record * work ;
for ( work = d - > workgrouplist ; work ; work = work - > next )
1996-10-02 15:41:30 +00:00
{
struct server_record * s ;
for ( s = work - > serverlist ; s ; s = s - > next )
{
fstring tmp ;
/* don't list domains I don't have a master for */
if ( ( s - > serv . type & SV_TYPE_DOMAIN_ENUM ) & & ! s - > serv . comment [ 0 ] )
{
continue ;
}
/* output server details, plus what workgroup/domain
they ' re in . without the domain information , the
combined list of all servers in all workgroups gets
sent to anyone asking about any workgroup ! */
sprintf ( tmp , " \" %s \" " , s - > serv . name ) ;
fprintf ( f , " %-25s " , tmp ) ;
fprintf ( f , " %08x " , s - > serv . type ) ;
sprintf ( tmp , " \" %s \" " , s - > serv . comment ) ;
fprintf ( f , " %-30s " , tmp ) ;
fprintf ( f , " \" %s \" \n " , work - > work_group ) ;
}
}
1996-07-07 13:29:56 +00:00
}
fclose ( f ) ;
unlink ( fname ) ;
chmod ( fnamenew , 0644 ) ;
rename ( fnamenew , fname ) ;
DEBUG ( 3 , ( " Wrote browse list %s \n " , fname ) ) ;
}