2005-01-21 09:54:10 +03:00
/*
Unix SMB / CIFS implementation .
make nbt name query requests
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
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"
# include "libcli/nbt/libnbt.h"
2006-01-10 01:12:53 +03:00
# include "lib/socket/socket.h"
2005-01-21 09:54:10 +03:00
/*
send a nbt name query
*/
struct nbt_name_request * nbt_name_query_send ( struct nbt_name_socket * nbtsock ,
struct nbt_name_query * io )
{
struct nbt_name_request * req ;
struct nbt_name_packet * packet ;
2006-01-10 01:12:53 +03:00
struct socket_address * dest ;
2005-01-21 09:54:10 +03:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return NULL ;
packet - > qdcount = 1 ;
packet - > operation = NBT_OPCODE_QUERY ;
if ( io - > in . broadcast ) {
packet - > operation | = NBT_FLAG_BROADCAST ;
}
if ( io - > in . wins_lookup ) {
packet - > operation | = NBT_FLAG_RECURSION_DESIRED ;
}
packet - > questions = talloc_array ( packet , struct nbt_name_question , 1 ) ;
if ( packet - > questions = = NULL ) goto failed ;
packet - > questions [ 0 ] . name = io - > in . name ;
packet - > questions [ 0 ] . question_type = NBT_QTYPE_NETBIOS ;
packet - > questions [ 0 ] . question_class = NBT_QCLASS_IP ;
2005-10-14 16:22:15 +04:00
2006-01-10 01:12:53 +03:00
dest = socket_address_from_strings ( packet , nbtsock - > sock - > backend_name ,
io - > in . dest_addr , lp_nbt_port ( ) ) ;
if ( dest = = NULL ) goto failed ;
req = nbt_name_request_send ( nbtsock , dest , packet ,
2005-02-06 11:22:18 +03:00
io - > in . timeout , io - > in . retries , False ) ;
2005-01-21 09:54:10 +03:00
if ( req = = NULL ) goto failed ;
2005-01-31 09:55:25 +03:00
talloc_free ( packet ) ;
2005-01-21 09:54:10 +03:00
return req ;
failed :
talloc_free ( packet ) ;
return NULL ;
}
/*
2005-01-31 04:57:58 +03:00
wait for a name query reply
2005-01-21 09:54:10 +03:00
*/
NTSTATUS nbt_name_query_recv ( struct nbt_name_request * req ,
TALLOC_CTX * mem_ctx , struct nbt_name_query * io )
{
NTSTATUS status ;
struct nbt_name_packet * packet ;
2005-01-31 04:57:58 +03:00
int i ;
2005-01-21 09:54:10 +03:00
status = nbt_name_request_recv ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) | |
req - > num_replies = = 0 ) {
talloc_free ( req ) ;
return status ;
}
packet = req - > replies [ 0 ] . packet ;
2006-01-10 01:12:53 +03:00
io - > out . reply_from = talloc_steal ( mem_ctx , req - > replies [ 0 ] . dest - > addr ) ;
2005-01-21 09:54:10 +03:00
2005-02-10 06:22:47 +03:00
if ( ( packet - > operation & NBT_RCODE ) ! = 0 ) {
status = nbt_rcode_to_ntstatus ( packet - > operation & NBT_RCODE ) ;
talloc_free ( req ) ;
return status ;
}
2005-01-21 09:54:10 +03:00
if ( packet - > ancount ! = 1 | |
packet - > answers [ 0 ] . rr_type ! = NBT_QTYPE_NETBIOS | |
packet - > answers [ 0 ] . rr_class ! = NBT_QCLASS_IP ) {
talloc_free ( req ) ;
2005-02-10 06:22:47 +03:00
return status ;
2005-01-21 09:54:10 +03:00
}
io - > out . name = packet - > answers [ 0 ] . name ;
2005-01-31 04:57:58 +03:00
io - > out . num_addrs = packet - > answers [ 0 ] . rdata . netbios . length / 6 ;
2005-02-14 12:15:24 +03:00
io - > out . reply_addrs = talloc_array ( mem_ctx , const char * , io - > out . num_addrs + 1 ) ;
2005-01-31 04:57:58 +03:00
if ( io - > out . reply_addrs = = NULL ) {
2005-01-21 09:54:10 +03:00
talloc_free ( req ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-01-31 04:57:58 +03:00
for ( i = 0 ; i < io - > out . num_addrs ; i + + ) {
2005-12-02 18:02:21 +03:00
io - > out . reply_addrs [ i ] = talloc_steal ( io - > out . reply_addrs ,
2005-02-01 07:12:44 +03:00
packet - > answers [ 0 ] . rdata . netbios . addresses [ i ] . ipaddr ) ;
2005-01-31 04:57:58 +03:00
}
2005-02-14 12:15:24 +03:00
io - > out . reply_addrs [ i ] = NULL ;
2005-01-31 04:57:58 +03:00
2005-01-21 09:54:10 +03:00
talloc_steal ( mem_ctx , io - > out . name . name ) ;
talloc_steal ( mem_ctx , io - > out . name . scope ) ;
talloc_free ( req ) ;
return NT_STATUS_OK ;
}
/*
2005-01-31 04:57:58 +03:00
wait for a name query reply
2005-01-21 09:54:10 +03:00
*/
NTSTATUS nbt_name_query ( struct nbt_name_socket * nbtsock ,
TALLOC_CTX * mem_ctx , struct nbt_name_query * io )
{
struct nbt_name_request * req = nbt_name_query_send ( nbtsock , io ) ;
return nbt_name_query_recv ( req , mem_ctx , io ) ;
}
/*
send a nbt name status
*/
struct nbt_name_request * nbt_name_status_send ( struct nbt_name_socket * nbtsock ,
struct nbt_name_status * io )
{
struct nbt_name_request * req ;
struct nbt_name_packet * packet ;
2006-01-10 01:12:53 +03:00
struct socket_address * dest ;
2005-01-21 09:54:10 +03:00
packet = talloc_zero ( nbtsock , struct nbt_name_packet ) ;
if ( packet = = NULL ) return NULL ;
packet - > qdcount = 1 ;
packet - > operation = NBT_OPCODE_QUERY ;
packet - > questions = talloc_array ( packet , struct nbt_name_question , 1 ) ;
if ( packet - > questions = = NULL ) goto failed ;
packet - > questions [ 0 ] . name = io - > in . name ;
packet - > questions [ 0 ] . question_type = NBT_QTYPE_STATUS ;
packet - > questions [ 0 ] . question_class = NBT_QCLASS_IP ;
2005-10-14 16:22:15 +04:00
2006-01-10 01:12:53 +03:00
dest = socket_address_from_strings ( packet , nbtsock - > sock - > backend_name ,
io - > in . dest_addr , lp_nbt_port ( ) ) ;
if ( dest = = NULL ) goto failed ;
req = nbt_name_request_send ( nbtsock , dest , packet ,
2005-02-06 11:22:18 +03:00
io - > in . timeout , io - > in . retries , False ) ;
2005-01-21 09:54:10 +03:00
if ( req = = NULL ) goto failed ;
2005-01-31 09:55:25 +03:00
talloc_free ( packet ) ;
2005-01-21 09:54:10 +03:00
return req ;
failed :
talloc_free ( packet ) ;
return NULL ;
}
/*
2005-01-31 04:57:58 +03:00
wait for a name status reply
2005-01-21 09:54:10 +03:00
*/
NTSTATUS nbt_name_status_recv ( struct nbt_name_request * req ,
TALLOC_CTX * mem_ctx , struct nbt_name_status * io )
{
NTSTATUS status ;
struct nbt_name_packet * packet ;
int i ;
status = nbt_name_request_recv ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) | |
req - > num_replies = = 0 ) {
talloc_free ( req ) ;
return status ;
}
packet = req - > replies [ 0 ] . packet ;
2006-01-10 01:12:53 +03:00
io - > out . reply_from = talloc_steal ( mem_ctx , req - > replies [ 0 ] . dest - > addr ) ;
2005-01-21 09:54:10 +03:00
2005-02-10 06:22:47 +03:00
if ( ( packet - > operation & NBT_RCODE ) ! = 0 ) {
status = nbt_rcode_to_ntstatus ( packet - > operation & NBT_RCODE ) ;
talloc_free ( req ) ;
return status ;
}
2005-01-21 09:54:10 +03:00
if ( packet - > ancount ! = 1 | |
packet - > answers [ 0 ] . rr_type ! = NBT_QTYPE_STATUS | |
packet - > answers [ 0 ] . rr_class ! = NBT_QCLASS_IP ) {
talloc_free ( req ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
io - > out . name = packet - > answers [ 0 ] . name ;
talloc_steal ( mem_ctx , io - > out . name . name ) ;
talloc_steal ( mem_ctx , io - > out . name . scope ) ;
io - > out . status = packet - > answers [ 0 ] . rdata . status ;
talloc_steal ( mem_ctx , io - > out . status . names ) ;
for ( i = 0 ; i < io - > out . status . num_names ; i + + ) {
talloc_steal ( io - > out . status . names , io - > out . status . names [ i ] . name ) ;
}
talloc_free ( req ) ;
return NT_STATUS_OK ;
}
/*
2005-01-31 04:57:58 +03:00
wait for a name status reply
2005-01-21 09:54:10 +03:00
*/
NTSTATUS nbt_name_status ( struct nbt_name_socket * nbtsock ,
TALLOC_CTX * mem_ctx , struct nbt_name_status * io )
{
struct nbt_name_request * req = nbt_name_status_send ( nbtsock , io ) ;
return nbt_name_status_recv ( req , mem_ctx , io ) ;
}