1996-07-07 17:29:56 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
NBT netbios routines and daemon - version 2
1997-05-08 05:14:17 +04:00
Copyright ( C ) Andrew Tridgell 1994 - 1997
1996-07-07 17:29:56 +04: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 :
Module name : nameservresp . c
14 jan 96 : lkcl @ pires . co . uk
added multiple workgroup domain master support
05 jul 96 : lkcl @ pires . co . uk
created module nameservresp containing NetBIOS response functions
*/
# include "includes.h"
extern int ClientNMB ;
extern int DEBUGLEVEL ;
extern pstring scope ;
1997-05-31 00:40:48 +04:00
extern fstring myworkgroup ;
1996-07-07 17:29:56 +04:00
extern struct in_addr ipzero ;
1997-05-31 00:40:48 +04:00
extern struct in_addr wins_ip ;
extern struct in_addr ipzero ;
1996-07-07 17:29:56 +04:00
# define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
/****************************************************************************
response for a reg release received . samba has asked a WINS server if it
could release a name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-27 17:22:56 +03:00
static void response_name_release ( struct nmb_name * ans_name ,
struct subnet_record * d , struct packet_struct * p )
1996-07-07 17:29:56 +04:00
{
1996-10-02 19:41:30 +04:00
struct nmb_packet * nmb = & p - > packet . nmb ;
1996-10-27 17:22:56 +03:00
char * name = ans_name - > name ;
int type = ans_name - > name_type ;
1996-10-02 19:41:30 +04:00
1996-07-07 17:29:56 +04:00
DEBUG ( 4 , ( " response name release received \n " ) ) ;
1996-10-02 19:41:30 +04:00
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
1996-07-10 22:48:49 +04:00
{
/* IMPORTANT: see expire_netbios_response_entries() */
1996-07-07 17:29:56 +04:00
1996-10-02 19:41:30 +04:00
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
1996-07-10 22:48:49 +04:00
/* NOTE: we only release our own names at present */
1996-10-02 19:41:30 +04:00
if ( ismyip ( found_ip ) )
1996-07-10 22:48:49 +04:00
{
1996-10-02 19:41:30 +04:00
name_unregister_work ( d , name , type ) ;
1996-07-07 17:29:56 +04:00
}
1996-07-10 22:48:49 +04:00
else
1996-07-07 17:29:56 +04:00
{
1996-07-10 22:48:49 +04:00
DEBUG ( 2 , ( " name release for different ip! %s %s \n " ,
1996-10-27 17:22:56 +03:00
inet_ntoa ( found_ip ) , namestr ( ans_name ) ) ) ;
1996-07-10 22:48:49 +04:00
}
}
else
{
1996-10-27 17:22:56 +03:00
DEBUG ( 2 , ( " name release for %s rejected! \n " , namestr ( ans_name ) ) ) ;
1996-07-07 17:29:56 +04:00
1996-07-10 22:48:49 +04:00
/* XXXX PANIC! what to do if it's one of samba's own names? */
/* XXXX do we honestly care if our name release was rejected?
only if samba is issuing the release on behalf of some out - of - sync
server . if it ' s one of samba ' s SELF names , we don ' t care . */
}
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
response for a reg request received
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-27 17:22:56 +03:00
static void response_name_reg ( struct nmb_name * ans_name ,
struct subnet_record * d , struct packet_struct * p )
1996-07-07 17:29:56 +04:00
{
1996-10-02 19:41:30 +04:00
struct nmb_packet * nmb = & p - > packet . nmb ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
1996-10-27 17:22:56 +03:00
char * name = ans_name - > name ;
int type = ans_name - > name_type ;
1996-10-02 19:41:30 +04:00
1996-07-07 17:29:56 +04:00
DEBUG ( 4 , ( " response name registration received! \n " ) ) ;
1997-05-31 00:40:48 +04:00
# if 1
/* This code is neccesitated due to bugs in earlier versions of
Samba ( up to 1.9 .16 p11 ) . They respond to a broadcast
name registration of WORKGROUP < 1 b > when they should
not . Hence , until these versions are gone , we should
treat such errors as success for this particular
case only . jallison @ whistle . com .
*/
if ( ( ( d ! = wins_subnet ) & & ( nmb - > header . rcode = = 6 ) & & strequal ( myworkgroup , name ) & &
( type = = 0x1b ) ) | |
( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata ) )
# else
1996-10-02 19:41:30 +04:00
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
1997-05-31 00:40:48 +04:00
# endif
1996-07-07 17:29:56 +04:00
{
1996-07-10 22:48:49 +04:00
/* IMPORTANT: see expire_netbios_response_entries() */
1996-07-07 17:29:56 +04:00
1996-10-02 19:41:30 +04:00
int nb_flags = nmb - > answers - > rdata [ 0 ] ;
int ttl = nmb - > answers - > ttl ;
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
name_register_work ( d , name , type , nb_flags , ttl , found_ip , bcast ) ;
1996-07-07 17:29:56 +04:00
}
else
{
1997-05-16 03:47:34 +04:00
DEBUG ( 2 , ( " name registration for %s rejected by ip %s! \n " ,
namestr ( ans_name ) , inet_ntoa ( p - > ip ) ) ) ;
1996-07-07 17:29:56 +04:00
1996-10-02 19:41:30 +04:00
/* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work ( d , name , type ) ;
1996-07-07 17:29:56 +04:00
}
}
/****************************************************************************
1996-08-01 21:49:40 +04:00
response from a name query announce host
NAME_QUERY_ANNOUNCE_HOST is dealt with here
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 19:41:30 +04:00
static void response_announce_host ( struct nmb_name * ans_name ,
struct nmb_packet * nmb ,
struct response_record * n , struct subnet_record * d )
1996-08-01 21:49:40 +04:00
{
1996-10-02 19:41:30 +04:00
DEBUG ( 4 , ( " Name query at %s ip %s - " ,
namestr ( & n - > name ) , inet_ntoa ( n - > send_ip ) ) ) ;
if ( ! name_equal ( & n - > name , ans_name ) )
{
/* someone gave us the wrong name as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG ( 4 , ( " unexpected name received: %s \n " , namestr ( ans_name ) ) ) ;
return ;
}
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
{
/* we had sent out a name query to the current owner
of a name because someone else wanted it . now they
have responded saying that they still want the name ,
so the other host can ' t have it .
*/
/* first check all the details are correct */
int nb_flags = nmb - > answers - > rdata [ 0 ] ;
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
if ( nb_flags ! = n - > nb_flags )
{
/* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG ( 4 , ( " expected nb_flags: %d \n " , n - > nb_flags ) ) ;
DEBUG ( 4 , ( " unexpected nb_flags: %d \n " , nb_flags ) ) ;
return ;
}
/* do an announce host */
do_announce_host ( ANN_HostAnnouncement ,
n - > my_name , 0x00 , d - > myip ,
n - > name . name , 0x1d , found_ip ,
n - > ttl ,
n - > my_name , n - > server_type , n - > my_comment ) ;
}
else
{
/* XXXX negative name query response. no master exists. oops */
}
1996-08-01 21:49:40 +04:00
}
/****************************************************************************
response from a name query server check . states of type NAME_QUERY_DOM_SRV_CHK ,
1996-07-07 17:29:56 +04:00
NAME_QUERY_SRV_CHK , and NAME_QUERY_FIND_MST dealt with here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void response_server_check ( struct nmb_name * ans_name ,
1996-10-02 19:41:30 +04:00
struct response_record * n , struct subnet_record * d )
1996-07-07 17:29:56 +04:00
{
/* issue another state: this time to do a name status check */
1996-08-01 21:49:40 +04:00
enum state_type cmd = ( n - > state = = NAME_QUERY_DOM_SRV_CHK ) ?
1996-10-02 19:41:30 +04:00
NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK ;
1996-07-07 17:29:56 +04:00
1997-04-09 05:19:25 +04:00
/* initiate a name status check on the server that replied
in addition , the workgroup being checked has been stored
in the response_record - > my_name ( see announce_master ) we
also propagate this into the same field . */
1996-07-07 17:29:56 +04:00
queue_netbios_packet ( d , ClientNMB , NMB_STATUS , cmd ,
1996-10-02 19:41:30 +04:00
ans_name - > name , ans_name - > name_type ,
1997-04-09 05:19:25 +04:00
0 , 0 , 0 , n - > my_name , NULL ,
1996-10-02 19:41:30 +04:00
False , False , n - > send_ip , n - > reply_to_ip ) ;
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
interpret a node status response . this is pretty hacked : we need two bits of
info . a ) the name of the workgroup b ) the name of the server . it will also
add all the names it finds into the namelist .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL interpret_node_status ( struct subnet_record * d ,
1996-10-02 19:41:30 +04:00
char * p , struct nmb_name * name , int t ,
char * serv_name , struct in_addr ip , BOOL bcast )
1996-07-07 17:29:56 +04:00
{
int numnames = CVAL ( p , 0 ) ;
BOOL found = False ;
1996-10-11 09:49:42 +04:00
DEBUG ( 4 , ( " received %d names \n " , numnames ) ) ;
1996-07-07 17:29:56 +04:00
p + = 1 ;
if ( serv_name ) * serv_name = 0 ;
while ( numnames - - )
{
char qname [ 17 ] ;
int type ;
fstring flags ;
int nb_flags ;
BOOL group = False ;
BOOL add = False ;
* flags = 0 ;
StrnCpy ( qname , p , 15 ) ;
type = CVAL ( p , 15 ) ;
nb_flags = p [ 16 ] ;
trim_string ( qname , NULL , " " ) ;
p + = 18 ;
if ( NAME_GROUP ( nb_flags ) ) { strcat ( flags , " <GROUP> " ) ; group = True ; }
if ( NAME_BFLAG ( nb_flags ) ) { strcat ( flags , " B " ) ; }
if ( NAME_PFLAG ( nb_flags ) ) { strcat ( flags , " P " ) ; }
if ( NAME_MFLAG ( nb_flags ) ) { strcat ( flags , " M " ) ; }
1996-08-01 21:49:40 +04:00
if ( NAME_HFLAG ( nb_flags ) ) { strcat ( flags , " H " ) ; }
1996-07-07 17:29:56 +04:00
if ( NAME_DEREG ( nb_flags ) ) { strcat ( flags , " <DEREGISTERING> " ) ; }
1997-04-09 05:19:25 +04:00
if ( NAME_CONFLICT ( nb_flags ) ) { strcat ( flags , " <CONFLICT> " ) ; }
1996-07-07 17:29:56 +04:00
if ( NAME_ACTIVE ( nb_flags ) ) { strcat ( flags , " <ACTIVE> " ) ; add = True ; }
if ( NAME_PERMANENT ( nb_flags ) ) { strcat ( flags , " <PERMANENT> " ) ; add = True ; }
1997-04-09 05:19:25 +04:00
/* I don't think we should be messing with our namelist here... JRA */
#if 0
1996-07-07 17:29:56 +04:00
/* might as well update our namelist while we're at it */
if ( add )
1996-10-02 19:41:30 +04:00
{
struct in_addr nameip ;
enum name_source src ;
if ( ismyip ( ip ) ) {
nameip = ipzero ;
src = SELF ;
} else {
nameip = ip ;
src = STATUS_QUERY ;
}
add_netbios_entry ( d , qname , type , nb_flags , 2 * 60 * 60 , src , nameip , True , bcast ) ;
}
1997-04-09 05:19:25 +04:00
# endif /* JRA */
1996-07-07 17:29:56 +04:00
/* we want the server name */
1997-04-09 05:19:25 +04:00
if ( serv_name & & ! * serv_name & & ! group & & type = = 0x20 )
1996-10-02 19:41:30 +04:00
{
StrnCpy ( serv_name , qname , 15 ) ;
serv_name [ 15 ] = 0 ;
}
1996-07-07 17:29:56 +04:00
/* looking for a name and type? */
if ( name & & ! found & & ( t = = type ) )
1996-10-02 19:41:30 +04:00
{
/* take a guess at some of the name types we're going to ask for.
evaluate whether they are group names or no . . . */
1997-04-09 05:19:25 +04:00
if ( ( ( t = = 0x1b | | t = = 0x1d | | t = = 0x20 ) & & ! group ) | |
( ( t = = 0x1c | | t = = 0x1e ) & & group ) )
1996-10-02 19:41:30 +04:00
{
found = True ;
make_nmb_name ( name , qname , type , scope ) ;
}
}
1996-07-07 17:29:56 +04:00
1996-10-11 09:49:42 +04:00
DEBUG ( 4 , ( " \t %s(0x%x) \t %s \n " , qname , type , flags ) ) ;
1996-07-07 17:29:56 +04:00
}
1996-10-11 09:49:42 +04:00
DEBUG ( 4 , ( " num_good_sends=%d num_good_receives=%d \n " ,
1996-10-02 19:41:30 +04:00
IVAL ( p , 20 ) , IVAL ( p , 24 ) ) ) ;
1996-07-07 17:29:56 +04:00
return found ;
}
/****************************************************************************
1996-08-01 21:49:40 +04:00
response from a name status check . states of type NAME_STATUS_DOM_SRV_CHK
1996-07-07 17:29:56 +04:00
and NAME_STATUS_SRV_CHK dealt with here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void response_name_status_check ( struct in_addr ip ,
1996-10-02 19:41:30 +04:00
struct nmb_packet * nmb , BOOL bcast ,
struct response_record * n , struct subnet_record * d )
1996-07-07 17:29:56 +04:00
{
1996-10-02 19:41:30 +04:00
/* NMB_STATUS arrives: contains workgroup name and server name required.
1996-07-07 17:29:56 +04:00
amongst other things . */
1996-10-02 19:41:30 +04:00
struct nmb_name name ;
fstring serv_name ;
if ( interpret_node_status ( d , nmb - > answers - > rdata ,
1997-04-09 05:19:25 +04:00
& name , 0x20 , serv_name , ip , bcast ) )
1996-10-02 19:41:30 +04:00
{
if ( * serv_name )
{
1997-04-09 05:19:25 +04:00
/* response_record->my_name contains the
workgroup name to sync with . See
response_server_check ( ) */
1996-10-02 19:41:30 +04:00
sync_server ( n - > state , serv_name ,
1997-05-08 05:14:17 +04:00
n - > my_name , name . name_type , d , n - > send_ip ) ;
1996-10-02 19:41:30 +04:00
}
}
else
{
1997-04-09 05:19:25 +04:00
DEBUG ( 1 , ( " No 0x20 name type in interpret_node_status() \n " ) ) ;
1996-10-02 19:41:30 +04:00
}
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
response from a name query for secured WINS registration . a state of
NAME_REGISTER_CHALLENGE is dealt with here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 19:41:30 +04:00
static void response_name_query_register ( struct nmb_packet * nmb ,
struct nmb_name * ans_name ,
struct response_record * n , struct subnet_record * d )
1996-07-07 17:29:56 +04:00
{
1996-10-02 19:41:30 +04:00
struct in_addr register_ip ;
BOOL new_owner ;
DEBUG ( 4 , ( " Name query at %s ip %s - " ,
namestr ( & n - > name ) , inet_ntoa ( n - > send_ip ) ) ) ;
if ( ! name_equal ( & n - > name , ans_name ) )
{
/* someone gave us the wrong name as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG ( 4 , ( " unexpected name received: %s \n " , namestr ( ans_name ) ) ) ;
return ;
}
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
{
/* we had sent out a name query to the current owner
of a name because someone else wanted it . now they
have responded saying that they still want the name ,
so the other host can ' t have it .
*/
/* first check all the details are correct */
int nb_flags = nmb - > answers - > rdata [ 0 ] ;
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
if ( nb_flags ! = n - > nb_flags )
{
/* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG ( 4 , ( " expected nb_flags: %d \n " , n - > nb_flags ) ) ;
DEBUG ( 4 , ( " unexpected nb_flags: %d \n " , nb_flags ) ) ;
return ;
}
if ( ! ip_equal ( n - > send_ip , found_ip ) )
{
/* someone gave us the wrong ip as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG ( 4 , ( " expected ip: %s \n " , inet_ntoa ( n - > send_ip ) ) ) ;
DEBUG ( 4 , ( " unexpected ip: %s \n " , inet_ntoa ( found_ip ) ) ) ;
return ;
}
DEBUG ( 4 , ( " OK: %s \n " , inet_ntoa ( found_ip ) ) ) ;
/* fine: now tell the other host they can't have the name */
register_ip = n - > send_ip ;
new_owner = False ;
}
else
{
DEBUG ( 4 , ( " NEGATIVE RESPONSE! \n " ) ) ;
/* the owner didn't want the name: the other host can have it */
register_ip = n - > reply_to_ip ;
new_owner = True ;
}
/* register the old or the new owners' ip */
add_name_respond ( d , n - > fd , d - > myip , n - > response_id , & n - > name , n - > nb_flags ,
GET_TTL ( 0 ) , register_ip ,
new_owner , n - > reply_to_ip ) ;
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
response from a name query to sync browse lists or to update our netbios
entry . states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 19:41:30 +04:00
static void response_name_query_sync ( struct nmb_packet * nmb ,
struct nmb_name * ans_name , BOOL bcast ,
struct response_record * n , struct subnet_record * d )
1996-07-07 17:29:56 +04:00
{
1997-04-09 05:19:25 +04:00
DEBUG ( 4 , ( " Name query at %s ip %s - " ,
namestr ( & n - > name ) , inet_ntoa ( n - > send_ip ) ) ) ;
1996-10-02 19:41:30 +04:00
1997-04-09 05:19:25 +04:00
if ( ! name_equal ( & n - > name , ans_name ) )
1996-10-02 19:41:30 +04:00
{
1997-04-09 05:19:25 +04:00
/* someone gave us the wrong name as a reply. oops. */
DEBUG ( 4 , ( " unexpected name received: %s \n " , namestr ( ans_name ) ) ) ;
return ;
}
1996-10-02 19:41:30 +04:00
1997-04-09 05:19:25 +04:00
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
{
int nb_flags = nmb - > answers - > rdata [ 0 ] ;
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
if ( ! ip_equal ( n - > send_ip , found_ip ) )
{
/* someone gave us the wrong ip as a reply. oops. */
DEBUG ( 4 , ( " expected ip: %s \n " , inet_ntoa ( n - > send_ip ) ) ) ;
DEBUG ( 4 , ( " unexpected ip: %s \n " , inet_ntoa ( found_ip ) ) ) ;
return ;
}
1996-10-02 19:41:30 +04:00
1997-04-09 05:19:25 +04:00
DEBUG ( 4 , ( " OK: %s \n " , inet_ntoa ( found_ip ) ) ) ;
if ( n - > state = = NAME_QUERY_SYNC_LOCAL | |
n - > state = = NAME_QUERY_SYNC_REMOTE )
{
struct work_record * work = NULL ;
/* We cheat here as we know that the workgroup name has
been placed in the my_comment field of the
response_record struct by the code in
start_sync_browse_entry ( ) .
*/
if ( ( work = find_workgroupstruct ( d , n - > my_comment , False ) ) )
{
BOOL local_list_only = n - > state = = NAME_QUERY_SYNC_LOCAL ;
/* the server is there: sync quick before it (possibly) dies! */
sync_browse_lists ( d , work , ans_name - > name , ans_name - > name_type ,
found_ip , local_list_only ) ;
}
1996-10-02 19:41:30 +04:00
}
1997-04-09 05:19:25 +04:00
else
1996-10-02 19:41:30 +04:00
{
1997-04-09 05:19:25 +04:00
/* update our netbios name list (re-register it if necessary) */
add_netbios_entry ( d , ans_name - > name , ans_name - > name_type ,
nb_flags , GET_TTL ( 0 ) , REGISTER ,
found_ip , False , ! bcast ) ;
}
}
else
{
DEBUG ( 4 , ( " NEGATIVE RESPONSE! \n " ) ) ;
if ( n - > state = = NAME_QUERY_CONFIRM )
{
/* XXXX remove_netbios_entry()? */
/* lots of things we ought to do, here. if we get here,
then we ' re in a mess : our name database doesn ' t match
reality . sort it out
1996-07-07 17:29:56 +04:00
*/
1997-04-09 05:19:25 +04:00
remove_netbios_name ( d , n - > name . name , n - > name . name_type ,
REGISTER , n - > send_ip ) ;
1996-10-02 19:41:30 +04:00
}
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
}
1997-05-31 00:40:48 +04:00
/****************************************************************************
response from a name query for DOMAIN < 1 b >
NAME_QUERY_DOMAIN is dealt with here - we are trying to become a domain
master browser and WINS replied - check it ' s our address .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void response_name_query_domain ( struct nmb_name * ans_name ,
struct nmb_packet * nmb ,
struct response_record * n , struct subnet_record * d )
{
DEBUG ( 4 , ( " response_name_query_domain: Got %s response from %s for query \
for % s \ n " , nmb->header.rcode == 0 ? " success " : " failure " ,
inet_ntoa ( n - > send_ip ) , namestr ( ans_name ) ) ) ;
/* Check the name is correct and ip address returned is our own. If it is then we
just remove the response record .
*/
if ( name_equal ( & n - > name , ans_name ) & & ( nmb - > header . rcode = = 0 ) & & ( nmb - > answers - > rdata ) )
{
struct in_addr found_ip ;
putip ( ( char * ) & found_ip , & nmb - > answers - > rdata [ 2 ] ) ;
/* Samba 1.9.16p11 servers seem to return the broadcast address for this
query . */
if ( ismyip ( found_ip ) | | ip_equal ( wins_ip , found_ip ) | | ip_equal ( ipzero , found_ip ) )
{
DEBUG ( 4 , ( " response_name_query_domain: WINS server returned our ip \
address . Pretending we never received response . \ n " ));
n - > num_msgs = 0 ;
n - > repeat_count = 0 ;
n - > repeat_time = 0 ;
}
else
{
DEBUG ( 0 , ( " response_name_query_domain: WINS server already has a \
domain master browser registered % s at address % s \ n " ,
namestr ( ans_name ) , inet_ntoa ( found_ip ) ) ) ;
}
}
else
{
/* Negative/incorrect response. No domain master
browser was registered - pretend we didn ' t get this response .
*/
n - > num_msgs = 0 ;
n - > repeat_count = 0 ;
n - > repeat_time = 0 ;
}
}
1996-07-07 17:29:56 +04:00
/****************************************************************************
report the response record type
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void debug_rr_type ( int rr_type )
{
switch ( rr_type )
1997-04-09 05:19:25 +04:00
{
case NMB_STATUS : DEBUG ( 3 , ( " Name status " ) ) ; break ;
case NMB_QUERY : DEBUG ( 3 , ( " Name query " ) ) ; break ;
case NMB_REG : DEBUG ( 3 , ( " Name registration " ) ) ; break ;
case NMB_REL : DEBUG ( 3 , ( " Name release " ) ) ; break ;
default : DEBUG ( 1 , ( " wrong response packet type received " ) ) ; break ;
}
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
report the response record nmbd state
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-07-17 22:33:36 +04:00
void debug_state_type ( int state )
1996-07-07 17:29:56 +04:00
{
/* report the state type to help debugging */
switch ( state )
1997-04-09 05:19:25 +04:00
{
case NAME_QUERY_DOM_SRV_CHK : DEBUG ( 4 , ( " NAME_QUERY_DOM_SRV_CHK \n " ) ) ; break ;
1996-08-01 21:49:40 +04:00
case NAME_QUERY_SRV_CHK : DEBUG ( 4 , ( " NAME_QUERY_SRV_CHK \n " ) ) ; break ;
case NAME_QUERY_FIND_MST : DEBUG ( 4 , ( " NAME_QUERY_FIND_MST \n " ) ) ; break ;
case NAME_QUERY_MST_CHK : DEBUG ( 4 , ( " NAME_QUERY_MST_CHK \n " ) ) ; break ;
case NAME_QUERY_CONFIRM : DEBUG ( 4 , ( " NAME_QUERY_CONFIRM \n " ) ) ; break ;
case NAME_QUERY_SYNC_LOCAL : DEBUG ( 4 , ( " NAME_QUERY_SYNC_LOCAL \n " ) ) ; break ;
case NAME_QUERY_SYNC_REMOTE : DEBUG ( 4 , ( " NAME_QUERY_SYNC_REMOTE \n " ) ) ; break ;
case NAME_QUERY_ANNOUNCE_HOST : DEBUG ( 4 , ( " NAME_QUERY_ANNCE_HOST \n " ) ) ; break ;
1997-05-31 00:40:48 +04:00
case NAME_QUERY_DOMAIN : DEBUG ( 4 , ( " NAME_QUERY_DOMAIN \n " ) ) ; break ;
1997-04-09 05:19:25 +04:00
1996-08-01 21:49:40 +04:00
case NAME_REGISTER : DEBUG ( 4 , ( " NAME_REGISTER \n " ) ) ; break ;
case NAME_REGISTER_CHALLENGE : DEBUG ( 4 , ( " NAME_REGISTER_CHALLENGE \n " ) ) ; break ;
1997-04-09 05:19:25 +04:00
1996-08-01 21:49:40 +04:00
case NAME_RELEASE : DEBUG ( 4 , ( " NAME_RELEASE \n " ) ) ; break ;
1997-04-09 05:19:25 +04:00
case NAME_STATUS_DOM_SRV_CHK : DEBUG ( 4 , ( " NAME_STATUS_DOM_SRV_CHK \n " ) ) ; break ;
1996-08-01 21:49:40 +04:00
case NAME_STATUS_SRV_CHK : DEBUG ( 4 , ( " NAME_STATUS_SRV_CHK \n " ) ) ; break ;
1997-04-09 05:19:25 +04:00
1996-07-07 17:29:56 +04:00
default : break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
}
/****************************************************************************
report any problems with the fact that a response has been received .
( responses for certain types of operations are only expected from one host )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL response_problem_check ( struct response_record * n ,
1996-10-27 17:22:56 +03:00
struct nmb_packet * nmb , char * ans_name )
1996-07-07 17:29:56 +04:00
{
switch ( nmb - > answers - > rr_type )
{
1997-04-09 05:19:25 +04:00
case NMB_REL :
{
1996-07-07 17:29:56 +04:00
if ( n - > num_msgs > 1 )
1997-04-09 05:19:25 +04:00
{
1996-07-07 17:29:56 +04:00
DEBUG ( 1 , ( " more than one release name response received! \n " ) ) ;
return True ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
case NMB_REG :
1997-04-09 05:19:25 +04:00
{
1996-07-07 17:29:56 +04:00
if ( n - > num_msgs > 1 )
1997-04-09 05:19:25 +04:00
{
1996-07-07 17:29:56 +04:00
DEBUG ( 1 , ( " more than one register name response received! \n " ) ) ;
return True ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
case NMB_QUERY :
1997-04-09 05:19:25 +04:00
{
if ( n - > num_msgs > 1 )
{
if ( nmb - > header . rcode = = 0 & & nmb - > answers - > rdata )
{
int nb_flags = nmb - > answers - > rdata [ 0 ] ;
if ( ( ! NAME_GROUP ( nb_flags ) ) )
1996-10-02 19:41:30 +04:00
{
1997-04-09 05:19:25 +04:00
/* oh dear. more than one person responded to a
unique name .
there is either a network problem , a
configuration problem
or a server is mis - behaving */
/* XXXX mark the name as in conflict, and then let the
person who just responded know that they
must also mark it
as in conflict , and therefore must NOT use it .
see rfc1001 . txt 15.1 .3 .5 */
/* this may cause problems for some
early versions of nmbd */
switch ( n - > state )
{
case NAME_QUERY_FIND_MST :
1996-10-02 19:41:30 +04:00
{
1997-05-31 00:40:48 +04:00
/* query for ^1^2__MSBROWSE__^2^1 expect
1997-04-09 05:19:25 +04:00
lots of responses */
return False ;
1996-10-02 19:41:30 +04:00
}
1997-04-09 05:19:25 +04:00
case NAME_QUERY_ANNOUNCE_HOST :
case NAME_QUERY_DOM_SRV_CHK :
case NAME_QUERY_SRV_CHK :
case NAME_QUERY_MST_CHK :
{
if ( ! strequal ( ans_name , n - > name . name ) )
{
/* one subnet, one master browser
per workgroup */
/* XXXX force an election? */
DEBUG ( 3 , ( " more than one master browser replied! \n " ) ) ;
return True ;
}
break ;
}
default : break ;
}
DEBUG ( 3 , ( " Unique Name conflict detected! \n " ) ) ;
return True ;
1996-10-02 19:41:30 +04:00
}
1997-04-09 05:19:25 +04:00
}
else
{
/* we have received a negative reply,
having already received
at least one response ( pos / neg ) .
something ' s really wrong ! */
DEBUG ( 3 , ( " wierd name query problem detected! \n " ) ) ;
return True ;
}
}
}
1996-07-07 17:29:56 +04:00
}
return False ;
}
1996-10-24 04:09:08 +04:00
#if 0
1996-07-07 17:29:56 +04:00
/****************************************************************************
check that the response received is compatible with the response record
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL response_compatible ( struct response_record * n ,
1996-10-02 19:41:30 +04:00
struct nmb_packet * nmb )
1996-07-07 17:29:56 +04:00
{
switch ( n - > state )
{
case NAME_RELEASE :
{
1996-10-23 22:38:05 +04:00
if ( nmb - > answers - > rr_type ! = 0x20 )
1996-10-02 19:41:30 +04:00
{
DEBUG ( 1 , ( " Name release reply has wrong answer rr_type \n " ) ) ;
return False ;
}
1996-07-07 17:29:56 +04:00
break ;
}
case NAME_REGISTER :
{
1996-10-23 22:38:05 +04:00
if ( nmb - > answers - > rr_type ! = 0x20 )
1996-10-02 19:41:30 +04:00
{
DEBUG ( 1 , ( " Name register reply has wrong answer rr_type \n " ) ) ;
return False ;
}
1996-07-07 17:29:56 +04:00
break ;
}
case NAME_REGISTER_CHALLENGE : /* this is a query: we then do a register */
case NAME_QUERY_CONFIRM :
1996-08-01 21:49:40 +04:00
case NAME_QUERY_ANNOUNCE_HOST :
case NAME_QUERY_SYNC_LOCAL :
case NAME_QUERY_SYNC_REMOTE :
case NAME_QUERY_DOM_SRV_CHK :
1996-07-07 17:29:56 +04:00
case NAME_QUERY_SRV_CHK :
case NAME_QUERY_FIND_MST :
case NAME_QUERY_MST_CHK :
{
1996-10-23 22:38:05 +04:00
if ( nmb - > answers - > rr_type ! = 0x20 )
1996-10-02 19:41:30 +04:00
{
DEBUG ( 1 , ( " Name query reply has wrong answer rr_type \n " ) ) ;
return False ;
}
break ;
1996-07-07 17:29:56 +04:00
}
1996-08-01 21:49:40 +04:00
case NAME_STATUS_DOM_SRV_CHK :
1996-07-07 17:29:56 +04:00
case NAME_STATUS_SRV_CHK :
{
1996-10-23 22:38:05 +04:00
if ( nmb - > answers - > rr_type ! = 0x21 )
1996-10-02 19:41:30 +04:00
{
DEBUG ( 1 , ( " Name status reply has wrong answer rr_type \n " ) ) ;
return False ;
}
break ;
1996-07-07 17:29:56 +04:00
}
default :
{
1996-10-02 19:41:30 +04:00
DEBUG ( 1 , ( " unknown state type received in response_netbios_packet \n " ) ) ;
return False ;
1996-07-07 17:29:56 +04:00
}
}
return True ;
}
1996-10-24 04:09:08 +04:00
# endif
1996-07-07 17:29:56 +04:00
/****************************************************************************
process the response packet received
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-10-02 19:41:30 +04:00
static void response_process ( struct subnet_record * d , struct packet_struct * p ,
1997-04-09 05:19:25 +04:00
struct response_record * n , struct nmb_packet * nmb ,
BOOL bcast , struct nmb_name * ans_name )
1996-07-07 17:29:56 +04:00
{
switch ( n - > state )
{
1997-04-09 05:19:25 +04:00
case NAME_RELEASE :
{
1996-10-27 17:22:56 +03:00
response_name_release ( ans_name , d , p ) ;
1996-07-07 17:29:56 +04:00
break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
case NAME_REGISTER :
1997-04-09 05:19:25 +04:00
{
1996-10-27 17:22:56 +03:00
response_name_reg ( ans_name , d , p ) ;
1996-07-07 17:29:56 +04:00
break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
case NAME_REGISTER_CHALLENGE :
1997-04-09 05:19:25 +04:00
{
1996-10-02 19:41:30 +04:00
response_name_query_register ( nmb , ans_name , n , d ) ;
1996-07-07 17:29:56 +04:00
break ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
1996-08-01 21:49:40 +04:00
case NAME_QUERY_DOM_SRV_CHK :
1996-07-07 17:29:56 +04:00
case NAME_QUERY_SRV_CHK :
case NAME_QUERY_FIND_MST :
1997-04-09 05:19:25 +04:00
{
response_server_check ( ans_name , n , d ) ;
break ;
}
1996-08-01 21:49:40 +04:00
case NAME_STATUS_DOM_SRV_CHK :
1996-07-07 17:29:56 +04:00
case NAME_STATUS_SRV_CHK :
1997-04-09 05:19:25 +04:00
{
response_name_status_check ( p - > ip , nmb , bcast , n , d ) ;
break ;
}
1996-08-01 21:49:40 +04:00
case NAME_QUERY_ANNOUNCE_HOST :
1997-04-09 05:19:25 +04:00
{
response_announce_host ( ans_name , nmb , n , d ) ;
break ;
}
1996-08-01 21:49:40 +04:00
1996-07-07 17:29:56 +04:00
case NAME_QUERY_CONFIRM :
1996-08-01 21:49:40 +04:00
case NAME_QUERY_SYNC_LOCAL :
case NAME_QUERY_SYNC_REMOTE :
1997-04-09 05:19:25 +04:00
{
response_name_query_sync ( nmb , ans_name , bcast , n , d ) ;
break ;
}
1996-07-07 17:29:56 +04:00
case NAME_QUERY_MST_CHK :
1997-04-09 05:19:25 +04:00
{
/* no action required here. it's when NO responses are received
that we need to do something . see expire_name_query_entries ( ) */
1996-10-02 19:41:30 +04:00
1997-04-09 05:19:25 +04:00
DEBUG ( 4 , ( " Master browser exists for %s at %s (just checking!) \n " ,
namestr ( & n - > name ) , inet_ntoa ( n - > send_ip ) ) ) ;
break ;
}
1997-05-31 00:40:48 +04:00
case NAME_QUERY_DOMAIN :
{
/* We were asking to be a domain master browser, and someone
replied . If it was the WINS server and the IP it is
returning is our own - then remove the record and pretend
we didn ' t get a response . Else we do nothing and let
dead_netbios_entry deal with it .
We can only become domain master browser
when no broadcast responses are received and WINS
either contains no entry for the DOMAIN < 1 b > name or
contains our IP address .
*/
response_name_query_domain ( ans_name , nmb , n , d ) ;
break ;
}
1996-07-07 17:29:56 +04:00
default :
1997-04-09 05:19:25 +04:00
{
DEBUG ( 1 , ( " unknown state type received in response_netbios_packet \n " ) ) ;
break ;
}
1996-07-07 17:29:56 +04:00
}
}
/****************************************************************************
response from a netbios packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void response_netbios_packet ( struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
struct nmb_name * ans_name = NULL ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
struct response_record * n ;
struct subnet_record * d = NULL ;
if ( ! ( n = find_response_record ( & d , nmb - > header . name_trn_id ) ) ) {
DEBUG ( 2 , ( " unknown netbios response (received late or from nmblookup?) \n " ) ) ;
return ;
}
if ( ! d )
1997-04-09 05:19:25 +04:00
{
DEBUG ( 2 , ( " response packet: subnet %s not known \n " , inet_ntoa ( p - > ip ) ) ) ;
return ;
}
1996-07-07 17:29:56 +04:00
1996-10-02 19:41:30 +04:00
/* args wrong way round: spotted by ccm@shentel.net */
1996-08-01 21:49:40 +04:00
if ( ! same_net ( d - > bcast_ip , p - > ip , d - > mask_ip ) ) /* copes with WINS 'subnet' */
1997-04-09 05:19:25 +04:00
{
DEBUG ( 2 , ( " response from %s. " , inet_ntoa ( p - > ip ) ) ) ;
DEBUG ( 2 , ( " expected on subnet %s. hmm. \n " , inet_ntoa ( d - > bcast_ip ) ) ) ;
}
1996-07-07 17:29:56 +04:00
if ( nmb - > answers = = NULL )
1997-04-09 05:19:25 +04:00
{
1996-07-07 17:29:56 +04:00
/* hm. the packet received was a response, but with no answer. wierd! */
DEBUG ( 2 , ( " NMB packet response from %s (bcast=%s) - UNKNOWN \n " ,
1996-10-02 19:41:30 +04:00
inet_ntoa ( p - > ip ) , BOOLSTR ( bcast ) ) ) ;
1996-07-07 17:29:56 +04:00
return ;
1997-04-09 05:19:25 +04:00
}
1996-07-07 17:29:56 +04:00
ans_name = & nmb - > answers - > rr_name ;
DEBUG ( 3 , ( " response for %s from %s (bcast=%s) \n " ,
1996-10-02 19:41:30 +04:00
namestr ( ans_name ) , inet_ntoa ( p - > ip ) , BOOLSTR ( bcast ) ) ) ;
1996-07-07 17:29:56 +04:00
debug_rr_type ( nmb - > answers - > rr_type ) ;
1997-04-09 05:19:25 +04:00
1996-07-07 17:29:56 +04:00
n - > num_msgs + + ; /* count number of responses received */
n - > repeat_count = 0 ; /* don't resend: see expire_netbios_packets() */
1997-04-09 05:19:25 +04:00
1996-07-07 17:29:56 +04:00
debug_state_type ( n - > state ) ;
1997-04-09 05:19:25 +04:00
1996-07-07 17:29:56 +04:00
/* problem checking: multiple responses etc */
1996-10-27 17:22:56 +03:00
if ( response_problem_check ( n , nmb , ans_name - > name ) )
1996-07-07 17:29:56 +04:00
return ;
1997-04-09 05:19:25 +04:00
1996-07-07 17:29:56 +04:00
/* now deal with the current state */
1996-10-02 19:41:30 +04:00
response_process ( d , p , n , nmb , bcast , ans_name ) ;
1996-07-07 17:29:56 +04:00
}