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 ) 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"
/****************************************************************************
Function called when the name lookup succeeded .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void wins_proxy_name_query_request_success ( struct subnet_record * subrec ,
struct userdata_struct * userdata ,
struct nmb_name * nmbname , struct in_addr ip , struct res_rec * rrec )
{
2004-03-13 05:16:21 +03:00
fstring name ;
2003-08-27 05:25:01 +04:00
struct packet_struct * original_packet ;
struct subnet_record * orig_broadcast_subnet ;
struct name_record * namerec ;
uint16 nb_flags ;
int num_ips ;
int i ;
int ttl = 3600 ; /* By default one hour in the cache. */
struct in_addr * iplist ;
/* Extract the original packet and the original broadcast subnet from
the userdata . */
memcpy ( ( char * ) & orig_broadcast_subnet , userdata - > data , sizeof ( struct subnet_record * ) ) ;
memcpy ( ( char * ) & original_packet , & userdata - > data [ sizeof ( struct subnet_record * ) ] ,
sizeof ( struct packet_struct * ) ) ;
nb_flags = get_nb_flags ( rrec - > rdata ) ;
num_ips = rrec - > rdlength / 6 ;
if ( num_ips = = 0 ) {
DEBUG ( 0 , ( " wins_proxy_name_query_request_success: Invalid number of IP records (0) \
1998-11-14 04:04:13 +03:00
returned for name % s . \ n " , nmb_namestr(nmbname) ));
2003-08-27 05:25:01 +04:00
return ;
}
if ( num_ips = = 1 ) {
iplist = & ip ;
} else {
if ( ( iplist = ( struct in_addr * ) malloc ( num_ips * sizeof ( struct in_addr ) ) ) = = NULL ) {
DEBUG ( 0 , ( " wins_proxy_name_query_request_success: malloc fail ! \n " ) ) ;
return ;
}
for ( i = 0 ; i < num_ips ; i + + )
putip ( ( char * ) & iplist [ i ] , ( char * ) & rrec - > rdata [ ( i * 6 ) + 2 ] ) ;
}
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
if ( rrec = = PERMANENT_TTL )
ttl = lp_max_ttl ( ) ;
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( name , sizeof ( name ) , nmbname - > name ) ;
2003-08-27 05:25:01 +04:00
namerec = add_name_to_subnet ( orig_broadcast_subnet , name ,
nmbname - > name_type , nb_flags , ttl ,
WINS_PROXY_NAME , num_ips , iplist ) ;
if ( iplist ! = & ip )
SAFE_FREE ( iplist ) ;
/*
* Check that none of the IP addresses we are returning is on the
* same broadcast subnet as the original requesting packet . If it
* is then don ' t reply ( although we still need to add the name
* to the cache ) as the actual machine will be replying also
* and we don ' t want two replies to a broadcast query .
*/
if ( namerec & & original_packet - > packet . nmb . header . nm_flags . bcast ) {
for ( i = 0 ; i < namerec - > data . num_ips ; i + + ) {
if ( same_net ( namerec - > data . ip [ i ] , orig_broadcast_subnet - > myip ,
orig_broadcast_subnet - > mask_ip ) ) {
DEBUG ( 5 , ( " wins_proxy_name_query_request_success: name %s is a WINS \
1998-06-09 05:56:18 +04:00
proxy name and is also on the same subnet ( % s ) as the requestor . \
2003-08-27 05:25:01 +04:00
Not replying . \ n " , nmb_namestr(&namerec->name), orig_broadcast_subnet->subnet_name ) );
return ;
}
}
}
/* Finally reply to the original name query. */
reply_netbios_packet ( original_packet , /* Packet to reply to. */
0 , /* Result code. */
NMB_QUERY , /* nmbd type code. */
NMB_NAME_QUERY_OPCODE , /* opcode. */
ttl , /* ttl. */
rrec - > rdata , /* data to send. */
rrec - > rdlength ) ; /* data length. */
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function called when the name lookup failed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void wins_proxy_name_query_request_fail ( struct subnet_record * subrec ,
struct response_record * rrec ,
struct nmb_name * question_name , int fail_code )
{
2003-08-27 05:25:01 +04:00
DEBUG ( 4 , ( " wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
1998-11-14 04:04:13 +03:00
of name % s . \ n " , fail_code, nmb_namestr(question_name) ));
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function to make a deep copy of the userdata we will need when the WINS
proxy query returns .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct userdata_struct * wins_proxy_userdata_copy_fn ( struct userdata_struct * userdata )
{
2003-08-27 05:25:01 +04:00
struct packet_struct * p , * copy_of_p ;
struct userdata_struct * new_userdata = ( struct userdata_struct * ) malloc ( userdata - > userdata_len ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
if ( new_userdata = = NULL )
return NULL ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
new_userdata - > copy_fn = userdata - > copy_fn ;
new_userdata - > free_fn = userdata - > free_fn ;
new_userdata - > userdata_len = userdata - > userdata_len ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Copy the subnet_record pointer. */
memcpy ( new_userdata - > data , userdata - > data , sizeof ( struct subnet_record * ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Extract the pointer to the packet struct */
memcpy ( ( char * ) & p , & userdata - > data [ sizeof ( struct subnet_record * ) ] , sizeof ( struct packet_struct * ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Do a deep copy of the packet. */
if ( ( copy_of_p = copy_packet ( p ) ) = = NULL ) {
SAFE_FREE ( new_userdata ) ;
return NULL ;
}
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Lock the copy. */
copy_of_p - > locked = True ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
memcpy ( & new_userdata - > data [ sizeof ( struct subnet_record * ) ] , ( char * ) & copy_of_p ,
sizeof ( struct packet_struct * ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
return new_userdata ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Function to free the deep copy of the userdata we used when the WINS
proxy query returned .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void wins_proxy_userdata_free_fn ( struct userdata_struct * userdata )
{
2003-08-27 05:25:01 +04:00
struct packet_struct * p ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Extract the pointer to the packet struct */
memcpy ( ( char * ) & p , & userdata - > data [ sizeof ( struct subnet_record * ) ] ,
sizeof ( struct packet_struct * ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
/* Unlock the packet. */
p - > locked = False ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
free_packet ( p ) ;
ZERO_STRUCTP ( userdata ) ;
SAFE_FREE ( userdata ) ;
1997-12-13 17:16:07 +03:00
}
/****************************************************************************
Make a WINS query on behalf of a broadcast client name query request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void make_wins_proxy_name_query_request ( struct subnet_record * subrec ,
struct packet_struct * incoming_packet ,
struct nmb_name * question_name )
{
2003-08-27 05:25:01 +04:00
long * ud [ ( sizeof ( struct userdata_struct ) + sizeof ( struct subrec * ) +
sizeof ( struct packet_struct * ) ) / sizeof ( long * ) + 1 ] ;
struct userdata_struct * userdata = ( struct userdata_struct * ) ud ;
2004-03-13 05:16:21 +03:00
fstring qname ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
memset ( ud , ' \0 ' , sizeof ( ud ) ) ;
1997-12-13 17:16:07 +03:00
2003-08-27 05:25:01 +04:00
userdata - > copy_fn = wins_proxy_userdata_copy_fn ;
userdata - > free_fn = wins_proxy_userdata_free_fn ;
userdata - > userdata_len = sizeof ( ud ) ;
memcpy ( userdata - > data , ( char * ) & subrec , sizeof ( struct subnet_record * ) ) ;
memcpy ( & userdata - > data [ sizeof ( struct subnet_record * ) ] , ( char * ) & incoming_packet ,
sizeof ( struct packet_struct * ) ) ;
/* Now use the unicast subnet to query the name with the WINS server. */
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( qname , sizeof ( qname ) , question_name - > name ) ;
2003-08-27 05:25:01 +04:00
query_name ( unicast_subnet , qname , question_name - > name_type ,
wins_proxy_name_query_request_success ,
wins_proxy_name_query_request_fail ,
userdata ) ;
1997-12-13 17:16:07 +03:00
}