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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1997-12-13 17:16:07 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1997-12-13 17:16:07 +03:00
*/
# include "includes.h"
2010-08-18 17:22:09 +04:00
# include "nmbd/nmbd.h"
1997-12-13 17:16:07 +03:00
/****************************************************************************
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-16 00:45:45 +03:00
unstring name ;
2003-08-27 05:25:01 +04:00
struct packet_struct * original_packet ;
struct subnet_record * orig_broadcast_subnet ;
2005-12-07 02:06:38 +03:00
struct name_record * namerec = NULL ;
2015-04-30 06:14:34 +03:00
uint16_t nb_flags ;
2003-08-27 05:25:01 +04:00
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 * ) ) ;
2006-03-06 20:47:21 +03:00
if ( rrec ) {
2006-03-06 23:05:20 +03:00
nb_flags = get_nb_flags ( rrec - > rdata ) ;
2006-03-06 20:47:21 +03:00
num_ips = rrec - > rdlength / 6 ;
} else {
2006-03-06 23:05:20 +03:00
nb_flags = 0 ;
2006-03-06 20:47:21 +03:00
num_ips = 0 ;
}
2003-08-27 05:25:01 +04:00
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 {
2004-12-07 21:25:53 +03:00
if ( ( iplist = SMB_MALLOC_ARRAY ( struct in_addr , num_ips ) ) = = NULL ) {
2003-08-27 05:25:01 +04:00
DEBUG ( 0 , ( " wins_proxy_name_query_request_success: malloc fail ! \n " ) ) ;
return ;
}
2005-12-07 02:06:38 +03:00
for ( i = 0 ; i < num_ips ; i + + ) {
2003-08-27 05:25:01 +04:00
putip ( ( char * ) & iplist [ i ] , ( char * ) & rrec - > rdata [ ( i * 6 ) + 2 ] ) ;
2005-12-07 02:06:38 +03:00
}
2003-08-27 05:25:01 +04:00
}
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
2006-03-08 04:43:23 +03:00
if ( rrec - > ttl = = PERMANENT_TTL ) {
2003-08-27 05:25:01 +04:00
ttl = lp_max_ttl ( ) ;
2005-12-07 02:06:38 +03:00
}
2003-08-27 05:25:01 +04:00
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( name , sizeof ( name ) , nmbname - > name ) ;
2005-12-07 02:06:38 +03:00
add_name_to_subnet ( orig_broadcast_subnet , name ,
2003-08-27 05:25:01 +04:00
nmbname - > name_type , nb_flags , ttl ,
WINS_PROXY_NAME , num_ips , iplist ) ;
2006-03-06 22:23:54 +03:00
if ( iplist ! = & ip ) {
SAFE_FREE ( iplist ) ;
}
2005-12-07 02:06:38 +03:00
namerec = find_name_on_subnet ( orig_broadcast_subnet , nmbname , FIND_ANY_NAME ) ;
if ( ! namerec ) {
DEBUG ( 0 , ( " wins_proxy_name_query_request_success: failed to add "
" name %s to subnet %s ! \n " ,
name ,
orig_broadcast_subnet - > subnet_name ) ) ;
return ;
}
2003-08-27 05:25:01 +04:00
/*
* 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 + + ) {
2007-10-11 05:25:16 +04:00
if ( same_net_v4 ( namerec - > data . ip [ i ] , orig_broadcast_subnet - > myip ,
2003-08-27 05:25:01 +04:00
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 ;
2004-12-07 21:25:53 +03:00
struct userdata_struct * new_userdata = ( struct userdata_struct * ) SMB_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 )
{
2005-03-10 01:20:40 +03:00
union {
struct userdata_struct ud ;
char c [ sizeof ( struct userdata_struct ) + sizeof ( struct subrec * ) +
sizeof ( struct packet_struct * ) + sizeof ( long * ) ] ;
} ud ;
struct userdata_struct * userdata = & ud . ud ;
2004-03-16 00:45:45 +03:00
unstring qname ;
1997-12-13 17:16:07 +03:00
2005-03-10 01:20:40 +03: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
}