1996-05-04 07:50:46 +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-05-04 07:50:46 +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 .
1996-07-07 12:36:18 +00:00
Module name : nameserv . c
1996-06-04 06:42:03 +00:00
Revision History :
14 jan 96 : lkcl @ pires . co . uk
added multiple workgroup domain master support
1996-07-07 12:36:18 +00:00
04 jul 96 : lkcl @ pires . co . uk
module nameserv contains name server management functions
1996-05-04 07:50:46 +00:00
*/
# include "includes.h"
1996-06-06 11:43:09 +00:00
extern int ClientNMB ;
1996-06-29 18:49:20 +00:00
1996-05-04 07:50:46 +00:00
extern int DEBUGLEVEL ;
extern pstring scope ;
1996-06-04 06:42:03 +00:00
extern pstring myname ;
1997-05-20 00:32:51 +00:00
extern fstring myworkgroup ;
1996-06-04 06:42:03 +00:00
extern struct in_addr ipzero ;
1997-04-09 01:19:25 +00:00
extern struct in_addr wins_ip ;
1996-05-04 07:50:46 +00:00
1996-06-29 18:49:20 +00:00
extern struct subnet_record * subnetlist ;
1996-08-01 17:49:40 +00:00
extern uint16 nb_type ; /* samba's NetBIOS type */
1996-05-04 07:50:46 +00:00
/****************************************************************************
1996-06-04 06:42:03 +00:00
remove an entry from the name list
1996-07-09 18:01:46 +00:00
1996-08-21 06:09:00 +00:00
note : the name will _always_ be removed
1996-07-09 18:01:46 +00:00
XXXX at present , the name is removed _even_ if a WINS server says keep it .
1996-05-04 07:50:46 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 15:41:30 +00:00
void remove_name_entry ( struct subnet_record * d , char * name , int type )
1996-05-04 07:50:46 +00:00
{
1996-07-01 18:29:21 +00:00
/* XXXX BUG: if samba is offering WINS support, it should still broadcast
a de - registration packet to the local subnet before removing the
name from its local - subnet name database . */
1996-07-09 18:01:46 +00:00
struct name_record n ;
struct name_record * n2 = NULL ;
make_nmb_name ( & n . name , name , type , scope ) ;
if ( ( n2 = find_name_search ( & d , & n . name , FIND_SELF , ipzero ) ) )
{
/* check name isn't already being de-registered */
1996-08-17 13:17:45 +00:00
if ( NAME_DEREG ( n2 - > ip_flgs [ 0 ] . nb_flags ) )
1996-07-09 18:01:46 +00:00
return ;
/* mark the name as in the process of deletion. */
1996-08-17 13:17:45 +00:00
n2 - > ip_flgs [ 0 ] . nb_flags & = NB_DEREG ;
1996-07-09 18:01:46 +00:00
}
1996-08-21 06:09:00 +00:00
if ( ! n2 ) return ;
/* remove the name immediately. even if the spec says we should
first try to release them , this is too dangerous with our current
name structures as otherwise we will end up replying to names we
don ' t really own */
remove_netbios_name ( d , name , type , SELF , n2 - > ip_flgs [ 0 ] . ip ) ;
1996-06-29 18:49:20 +00:00
1997-04-09 01:19:25 +00:00
if ( ip_equal ( d - > bcast_ip , wins_ip ) )
1997-03-12 20:21:11 +00:00
{
if ( ! lp_wins_support ( ) )
{
1996-10-02 15:41:30 +00:00
/* not a WINS server: we have to release them on the network */
1997-05-08 01:14:17 +00:00
queue_netbios_pkt_wins ( ClientNMB , NMB_REL , NAME_RELEASE ,
1996-10-02 15:41:30 +00:00
name , type , 0 , 0 , 0 , NULL , NULL ,
1996-08-21 06:09:00 +00:00
False , True , ipzero , ipzero ) ;
1996-10-02 15:41:30 +00:00
}
1997-03-12 20:21:11 +00:00
}
else
{
1996-08-21 06:09:00 +00:00
/* local interface: release them on the network */
queue_netbios_packet ( d , ClientNMB , NMB_REL , NAME_RELEASE ,
1996-10-02 15:41:30 +00:00
name , type , 0 , 0 , 0 , NULL , NULL ,
1996-08-21 06:09:00 +00:00
True , True , d - > bcast_ip , d - > bcast_ip ) ;
1996-07-09 18:01:46 +00:00
}
1996-05-04 07:50:46 +00:00
}
1996-06-04 06:42:03 +00:00
1996-05-04 07:50:46 +00:00
/****************************************************************************
1996-06-04 06:42:03 +00:00
add an entry to the name list
1996-07-09 18:01:46 +00:00
big note : our name will _always_ be added ( if there are no objections ) .
it ' s just a matter of when this will be done ( e . g after a time - out ) .
1996-05-04 07:50:46 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 15:41:30 +00:00
void add_my_name_entry ( struct subnet_record * d , char * name , int type , int nb_flags )
1996-05-04 07:50:46 +00:00
{
1996-06-29 18:49:20 +00:00
BOOL re_reg = False ;
struct nmb_name n ;
if ( ! d ) return ;
/* not that it particularly matters, but if the SELF name already exists,
it must be re - registered , rather than just registered */
make_nmb_name ( & n , name , type , scope ) ;
1996-07-17 18:33:36 +00:00
if ( find_name ( d - > namelist , & n , SELF ) )
1996-10-02 15:41:30 +00:00
re_reg = True ;
1996-06-29 18:49:20 +00:00
1996-07-01 18:29:21 +00:00
/* XXXX BUG: if samba is offering WINS support, it should still add the
name entry to a local - subnet name database . see rfc1001 . txt 15.1 .1 p28
regarding the point about M - nodes . */
1997-04-09 01:19:25 +00:00
if ( ip_equal ( d - > bcast_ip , wins_ip ) )
1996-07-01 18:29:21 +00:00
{
1996-07-09 18:01:46 +00:00
if ( lp_wins_support ( ) )
{
/* we are a WINS server. */
/* XXXX assume that if we are a WINS server that we are therefore
not pointing to another WINS server as well . this may later NOT
actually be true
*/
1996-07-17 18:33:36 +00:00
DEBUG ( 4 , ( " samba as WINS server adding: " ) ) ;
1996-07-10 18:48:49 +00:00
/* this will call add_netbios_entry() */
1996-10-02 15:41:30 +00:00
name_register_work ( d , name , type , nb_flags , 0 , ipzero , False ) ;
1996-07-09 18:01:46 +00:00
}
else
{
1997-05-20 00:32:51 +00:00
DEBUG ( 4 , ( " add_my_name_entry registering name %s with WINS server. \n " ,
name ) ) ;
1996-07-09 18:01:46 +00:00
/* a time-to-live allows us to refresh this name with the WINS server. */
1997-05-08 01:14:17 +00:00
queue_netbios_pkt_wins ( ClientNMB ,
1996-10-02 15:41:30 +00:00
re_reg ? NMB_REG_REFRESH : NMB_REG , NAME_REGISTER ,
name , type , nb_flags , GET_TTL ( 0 ) , 0 , NULL , NULL ,
False , True , ipzero , ipzero ) ;
1996-07-09 18:01:46 +00:00
}
}
else
{
1996-07-17 18:33:36 +00:00
/* broadcast the packet, but it comes from ipzero */
1996-10-02 15:41:30 +00:00
queue_netbios_packet ( d , ClientNMB ,
re_reg ? NMB_REG_REFRESH : NMB_REG , NAME_REGISTER ,
name , type , nb_flags , GET_TTL ( 0 ) , 0 , NULL , NULL ,
True , True , d - > bcast_ip , ipzero ) ;
1996-07-01 18:29:21 +00:00
}
1996-05-04 07:50:46 +00:00
}
1997-03-09 14:58:22 +00:00
/****************************************************************************
add the domain logon server and domain master browser names
this code was written so that several samba servers can co - operate in
sharing the task of ( one server ) being a domain master , and of being
domain logon servers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void add_domain_names ( time_t t )
{
static time_t lastrun = 0 ;
struct subnet_record * d ;
1997-05-08 01:14:17 +00:00
struct work_record * work ;
struct nmb_name n ;
1997-03-09 14:58:22 +00:00
if ( lastrun ! = 0 & & t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60 ) return ;
lastrun = t ;
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
1997-03-09 14:58:22 +00:00
{
1997-05-20 00:32:51 +00:00
work = find_workgroupstruct ( d , myworkgroup , False ) ;
1997-03-09 14:58:22 +00:00
if ( lp_domain_logons ( ) & & work & & work - > log_state = = LOGON_NONE )
{
1997-05-20 00:32:51 +00:00
make_nmb_name ( & n , myworkgroup , 0x1c , scope ) ;
1997-03-09 14:58:22 +00:00
if ( ! find_name ( d - > namelist , & n , FIND_SELF ) )
{
1997-03-12 20:21:11 +00:00
/* logon servers are group names - we don't expect this to fail. */
1997-03-09 14:58:22 +00:00
DEBUG ( 0 , ( " %s attempting to become logon server for %s %s \n " ,
1997-05-20 00:32:51 +00:00
timestring ( ) , myworkgroup , inet_ntoa ( d - > bcast_ip ) ) ) ;
1997-03-09 14:58:22 +00:00
become_logon_server ( d , work ) ;
}
}
1997-05-08 01:14:17 +00:00
}
1997-03-12 20:21:11 +00:00
1997-05-20 00:32:51 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
{
work = find_workgroupstruct ( d , myworkgroup , True ) ;
1997-04-09 01:19:25 +00:00
1997-05-20 00:32:51 +00:00
if ( lp_domain_master ( ) & & work & & work - > dom_state = = DOMAIN_NONE )
{
make_nmb_name ( & n , myworkgroup , 0x1b , scope ) ;
if ( ! find_name ( d - > namelist , & n , FIND_SELF ) )
1997-03-09 14:58:22 +00:00
{
1997-05-20 00:32:51 +00:00
DEBUG ( 0 , ( " %s add_domain_names: attempting to become domain master \
browser on workgroup % s % s \ n " ,
timestring ( ) , myworkgroup , inet_ntoa ( d - > bcast_ip ) ) ) ;
1997-04-09 01:19:25 +00:00
1997-05-08 01:14:17 +00:00
if ( lp_wins_support ( ) )
1997-03-12 20:21:11 +00:00
{
1997-05-08 01:14:17 +00:00
/* use the wins server's capabilities (indirectly). if
someone has already registered the domain < 1 b > name with
the WINS server , then the WINS server ' s job is to _check_
that the owner still wants it , before giving it away .
*/
1997-03-12 20:21:11 +00:00
1997-05-08 01:14:17 +00:00
DEBUG ( 1 , ( " %s initiating becoming domain master for %s \n " ,
1997-05-20 00:32:51 +00:00
timestring ( ) , myworkgroup ) ) ;
become_domain_master ( d , work ) ;
1997-03-12 20:21:11 +00:00
}
else
{
/* send out a query to establish whether there's a
1997-05-08 01:14:17 +00:00
domain controller on the WINS subnet . if not ,
we can become a domain controller .
1997-03-12 20:21:11 +00:00
it ' s only polite that we check , before claiming the
NetBIOS name 0x1b .
*/
1997-05-20 00:32:51 +00:00
DEBUG ( 0 , ( " add_domain_names:querying WINS for domain master \
on workgroup % s \ n " , myworkgroup));
1997-04-09 01:19:25 +00:00
1997-05-08 01:14:17 +00:00
queue_netbios_pkt_wins ( ClientNMB , NMB_QUERY , NAME_QUERY_DOMAIN ,
1997-05-20 00:32:51 +00:00
myworkgroup , 0x1b ,
1997-03-12 20:21:11 +00:00
0 , 0 , 0 , NULL , NULL ,
1997-05-08 01:14:17 +00:00
False , False , ipzero , ipzero ) ;
1997-03-12 20:21:11 +00:00
}
1997-03-09 14:58:22 +00:00
}
}
1997-05-20 00:32:51 +00:00
}
1997-03-09 14:58:22 +00:00
}
1996-05-04 07:50:46 +00:00
/****************************************************************************
add the magic samba names , useful for finding samba servers
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 06:42:03 +00:00
void add_my_names ( void )
1996-05-04 07:50:46 +00:00
{
1996-06-29 18:49:20 +00:00
struct subnet_record * d ;
1996-07-01 18:29:21 +00:00
/* each subnet entry, including WINS pseudo-subnet, has SELF names */
/* XXXX if there was a transport layer added to samba (ipx/spx etc) then
there would be yet _another_ for - loop , this time on the transport type
*/
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
1996-06-29 18:49:20 +00:00
{
1997-05-08 01:14:17 +00:00
BOOL wins = ( lp_wins_support ( ) & & ( d = = wins_subnet ) ) ;
1996-06-07 03:34:22 +00:00
1996-10-02 15:41:30 +00:00
add_my_name_entry ( d , myname , 0x20 , nb_type | NB_ACTIVE ) ;
add_my_name_entry ( d , myname , 0x03 , nb_type | NB_ACTIVE ) ;
add_my_name_entry ( d , myname , 0x00 , nb_type | NB_ACTIVE ) ;
add_my_name_entry ( d , myname , 0x1f , nb_type | NB_ACTIVE ) ;
1996-07-04 19:19:26 +00:00
/* these names are added permanently (ttl of zero) and will NOT be
refreshed with the WINS server */
1996-08-21 08:30:29 +00:00
add_netbios_entry ( d , " * " , 0x0 , nb_type | NB_ACTIVE , 0 , SELF , d - > myip , False , wins ) ;
1996-10-02 15:41:30 +00:00
add_netbios_entry ( d , " * " , 0x20 , nb_type | NB_ACTIVE , 0 , SELF , d - > myip , False , wins ) ;
1996-08-21 08:30:29 +00:00
add_netbios_entry ( d , " __SAMBA__ " , 0x20 , nb_type | NB_ACTIVE , 0 , SELF , d - > myip , False , wins ) ;
add_netbios_entry ( d , " __SAMBA__ " , 0x00 , nb_type | NB_ACTIVE , 0 , SELF , d - > myip , False , wins ) ;
1996-07-17 18:33:36 +00:00
}
1996-05-04 07:50:46 +00:00
}
1996-06-29 18:49:20 +00:00
1996-05-04 07:50:46 +00:00
1996-06-08 05:37:33 +00:00
/****************************************************************************
remove all the samba names . . . from a WINS server if necessary .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void remove_my_names ( )
{
1996-10-02 15:41:30 +00:00
struct subnet_record * d ;
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
1996-10-02 15:41:30 +00:00
{
struct name_record * n , * next ;
for ( n = d - > namelist ; n ; n = next )
{
next = n - > next ;
if ( n - > source = = SELF )
{
/* get all SELF names removed from the WINS server's database */
/* XXXX note: problem occurs if this removes the wrong one! */
remove_name_entry ( d , n - > name . name , n - > name . name_type ) ;
}
}
}
}
/*******************************************************************
refresh my own names
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void refresh_my_names ( time_t t )
{
struct subnet_record * d ;
1996-06-04 06:42:03 +00:00
1997-05-08 01:14:17 +00:00
for ( d = FIRST_SUBNET ; d ; d = NEXT_SUBNET_INCLUDING_WINS ( d ) )
1996-10-02 15:41:30 +00:00
{
struct name_record * n ;
for ( n = d - > namelist ; n ; n = n - > next )
1996-07-01 18:29:21 +00:00
{
1996-10-02 15:41:30 +00:00
/* each SELF name has an individual time to be refreshed */
1996-10-07 01:56:21 +00:00
if ( n - > source = = SELF & & n - > refresh_time < t & &
1996-10-02 15:41:30 +00:00
n - > death_time ! = 0 )
{
add_my_name_entry ( d , n - > name . name , n - > name . name_type ,
n - > ip_flgs [ 0 ] . nb_flags ) ;
/* they get a new lease on life :-) */
n - > death_time + = GET_TTL ( 0 ) ;
n - > refresh_time + = GET_TTL ( 0 ) ;
}
1996-07-01 18:29:21 +00:00
}
1996-10-02 15:41:30 +00:00
}
1996-06-04 15:14:47 +00:00
}
1996-06-04 06:42:03 +00:00
1996-07-07 12:36:18 +00:00
1996-06-29 18:49:20 +00:00
/*******************************************************************
queries names occasionally . an over - cautious , non - trusting WINS server !
1996-07-01 18:29:21 +00:00
this function has been added because nmbd could be restarted . it
is generally a good idea to check all the names that have been
reloaded from file .
XXXX which names to poll and which not can be refined at a later date .
1996-06-29 18:49:20 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-07 01:56:21 +00:00
void query_refresh_names ( time_t t )
1996-06-29 18:49:20 +00:00
{
1996-10-02 15:41:30 +00:00
struct name_record * n ;
1997-05-08 01:14:17 +00:00
struct subnet_record * d = wins_subnet ;
1996-06-29 18:49:20 +00:00
1996-10-02 15:41:30 +00:00
static time_t lasttime = 0 ;
1996-06-29 18:49:20 +00:00
1996-10-02 15:41:30 +00:00
int count = 0 ;
int name_refresh_time = NAME_POLL_REFRESH_TIME ;
int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL ;
if ( max_count > 10 ) max_count = 10 ;
1996-06-29 18:49:20 +00:00
1996-10-02 15:41:30 +00:00
name_refresh_time = NAME_POLL_INTERVAL * max_count / 2 ;
1996-06-29 18:49:20 +00:00
1996-10-02 15:41:30 +00:00
/* if (!lp_poll_wins()) return; polling of registered names allowed */
1996-06-29 18:49:20 +00:00
1996-10-02 15:41:30 +00:00
if ( ! d ) return ;
1996-06-29 18:49:20 +00:00
1996-07-09 18:01:46 +00:00
if ( ! lasttime ) lasttime = t ;
1996-10-02 15:41:30 +00:00
if ( t - lasttime < NAME_POLL_INTERVAL ) return ;
1996-06-29 18:49:20 +00:00
1996-07-09 18:01:46 +00:00
lasttime = time ( NULL ) ;
1996-10-02 15:41:30 +00:00
for ( n = d - > namelist ; n ; n = n - > next )
{
/* only do unique, registered names */
if ( n - > source ! = REGISTER ) continue ;
if ( ! NAME_GROUP ( n - > ip_flgs [ 0 ] . nb_flags ) ) continue ;
if ( n - > refresh_time < t )
{
DEBUG ( 3 , ( " Polling name %s \n " , namestr ( & n - > name ) ) ) ;
queue_netbios_packet ( d , ClientNMB , NMB_QUERY , NAME_QUERY_CONFIRM ,
n - > name . name , n - > name . name_type ,
0 , 0 , 0 , NULL , NULL ,
False , False , n - > ip_flgs [ 0 ] . ip , n - > ip_flgs [ 0 ] . ip ) ;
count + + ;
}
if ( count > = max_count )
{
/* don't do too many of these at once, but do enough to
cover everyone in the list */
return ;
}
/* this name will be checked on again, if it's not removed */
n - > refresh_time + = name_refresh_time ;
}
1996-06-29 18:49:20 +00:00
}
1996-07-09 18:01:46 +00:00