0001-01-01 02:30:17 +02:30
/*
0001-01-01 02:30:17 +02:30
Unix SMB / CIFS implementation .
0001-01-01 02:30:17 +02:30
NBT netbios routines and daemon - version 2
0001-01-01 02:30:17 +02:30
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1994 - 1998
Copyright ( C ) Jeremy Allison 1994 - 1998
0001-01-01 02:30:17 +02:30
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 .
This file contains all the code to process NetBIOS requests coming
in on port 137. It does not deal with the code needed to service
WINS server requests , but only broadcast and unicast requests .
*/
# include "includes.h"
0001-01-01 02:30:17 +02:30
extern fstring global_myworkgroup ;
0001-01-01 02:30:17 +02:30
/****************************************************************************
Send a name release response .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void send_name_release_response ( int rcode , struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
char rdata [ 6 ] ;
memcpy ( & rdata [ 0 ] , & nmb - > additional - > rdata [ 0 ] , 6 ) ;
reply_netbios_packet ( p , /* Packet to reply to. */
rcode , /* Result code. */
NMB_REL , /* nmbd type code. */
NMB_NAME_RELEASE_OPCODE , /* opcode. */
0 , /* ttl. */
rdata , /* data to send. */
6 ) ; /* data length. */
}
/****************************************************************************
Process a name release packet on a broadcast subnet .
Ignore it if it ' s not one of our names .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_name_release_request ( struct subnet_record * subrec ,
struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
struct in_addr owner_ip ;
struct nmb_name * question = & nmb - > question . question_name ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
uint16 nb_flags = get_nb_flags ( nmb - > additional - > rdata ) ;
BOOL group = ( nb_flags & NB_GROUP ) ? True : False ;
struct name_record * namerec ;
int rcode = 0 ;
putip ( ( char * ) & owner_ip , & nmb - > additional - > rdata [ 2 ] ) ;
if ( ! bcast )
{
/* We should only get broadcast name release packets here.
Anyone trying to release unicast should be going to a WINS
server . If the code gets here , then either we are not a wins
server and they sent it anyway , or we are a WINS server and
the request was malformed . Either way , log an error here .
and send an error reply back .
*/
DEBUG ( 0 , ( " process_name_release_request: unicast name release request \
received for name % s from IP % s on subnet % s . Error - should be sent to WINS server \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( question ) , inet_ntoa ( owner_ip ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
send_name_release_response ( FMT_ERR , p ) ;
return ;
}
DEBUG ( 3 , ( " process_name_release_request: Name release on name %s, \
subnet % s from owner IP % s \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( & nmb - > question . question_name ) ,
0001-01-01 02:30:17 +02:30
subrec - > subnet_name , inet_ntoa ( owner_ip ) ) ) ;
/* If someone is releasing a broadcast group name, just ignore it. */
if ( group & & ! ismyip ( owner_ip ) )
return ;
0001-01-01 02:30:17 +02:30
/*
* Code to work around a bug in FTP OnNet software NBT implementation .
* They do a broadcast name release for WORKGROUP < 0 > and WORKGROUP < 1 e >
* names and * don ' t set the group bit * ! ! ! ! !
*/
0001-01-01 02:30:17 +02:30
if ( ! group & & ! ismyip ( owner_ip ) & & strequal ( question - > name , global_myworkgroup ) & &
0001-01-01 02:30:17 +02:30
( ( question - > name_type = = 0x0 ) | | ( question - > name_type = = 0x1e ) ) )
{
DEBUG ( 6 , ( " process_name_release_request: FTP OnNet bug workaround. Ignoring \
group release name % s from IP % s on subnet % s with no group bit set . \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( question ) , inet_ntoa ( owner_ip ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
return ;
}
0001-01-01 02:30:17 +02:30
namerec = find_name_on_subnet ( subrec , & nmb - > question . question_name , FIND_ANY_NAME ) ;
/* We only care about someone trying to release one of our names. */
0001-01-01 02:30:17 +02:30
if ( namerec
& & ( ( namerec - > data . source = = SELF_NAME )
| | ( namerec - > data . source = = PERMANENT_NAME ) ) )
0001-01-01 02:30:17 +02:30
{
rcode = ACT_ERR ;
DEBUG ( 0 , ( " process_name_release_request: Attempt to release name %s from IP %s \
on subnet % s being rejected as it is one of our names . \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( & nmb - > question . question_name ) , inet_ntoa ( owner_ip ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
}
if ( rcode = = 0 )
return ;
/* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
send_name_release_response ( rcode , p ) ;
}
/****************************************************************************
Send a name registration response .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void send_name_registration_response ( int rcode , int ttl , struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
char rdata [ 6 ] ;
memcpy ( & rdata [ 0 ] , & nmb - > additional - > rdata [ 0 ] , 6 ) ;
reply_netbios_packet ( p , /* Packet to reply to. */
rcode , /* Result code. */
NMB_REG , /* nmbd type code. */
NMB_NAME_REG_OPCODE , /* opcode. */
ttl , /* ttl. */
rdata , /* data to send. */
6 ) ; /* data length. */
}
/****************************************************************************
Process a name refresh request on a broadcast subnet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_name_refresh_request ( struct subnet_record * subrec ,
struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
struct nmb_name * question = & nmb - > question . question_name ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
struct in_addr from_ip ;
putip ( ( char * ) & from_ip , & nmb - > additional - > rdata [ 2 ] ) ;
if ( ! bcast )
{
/* We should only get broadcast name refresh packets here.
Anyone trying to refresh unicast should be going to a WINS
server . If the code gets here , then either we are not a wins
server and they sent it anyway , or we are a WINS server and
the request was malformed . Either way , log an error here .
and send an error reply back .
*/
DEBUG ( 0 , ( " process_name_refresh_request: unicast name registration request \
0001-01-01 02:30:17 +02:30
received for name % s from IP % s on subnet % s . \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( question ) , inet_ntoa ( from_ip ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Error - should be sent to WINS server \n " ) ) ;
0001-01-01 02:30:17 +02:30
send_name_registration_response ( FMT_ERR , 0 , p ) ;
return ;
}
/* Just log a message. We really don't care about broadcast name
refreshes . */
DEBUG ( 3 , ( " process_name_refresh_request: Name refresh for name %s \
0001-01-01 02:30:17 +02:30
IP % s on subnet % s \ n " , nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
0001-01-01 02:30:17 +02:30
}
/****************************************************************************
Process a name registration request on a broadcast subnet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_name_registration_request ( struct subnet_record * subrec ,
struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
struct nmb_name * question = & nmb - > question . question_name ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
uint16 nb_flags = get_nb_flags ( nmb - > additional - > rdata ) ;
BOOL group = ( nb_flags & NB_GROUP ) ? True : False ;
struct name_record * namerec = NULL ;
int ttl = nmb - > additional - > ttl ;
struct in_addr from_ip ;
putip ( ( char * ) & from_ip , & nmb - > additional - > rdata [ 2 ] ) ;
if ( ! bcast )
{
/* We should only get broadcast name registration packets here.
Anyone trying to register unicast should be going to a WINS
server . If the code gets here , then either we are not a wins
server and they sent it anyway , or we are a WINS server and
the request was malformed . Either way , log an error here .
and send an error reply back .
*/
DEBUG ( 0 , ( " process_name_registration_request: unicast name registration request \
received for name % s from IP % s on subnet % s . Error - should be sent to WINS server \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( question ) , inet_ntoa ( from_ip ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
send_name_registration_response ( FMT_ERR , 0 , p ) ;
return ;
}
DEBUG ( 3 , ( " process_name_registration_request: Name registration for name %s \
0001-01-01 02:30:17 +02:30
IP % s on subnet % s \ n " , nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
0001-01-01 02:30:17 +02:30
/* See if the name already exists. */
namerec = find_name_on_subnet ( subrec , question , FIND_ANY_NAME ) ;
0001-01-01 02:30:17 +02:30
/*
* If the name being registered exists and is a WINS_PROXY_NAME
* then delete the WINS proxy name entry so we don ' t reply erroneously
* later to queries .
*/
0001-01-01 02:30:17 +02:30
if ( ( namerec ! = NULL ) & & ( namerec - > data . source = = WINS_PROXY_NAME ) )
0001-01-01 02:30:17 +02:30
{
remove_name_from_namelist ( subrec , namerec ) ;
namerec = NULL ;
}
0001-01-01 02:30:17 +02:30
if ( ! group )
{
/* Unique name. */
0001-01-01 02:30:17 +02:30
if ( ( namerec ! = NULL )
& & ( ( namerec - > data . source = = SELF_NAME )
| | ( namerec - > data . source = = PERMANENT_NAME )
| | NAME_GROUP ( namerec ) ) )
0001-01-01 02:30:17 +02:30
{
/* No-one can register one of Samba's names, nor can they
register a name that ' s a group name as a unique name */
send_name_registration_response ( ACT_ERR , 0 , p ) ;
return ;
}
else if ( namerec ! = NULL )
{
/* Update the namelist record with the new information. */
0001-01-01 02:30:17 +02:30
namerec - > data . ip [ 0 ] = from_ip ;
0001-01-01 02:30:17 +02:30
update_name_ttl ( namerec , ttl ) ;
DEBUG ( 3 , ( " process_name_registration_request: Updated name record %s \
0001-01-01 02:30:17 +02:30
with IP % s on subnet % s \ n " ,nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
0001-01-01 02:30:17 +02:30
return ;
}
}
else
{
/* Group name. */
0001-01-01 02:30:17 +02:30
if ( ( namerec ! = NULL )
& & ! NAME_GROUP ( namerec )
& & ( ( namerec - > data . source = = SELF_NAME )
| | ( namerec - > data . source = = PERMANENT_NAME ) ) )
0001-01-01 02:30:17 +02:30
{
/* Disallow group names when we have a unique name. */
send_name_registration_response ( ACT_ERR , 0 , p ) ;
return ;
}
}
}
/****************************************************************************
This is used to sort names for a name status into a sensible order .
We put our own names first , then in alphabetical order .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int status_compare ( char * n1 , char * n2 )
{
0001-01-01 02:30:17 +02:30
extern pstring global_myname ;
0001-01-01 02:30:17 +02:30
int l1 , l2 , l3 ;
/* It's a bit tricky because the names are space padded */
for ( l1 = 0 ; l1 < 15 & & n1 [ l1 ] & & n1 [ l1 ] ! = ' ' ; l1 + + ) ;
for ( l2 = 0 ; l2 < 15 & & n2 [ l2 ] & & n2 [ l2 ] ! = ' ' ; l2 + + ) ;
0001-01-01 02:30:17 +02:30
l3 = strlen ( global_myname ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( ( l1 = = l3 ) & & strncmp ( n1 , global_myname , l3 ) = = 0 & &
( l2 ! = l3 | | strncmp ( n2 , global_myname , l3 ) ! = 0 ) )
0001-01-01 02:30:17 +02:30
return - 1 ;
0001-01-01 02:30:17 +02:30
if ( ( l2 = = l3 ) & & strncmp ( n2 , global_myname , l3 ) = = 0 & &
( l1 ! = l3 | | strncmp ( n1 , global_myname , l3 ) ! = 0 ) )
0001-01-01 02:30:17 +02:30
return 1 ;
return memcmp ( n1 , n2 , 18 ) ;
}
/****************************************************************************
Process a node status query
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_node_status_request ( struct subnet_record * subrec , struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
char * qname = nmb - > question . question_name . name ;
int ques_type = nmb - > question . question_name . name_type ;
char rdata [ MAX_DGRAM_SIZE ] ;
char * countptr , * buf , * bufend , * buf0 ;
int names_added , i ;
struct name_record * namerec ;
DEBUG ( 3 , ( " process_node_status_request: status request for name %s from IP %s on \
0001-01-01 02:30:17 +02:30
subnet % s . \ n " , nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
0001-01-01 02:30:17 +02:30
subrec - > subnet_name ) ) ;
if ( ( namerec = find_name_on_subnet ( subrec , & nmb - > question . question_name ,
FIND_SELF_NAME ) ) = = 0 )
{
DEBUG ( 1 , ( " process_node_status_request: status request for name %s from IP %s on \
0001-01-01 02:30:17 +02:30
subnet % s - name not found . \ n " , nmb_namestr(&nmb->question.question_name),
0001-01-01 02:30:17 +02:30
inet_ntoa ( p - > ip ) , subrec - > subnet_name ) ) ;
return ;
}
0001-01-01 02:30:17 +02:30
/* this is not an exact calculation. the 46 is for the stats buffer
and the 60 is to leave room for the header etc */
bufend = & rdata [ MAX_DGRAM_SIZE ] - ( 18 + 46 + 60 ) ;
0001-01-01 02:30:17 +02:30
countptr = buf = rdata ;
buf + = 1 ;
buf0 = buf ;
names_added = 0 ;
0001-01-01 02:30:17 +02:30
namerec = ( struct name_record * ) ubi_trFirst ( subrec - > namelist ) ;
0001-01-01 02:30:17 +02:30
while ( buf < bufend )
{
0001-01-01 02:30:17 +02:30
if ( ( namerec - > data . source = = SELF_NAME )
| | ( namerec - > data . source = = PERMANENT_NAME ) )
0001-01-01 02:30:17 +02:30
{
int name_type = namerec - > name . name_type ;
if ( ! strequal ( namerec - > name . name , " * " ) & &
! strequal ( namerec - > name . name , " __SAMBA__ " ) & &
( name_type < 0x1b | | name_type > = 0x20 | |
ques_type < 0x1b | | ques_type > = 0x20 | |
strequal ( qname , namerec - > name . name ) ) )
{
/* Start with the name. */
0001-01-01 02:30:17 +02:30
memset ( buf , ' \0 ' , 18 ) ;
0001-01-01 02:30:17 +02:30
slprintf ( buf , 17 , " %-15.15s " , namerec - > name . name ) ;
0001-01-01 02:30:17 +02:30
strupper ( buf ) ;
/* Put the name type and netbios flags in the buffer. */
buf [ 15 ] = name_type ;
0001-01-01 02:30:17 +02:30
set_nb_flags ( & buf [ 16 ] , namerec - > data . nb_flags ) ;
0001-01-01 02:30:17 +02:30
buf [ 16 ] | = NB_ACTIVE ; /* all our names are active */
buf + = 18 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
names_added + + ;
}
}
/* Remove duplicate names. */
0001-01-01 02:30:17 +02:30
if ( names_added > 1 ) {
qsort ( buf0 , names_added , 18 , QSORT_CAST status_compare ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
for ( i = 1 ; i < names_added ; i + + )
0001-01-01 02:30:17 +02:30
{
if ( memcmp ( buf0 + 18 * i , buf0 + 18 * ( i - 1 ) , 16 ) = = 0 )
{
names_added - - ;
if ( names_added = = i )
break ;
memmove ( buf0 + 18 * i , buf0 + 18 * ( i + 1 ) , 18 * ( names_added - i ) ) ;
i - - ;
}
}
buf = buf0 + 18 * names_added ;
0001-01-01 02:30:17 +02:30
namerec = ( struct name_record * ) ubi_trNext ( namerec ) ;
0001-01-01 02:30:17 +02:30
if ( ! namerec )
{
/* End of the subnet specific name list. Now
add the names on the unicast subnet . */
struct subnet_record * uni_subrec = unicast_subnet ;
if ( uni_subrec ! = subrec )
{
subrec = uni_subrec ;
0001-01-01 02:30:17 +02:30
namerec = ( struct name_record * ) ubi_trFirst ( subrec - > namelist ) ;
0001-01-01 02:30:17 +02:30
}
}
if ( ! namerec )
break ;
}
SCVAL ( countptr , 0 , names_added ) ;
/* We don't send any stats as they could be used to attack
the protocol . */
0001-01-01 02:30:17 +02:30
memset ( buf , ' \0 ' , 46 ) ;
0001-01-01 02:30:17 +02:30
buf + = 46 ;
/* Send a NODE STATUS RESPONSE */
reply_netbios_packet ( p , /* Packet to reply to. */
0 , /* Result code. */
NMB_STATUS , /* nmbd type code. */
NMB_NAME_QUERY_OPCODE , /* opcode. */
0 , /* ttl. */
rdata , /* data to send. */
PTR_DIFF ( buf , rdata ) ) ; /* data length. */
}
/***************************************************************************
Process a name query .
For broadcast name queries :
- Only reply if the query is for one of YOUR names .
- NEVER send a negative response to a broadcast query .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_name_query_request ( struct subnet_record * subrec , struct packet_struct * p )
{
struct nmb_packet * nmb = & p - > packet . nmb ;
struct nmb_name * question = & nmb - > question . question_name ;
int name_type = question - > name_type ;
BOOL bcast = nmb - > header . nm_flags . bcast ;
int ttl = 0 ;
int rcode = 0 ;
char * prdata = NULL ;
char rdata [ 6 ] ;
BOOL success = False ;
struct name_record * namerec = NULL ;
int reply_data_len = 0 ;
int i ;
DEBUG ( 3 , ( " process_name_query_request: Name query from %s on subnet %s for name %s \n " ,
0001-01-01 02:30:17 +02:30
inet_ntoa ( p - > ip ) , subrec - > subnet_name , nmb_namestr ( question ) ) ) ;
0001-01-01 02:30:17 +02:30
/* Look up the name in the cache - if the request is a broadcast request that
came from a subnet we don ' t know about then search all the broadcast subnets
for a match ( as we don ' t know what interface the request came in on ) . */
if ( subrec = = remote_broadcast_subnet )
namerec = find_name_for_remote_broadcast_subnet ( question , FIND_ANY_NAME ) ;
else
namerec = find_name_on_subnet ( subrec , question , FIND_ANY_NAME ) ;
/* Check if it is a name that expired */
0001-01-01 02:30:17 +02:30
if ( namerec
& & ( ( namerec - > data . death_time ! = PERMANENT_TTL )
& & ( namerec - > data . death_time < p - > timestamp ) ) )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
DEBUG ( 5 , ( " process_name_query_request: expired name %s \n " , nmb_namestr ( & namerec - > name ) ) ) ;
0001-01-01 02:30:17 +02:30
namerec = NULL ;
}
if ( namerec )
{
/*
* Always respond to unicast queries .
* Don ' t respond to broadcast queries unless the query is for
* a name we own , a Primary Domain Controller name , or a WINS_PROXY
* name with type 0 or 0x20 . WINS_PROXY names are only ever added
* into the namelist if we were configured as a WINS proxy .
*/
0001-01-01 02:30:17 +02:30
if ( ! bcast
| | ( bcast
& & ( ( name_type = = 0x1b )
| | ( namerec - > data . source = = SELF_NAME )
| | ( namerec - > data . source = = PERMANENT_NAME )
| | ( ( namerec - > data . source = = WINS_PROXY_NAME )
& & ( ( name_type = = 0 ) | | ( name_type = = 0x20 ) )
)
)
)
)
0001-01-01 02:30:17 +02:30
{
/* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
or it ' s a Domain Master type . */
0001-01-01 02:30:17 +02:30
/*
* If this is a WINS_PROXY_NAME , then ceck that none of the IP
* addresses we are returning is on the same broadcast subnet
* as the requesting packet . If it is then don ' t reply as the
* actual machine will be replying also and we don ' t want two
* replies to a broadcast query .
*/
0001-01-01 02:30:17 +02:30
if ( namerec - > data . source = = WINS_PROXY_NAME )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < namerec - > data . num_ips ; i + + )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
if ( same_net ( namerec - > data . ip [ i ] , subrec - > myip , subrec - > mask_ip ) )
0001-01-01 02:30:17 +02:30
{
DEBUG ( 5 , ( " process_name_query_request: name %s is a WINS proxy name and is also \
on the same subnet ( % s ) as the requestor . Not replying . \ n " ,
0001-01-01 02:30:17 +02:30
nmb_namestr ( & namerec - > name ) , subrec - > subnet_name ) ) ;
0001-01-01 02:30:17 +02:30
return ;
}
}
}
0001-01-01 02:30:17 +02:30
ttl = ( namerec - > data . death_time ! = PERMANENT_TTL ) ?
namerec - > data . death_time - p - > timestamp : lp_max_ttl ( ) ;
0001-01-01 02:30:17 +02:30
/* Copy all known ip addresses into the return data. */
/* Optimise for the common case of one IP address so
we don ' t need a malloc . */
0001-01-01 02:30:17 +02:30
if ( namerec - > data . num_ips = = 1 )
0001-01-01 02:30:17 +02:30
prdata = rdata ;
else
{
0001-01-01 02:30:17 +02:30
if ( ( prdata = ( char * ) malloc ( namerec - > data . num_ips * 6 ) ) = = NULL )
0001-01-01 02:30:17 +02:30
{
DEBUG ( 0 , ( " process_name_query_request: malloc fail ! \n " ) ) ;
return ;
}
}
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < namerec - > data . num_ips ; i + + )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
set_nb_flags ( & prdata [ i * 6 ] , namerec - > data . nb_flags ) ;
putip ( ( char * ) & prdata [ 2 + ( i * 6 ) ] , & namerec - > data . ip [ i ] ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
sort_query_replies ( prdata , i , p - > ip ) ;
0001-01-01 02:30:17 +02:30
reply_data_len = namerec - > data . num_ips * 6 ;
0001-01-01 02:30:17 +02:30
success = True ;
}
}
/*
* If a machine is broadcasting a name lookup request and we have lp_wins_proxy ( )
* set we should initiate a WINS query here . On success we add the resolved name
* into our namelist with a type of WINS_PROXY_NAME and then reply to the query .
*/
if ( ! success & & ( namerec = = NULL ) & & we_are_a_wins_client ( ) & & lp_wins_proxy ( ) & &
bcast & & ( subrec ! = remote_broadcast_subnet ) )
{
make_wins_proxy_name_query_request ( subrec , p , question ) ;
return ;
}
if ( ! success & & bcast )
{
0001-01-01 02:30:17 +02:30
if ( prdata ! = rdata )
SAFE_FREE ( prdata ) ;
0001-01-01 02:30:17 +02:30
return ; /* Never reply with a negative response to broadcasts. */
}
/*
* Final check . From observation , if a unicast packet is sent
* to a non - WINS server with the recursion desired bit set
* then never send a negative response .
*/
if ( ! success & & ! bcast & & nmb - > header . nm_flags . recursion_desired )
{
0001-01-01 02:30:17 +02:30
if ( prdata ! = rdata )
SAFE_FREE ( prdata ) ;
0001-01-01 02:30:17 +02:30
return ;
}
if ( success )
{
rcode = 0 ;
DEBUG ( 3 , ( " OK \n " ) ) ;
}
else
{
rcode = NAM_ERR ;
DEBUG ( 3 , ( " UNKNOWN \n " ) ) ;
}
/* See rfc1002.txt 4.2.13. */
reply_netbios_packet ( p , /* Packet to reply to. */
rcode , /* Result code. */
NMB_QUERY , /* nmbd type code. */
NMB_NAME_QUERY_OPCODE , /* opcode. */
ttl , /* ttl. */
prdata , /* data to send. */
reply_data_len ) ; /* data length. */
0001-01-01 02:30:17 +02:30
if ( prdata ! = rdata )
SAFE_FREE ( prdata ) ;
0001-01-01 02:30:17 +02:30
}