2005-01-31 01:57:58 +00:00
/*
Unix SMB / CIFS implementation .
packet utility functions
Copyright ( C ) Andrew Tridgell 2005
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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-01-31 01:57:58 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-01-31 01:57:58 +00:00
*/
# include "includes.h"
# include "nbt_server/nbt_server.h"
2020-11-20 15:27:17 +01:00
# include "samba/service_task.h"
2006-01-09 22:12:53 +00:00
# include "lib/socket/socket.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_nbt.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2005-01-31 01:57:58 +00:00
/*
we received a badly formed packet - log it
*/
2005-02-04 01:39:10 +00:00
void nbtd_bad_packet ( struct nbt_name_packet * packet ,
2006-01-09 22:12:53 +00:00
const struct socket_address * src , const char * reason )
2005-01-31 01:57:58 +00:00
{
2005-10-14 12:22:15 +00:00
DEBUG ( 2 , ( " nbtd: bad packet '%s' from %s:%d \n " , reason , src - > addr , src - > port ) ) ;
2005-01-31 01:57:58 +00:00
if ( DEBUGLVL ( 5 ) ) {
NDR_PRINT_DEBUG ( nbt_name_packet , packet ) ;
}
}
2005-02-04 02:05:27 +00:00
/*
2005-02-04 05:13:46 +00:00
see if an incoming packet is a broadcast packet from one of our own
interfaces
2005-02-04 02:05:27 +00:00
*/
2007-10-06 21:33:16 +00:00
bool nbtd_self_packet_and_bcast ( struct nbt_name_socket * nbtsock ,
2006-01-18 16:36:53 +00:00
struct nbt_name_packet * packet ,
const struct socket_address * src )
2005-02-04 02:05:27 +00:00
{
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2005-02-06 08:25:53 +00:00
struct nbtd_interface ) ;
2006-01-18 16:36:53 +00:00
2005-02-04 05:13:46 +00:00
/* if its not a broadcast then its not considered a self packet */
if ( ! ( packet - > operation & NBT_FLAG_BROADCAST ) ) {
2007-10-06 21:33:16 +00:00
return false ;
2005-02-04 05:13:46 +00:00
}
2006-01-18 16:36:53 +00:00
/*
* this uses the fact that iface - > nbtsock is the unicast listen address
* if the interface isn ' t the global bcast interface
*
* so if the request was directed to the unicast address it isn ' t a broadcast
* message
*/
if ( iface - > nbtsock = = nbtsock & &
iface ! = iface - > nbtsrv - > bcast_interface ) {
2007-10-06 21:33:16 +00:00
return false ;
2005-02-04 02:05:27 +00:00
}
2006-01-18 16:36:53 +00:00
return nbtd_self_packet ( nbtsock , packet , src ) ;
}
2007-10-06 21:33:16 +00:00
bool nbtd_self_packet ( struct nbt_name_socket * nbtsock ,
2006-01-18 16:36:53 +00:00
struct nbt_name_packet * packet ,
const struct socket_address * src )
{
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2006-01-18 16:36:53 +00:00
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
/* if its not from the nbt port, then it wasn't a broadcast from us */
2010-07-16 14:32:42 +10:00
if ( src - > port ! = lpcfg_nbt_port ( iface - > nbtsrv - > task - > lp_ctx ) ) {
2007-10-06 21:33:16 +00:00
return false ;
2005-02-04 05:13:46 +00:00
}
/* we have to loop over our interface list, seeing if its from
one of our own interfaces */
2005-02-04 02:05:27 +00:00
for ( iface = nbtsrv - > interfaces ; iface ; iface = iface - > next ) {
2005-10-14 12:22:15 +00:00
if ( strcmp ( src - > addr , iface - > ip_address ) = = 0 ) {
2007-10-06 21:33:16 +00:00
return true ;
2005-02-04 02:05:27 +00:00
}
}
2007-10-06 21:33:16 +00:00
return false ;
2005-02-04 02:05:27 +00:00
}
2005-02-11 23:54:37 +00:00
2018-02-02 13:30:44 +01:00
struct nbt_name_packet * nbtd_name_query_reply_packet (
TALLOC_CTX * mem_ctx ,
uint16_t trn_id ,
uint32_t ttl ,
uint16_t nb_flags ,
const struct nbt_name * name ,
const char * * addresses ,
size_t num_addresses )
2005-02-11 23:54:37 +00:00
{
struct nbt_name_packet * packet ;
2018-02-02 13:30:44 +01:00
size_t i ;
struct nbt_res_rec * answer ;
struct nbt_rdata_netbios * rdata ;
NTSTATUS status ;
2005-02-11 23:54:37 +00:00
if ( num_addresses = = 0 ) {
2018-02-02 13:30:44 +01:00
return NULL ;
2005-02-11 23:54:37 +00:00
}
2018-02-02 13:30:44 +01:00
packet = talloc_zero ( mem_ctx , struct nbt_name_packet ) ;
if ( packet = = NULL ) {
return NULL ;
}
2005-02-11 23:54:37 +00:00
2018-02-02 13:30:44 +01:00
packet - > name_trn_id = trn_id ;
2005-02-11 23:54:37 +00:00
packet - > ancount = 1 ;
2010-09-29 17:22:09 -07:00
packet - > operation =
NBT_FLAG_REPLY |
NBT_OPCODE_QUERY |
NBT_FLAG_AUTHORITATIVE |
2005-02-11 23:54:37 +00:00
NBT_FLAG_RECURSION_DESIRED |
NBT_FLAG_RECURSION_AVAIL ;
packet - > answers = talloc_array ( packet , struct nbt_res_rec , 1 ) ;
2018-02-02 13:30:44 +01:00
if ( packet - > answers = = NULL ) {
goto failed ;
}
answer = packet - > answers ;
status = nbt_name_dup ( packet - > answers , name , & answer - > name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
answer - > rr_type = NBT_QTYPE_NETBIOS ;
answer - > rr_class = NBT_QCLASS_IP ;
answer - > ttl = ttl ;
rdata = & answer - > rdata . netbios ;
rdata - > length = num_addresses * 6 ;
rdata - > addresses = talloc_array (
packet - > answers ,
struct nbt_rdata_address ,
num_addresses ) ;
if ( rdata - > addresses = = NULL ) {
goto failed ;
}
for ( i = 0 ; i < num_addresses ; i + + ) {
struct nbt_rdata_address * addr = & rdata - > addresses [ i ] ;
2005-02-11 23:54:37 +00:00
addr - > nb_flags = nb_flags ;
addr - > ipaddr = talloc_strdup ( packet - > answers , addresses [ i ] ) ;
2018-02-02 13:30:44 +01:00
if ( addr - > ipaddr = = NULL ) {
goto failed ;
}
}
return packet ;
failed :
TALLOC_FREE ( packet ) ;
return NULL ;
}
/*
send a name query reply
*/
void nbtd_name_query_reply ( struct nbt_name_socket * nbtsock ,
struct nbt_name_packet * request_packet ,
struct socket_address * src ,
struct nbt_name * name , uint32_t ttl ,
uint16_t nb_flags , const char * * addresses )
{
struct nbt_name_packet * packet ;
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
packet = nbtd_name_query_reply_packet (
nbtsock ,
request_packet - > name_trn_id ,
ttl ,
nb_flags ,
name ,
addresses ,
str_list_length ( addresses ) ) ;
if ( packet = = NULL ) {
return ;
2005-02-11 23:54:37 +00:00
}
2005-02-12 01:00:15 +00:00
DEBUG ( 7 , ( " Sending name query reply for %s at %s to %s:%d \n " ,
2005-10-14 12:22:15 +00:00
nbt_name_string ( packet , name ) , addresses [ 0 ] , src - > addr , src - > port ) ) ;
2005-02-11 23:54:37 +00:00
2005-07-10 08:41:02 +00:00
nbtsrv - > stats . total_sent + + ;
2005-10-14 12:22:15 +00:00
nbt_name_reply_send ( nbtsock , src , packet ) ;
2005-02-11 23:54:37 +00:00
talloc_free ( packet ) ;
}
/*
send a negative name query reply
*/
void nbtd_negative_name_query_reply ( struct nbt_name_socket * nbtsock ,
struct nbt_name_packet * request_packet ,
2006-01-09 22:12:53 +00:00
struct socket_address * src )
2005-02-11 23:54:37 +00:00
{
struct nbt_name_packet * packet ;
struct nbt_name * name = & request_packet - > questions [ 0 ] . name ;
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2005-07-10 08:41:02 +00:00
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
2005-02-11 23:54:37 +00:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return ;
packet - > name_trn_id = request_packet - > name_trn_id ;
packet - > ancount = 1 ;
2010-09-29 17:22:09 -07:00
packet - > operation =
NBT_FLAG_REPLY |
NBT_OPCODE_QUERY |
NBT_FLAG_AUTHORITATIVE |
2005-02-11 23:54:37 +00:00
NBT_RCODE_NAM ;
packet - > answers = talloc_array ( packet , struct nbt_res_rec , 1 ) ;
if ( packet - > answers = = NULL ) goto failed ;
packet - > answers [ 0 ] . name = * name ;
packet - > answers [ 0 ] . rr_type = NBT_QTYPE_NULL ;
packet - > answers [ 0 ] . rr_class = NBT_QCLASS_IP ;
packet - > answers [ 0 ] . ttl = 0 ;
ZERO_STRUCT ( packet - > answers [ 0 ] . rdata ) ;
2005-02-12 01:00:15 +00:00
DEBUG ( 7 , ( " Sending negative name query reply for %s to %s:%d \n " ,
2005-10-14 12:22:15 +00:00
nbt_name_string ( packet , name ) , src - > addr , src - > port ) ) ;
2005-02-11 23:54:37 +00:00
2005-07-10 08:41:02 +00:00
nbtsrv - > stats . total_sent + + ;
2005-10-14 12:22:15 +00:00
nbt_name_reply_send ( nbtsock , src , packet ) ;
2005-02-11 23:54:37 +00:00
failed :
talloc_free ( packet ) ;
}
/*
2005-02-12 11:33:42 +00:00
send a name registration reply
2005-02-11 23:54:37 +00:00
*/
2005-02-12 11:33:42 +00:00
void nbtd_name_registration_reply ( struct nbt_name_socket * nbtsock ,
struct nbt_name_packet * request_packet ,
2006-01-09 22:12:53 +00:00
struct socket_address * src ,
2005-02-12 11:33:42 +00:00
uint8_t rcode )
2005-02-11 23:54:37 +00:00
{
struct nbt_name_packet * packet ;
struct nbt_name * name = & request_packet - > questions [ 0 ] . name ;
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2005-07-10 08:41:02 +00:00
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
2005-02-11 23:54:37 +00:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return ;
packet - > name_trn_id = request_packet - > name_trn_id ;
packet - > ancount = 1 ;
2010-09-29 17:22:09 -07:00
packet - > operation =
NBT_FLAG_REPLY |
2005-02-11 23:54:37 +00:00
NBT_OPCODE_REGISTER |
2010-09-29 17:22:09 -07:00
NBT_FLAG_AUTHORITATIVE |
2005-02-11 23:54:37 +00:00
NBT_FLAG_RECURSION_DESIRED |
NBT_FLAG_RECURSION_AVAIL |
2005-02-12 11:33:42 +00:00
rcode ;
2005-02-11 23:54:37 +00:00
packet - > answers = talloc_array ( packet , struct nbt_res_rec , 1 ) ;
if ( packet - > answers = = NULL ) goto failed ;
packet - > answers [ 0 ] . name = * name ;
packet - > answers [ 0 ] . rr_type = NBT_QTYPE_NETBIOS ;
packet - > answers [ 0 ] . rr_class = NBT_QCLASS_IP ;
2005-02-12 11:33:42 +00:00
packet - > answers [ 0 ] . ttl = request_packet - > additional [ 0 ] . ttl ;
2005-02-11 23:54:37 +00:00
packet - > answers [ 0 ] . rdata = request_packet - > additional [ 0 ] . rdata ;
2005-02-12 11:33:42 +00:00
DEBUG ( 7 , ( " Sending %s name registration reply for %s to %s:%d \n " ,
rcode = = 0 ? " positive " : " negative " ,
2005-10-14 12:22:15 +00:00
nbt_name_string ( packet , name ) , src - > addr , src - > port ) ) ;
2005-02-12 11:33:42 +00:00
2005-07-10 08:41:02 +00:00
nbtsrv - > stats . total_sent + + ;
2005-10-14 12:22:15 +00:00
nbt_name_reply_send ( nbtsock , src , packet ) ;
2005-02-12 11:33:42 +00:00
failed :
talloc_free ( packet ) ;
}
/*
send a name release reply
*/
void nbtd_name_release_reply ( struct nbt_name_socket * nbtsock ,
struct nbt_name_packet * request_packet ,
2006-01-09 22:12:53 +00:00
struct socket_address * src ,
2005-02-12 11:33:42 +00:00
uint8_t rcode )
{
struct nbt_name_packet * packet ;
struct nbt_name * name = & request_packet - > questions [ 0 ] . name ;
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2005-07-10 08:41:02 +00:00
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
2005-02-12 11:33:42 +00:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return ;
packet - > name_trn_id = request_packet - > name_trn_id ;
packet - > ancount = 1 ;
2010-09-29 17:22:09 -07:00
packet - > operation =
NBT_FLAG_REPLY |
2005-02-12 11:33:42 +00:00
NBT_OPCODE_RELEASE |
2010-09-29 17:22:09 -07:00
NBT_FLAG_AUTHORITATIVE |
2005-02-12 11:33:42 +00:00
rcode ;
packet - > answers = talloc_array ( packet , struct nbt_res_rec , 1 ) ;
if ( packet - > answers = = NULL ) goto failed ;
packet - > answers [ 0 ] . name = * name ;
packet - > answers [ 0 ] . rr_type = NBT_QTYPE_NETBIOS ;
packet - > answers [ 0 ] . rr_class = NBT_QCLASS_IP ;
packet - > answers [ 0 ] . ttl = request_packet - > additional [ 0 ] . ttl ;
packet - > answers [ 0 ] . rdata = request_packet - > additional [ 0 ] . rdata ;
DEBUG ( 7 , ( " Sending %s name release reply for %s to %s:%d \n " ,
rcode = = 0 ? " positive " : " negative " ,
2005-10-14 12:22:15 +00:00
nbt_name_string ( packet , name ) , src - > addr , src - > port ) ) ;
2005-02-11 23:54:37 +00:00
2005-07-10 08:41:02 +00:00
nbtsrv - > stats . total_sent + + ;
2005-10-14 12:22:15 +00:00
nbt_name_reply_send ( nbtsock , src , packet ) ;
2005-02-11 23:54:37 +00:00
failed :
talloc_free ( packet ) ;
}
2005-02-14 09:15:24 +00:00
/*
send a WACK reply
*/
void nbtd_wack_reply ( struct nbt_name_socket * nbtsock ,
struct nbt_name_packet * request_packet ,
2006-01-09 22:12:53 +00:00
struct socket_address * src ,
2005-02-14 09:15:24 +00:00
uint32_t ttl )
{
struct nbt_name_packet * packet ;
struct nbt_name * name = & request_packet - > questions [ 0 ] . name ;
2008-09-23 09:02:16 +02:00
struct nbtd_interface * iface = talloc_get_type ( nbtsock - > incoming . private_data ,
2005-07-10 08:41:02 +00:00
struct nbtd_interface ) ;
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
2005-02-14 09:15:24 +00:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return ;
packet - > name_trn_id = request_packet - > name_trn_id ;
packet - > ancount = 1 ;
2010-09-29 17:22:09 -07:00
packet - > operation =
NBT_FLAG_REPLY |
2005-02-14 09:15:24 +00:00
NBT_OPCODE_WACK |
2010-09-29 17:22:09 -07:00
NBT_FLAG_AUTHORITATIVE ;
2005-02-14 09:15:24 +00:00
packet - > answers = talloc_array ( packet , struct nbt_res_rec , 1 ) ;
if ( packet - > answers = = NULL ) goto failed ;
packet - > answers [ 0 ] . name = * name ;
packet - > answers [ 0 ] . rr_type = NBT_QTYPE_NETBIOS ;
packet - > answers [ 0 ] . rr_class = NBT_QCLASS_IP ;
packet - > answers [ 0 ] . ttl = ttl ;
packet - > answers [ 0 ] . rdata . data . length = 2 ;
2007-09-08 16:46:30 +00:00
packet - > answers [ 0 ] . rdata . data . data = talloc_array ( packet , uint8_t , 2 ) ;
2005-02-14 09:15:24 +00:00
if ( packet - > answers [ 0 ] . rdata . data . data = = NULL ) goto failed ;
RSSVAL ( packet - > answers [ 0 ] . rdata . data . data , 0 , request_packet - > operation ) ;
DEBUG ( 7 , ( " Sending WACK reply for %s to %s:%d \n " ,
2005-10-14 12:22:15 +00:00
nbt_name_string ( packet , name ) , src - > addr , src - > port ) ) ;
2005-02-14 09:15:24 +00:00
2005-07-10 08:41:02 +00:00
nbtsrv - > stats . total_sent + + ;
2005-10-14 12:22:15 +00:00
nbt_name_reply_send ( nbtsock , src , packet ) ;
2005-02-14 09:15:24 +00:00
failed :
talloc_free ( packet ) ;
}