2005-01-21 13:13:24 +00:00
/*
Unix SMB / CIFS implementation .
nbt list of addresses name resolution module
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-21 13:13:24 +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-21 13:13:24 +00:00
*/
/*
TODO : we should lower the timeout , and add retries for each name
*/
# include "includes.h"
# include "libcli/composite/composite.h"
2006-03-07 11:07:23 +00:00
# include "system/network.h"
2008-12-11 15:43:47 +01:00
# include "lib/socket/socket.h"
2006-08-17 13:37:04 +00:00
# include "lib/socket/netif.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_nbt.h"
2008-09-23 08:06:33 +02:00
# include "../libcli/nbt/libnbt.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2008-10-20 18:59:51 +02:00
# include "libcli/resolve/resolve.h"
2005-01-21 13:13:24 +00:00
struct nbtlist_state {
2008-12-13 11:03:52 +01:00
uint16_t flags ;
2008-12-17 17:25:40 +01:00
uint16_t port ;
2005-01-21 13:13:24 +00:00
struct nbt_name name ;
struct nbt_name_socket * nbtsock ;
int num_queries ;
struct nbt_name_request * * queries ;
struct nbt_name_query * io_queries ;
2008-12-11 15:43:47 +01:00
struct socket_address * * addrs ;
2008-12-13 20:50:36 +01:00
char * * names ;
2007-12-13 11:41:47 +01:00
struct interface * ifaces ;
2005-01-21 13:13:24 +00:00
} ;
/*
handle events during nbtlist name resolution
*/
static void nbtlist_handler ( struct nbt_name_request * req )
{
2008-09-23 09:02:16 +02:00
struct composite_context * c = talloc_get_type ( req - > async . private_data ,
2005-09-26 11:47:55 +00:00
struct composite_context ) ;
struct nbtlist_state * state = talloc_get_type ( c - > private_data , struct nbtlist_state ) ;
2006-11-08 21:20:45 +00:00
struct nbt_name_query * q ;
2005-01-21 13:13:24 +00:00
int i ;
for ( i = 0 ; i < state - > num_queries ; i + + ) {
if ( req = = state - > queries [ i ] ) break ;
}
2005-09-29 22:37:15 +00:00
2005-01-21 13:13:24 +00:00
if ( i = = state - > num_queries ) {
/* not for us?! */
2006-11-08 21:20:45 +00:00
composite_error ( c , NT_STATUS_INTERNAL_ERROR ) ;
return ;
2005-09-26 11:47:55 +00:00
}
2005-01-21 13:13:24 +00:00
2006-11-08 21:20:45 +00:00
q = & state - > io_queries [ i ] ;
c - > status = nbt_name_query_recv ( req , state , q ) ;
/* free the network resource directly */
talloc_free ( state - > nbtsock ) ;
if ( ! composite_is_ok ( c ) ) return ;
2008-12-11 15:43:47 +01:00
if ( q - > out . num_addrs < 1 ) {
2006-11-08 21:20:45 +00:00
composite_error ( c , NT_STATUS_UNEXPECTED_NETWORK_ERROR ) ;
return ;
}
2008-12-11 15:43:47 +01:00
state - > addrs = talloc_array ( state , struct socket_address * ,
q - > out . num_addrs + 1 ) ;
if ( composite_nomem ( state - > addrs , c ) ) return ;
2005-01-21 13:13:24 +00:00
2008-12-13 20:50:36 +01:00
state - > names = talloc_array ( state , char * , q - > out . num_addrs + 1 ) ;
if ( composite_nomem ( state - > names , c ) ) return ;
2008-12-11 15:43:47 +01:00
for ( i = 0 ; i < q - > out . num_addrs ; i + + ) {
state - > addrs [ i ] = socket_address_from_strings ( state - > addrs ,
" ipv4 " ,
q - > out . reply_addrs [ i ] ,
2008-12-17 17:25:40 +01:00
state - > port ) ;
2008-12-11 15:43:47 +01:00
if ( composite_nomem ( state - > addrs [ i ] , c ) ) return ;
2008-12-13 20:50:36 +01:00
state - > names [ i ] = talloc_strdup ( state - > names , state - > name . name ) ;
if ( composite_nomem ( state - > names [ i ] , c ) ) return ;
2005-01-21 13:13:24 +00:00
}
2008-12-11 15:43:47 +01:00
state - > addrs [ i ] = NULL ;
2008-12-13 20:50:36 +01:00
state - > names [ i ] = NULL ;
2006-11-08 21:20:45 +00:00
composite_done ( c ) ;
2005-01-21 13:13:24 +00:00
}
/*
nbtlist name resolution method - async send
*/
2006-11-09 01:11:45 +00:00
struct composite_context * resolve_name_nbtlist_send ( TALLOC_CTX * mem_ctx ,
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx ,
2008-12-13 11:03:52 +01:00
uint32_t flags ,
2008-12-17 17:25:40 +01:00
uint16_t port ,
2006-11-09 01:11:45 +00:00
struct nbt_name * name ,
2014-02-27 09:52:36 +01:00
const char * const * address_list ,
2007-12-13 22:46:44 +01:00
struct interface * ifaces ,
uint16_t nbt_port ,
2008-02-21 17:17:37 +01:00
int nbt_timeout ,
2007-10-06 22:28:14 +00:00
bool broadcast ,
bool wins_lookup )
2005-01-21 13:13:24 +00:00
{
2005-01-31 08:30:44 +00:00
struct composite_context * c ;
2005-01-21 13:13:24 +00:00
struct nbtlist_state * state ;
int i ;
2008-04-21 17:58:23 -04:00
c = composite_create ( mem_ctx , event_ctx ) ;
2006-11-08 21:20:45 +00:00
if ( c = = NULL ) return NULL ;
2008-12-17 16:55:44 +01:00
if ( flags & RESOLVE_NAME_FLAG_FORCE_DNS ) {
composite_error ( c , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ;
return c ;
}
if ( strlen ( name - > name ) > 15 ) {
composite_error ( c , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ;
return c ;
}
2005-01-21 13:13:24 +00:00
state = talloc ( c , struct nbtlist_state ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state , c ) ) return c ;
c - > private_data = state ;
2005-01-21 13:13:24 +00:00
2008-12-13 11:03:52 +01:00
state - > flags = flags ;
2008-12-17 17:25:40 +01:00
state - > port = port ;
2008-12-13 11:03:52 +01:00
2006-11-08 21:20:45 +00:00
c - > status = nbt_name_dup ( state , name , & state - > name ) ;
if ( ! composite_is_ok ( c ) ) return c ;
2005-01-21 13:13:24 +00:00
2005-02-11 07:54:20 +00:00
state - > name . name = strupper_talloc ( state , state - > name . name ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > name . name , c ) ) return c ;
2005-02-11 07:54:20 +00:00
if ( state - > name . scope ) {
state - > name . scope = strupper_talloc ( state , state - > name . scope ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > name . scope , c ) ) return c ;
2005-02-11 07:54:20 +00:00
}
2007-12-13 22:46:44 +01:00
state - > ifaces = talloc_reference ( state , ifaces ) ;
2007-12-13 11:41:47 +01:00
2007-02-28 17:25:29 +00:00
/*
* we can ' t push long names on the wire ,
* so bail out here to give a useful error message
*/
if ( strlen ( state - > name . name ) > 15 ) {
composite_error ( c , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ;
return c ;
}
2010-05-09 17:20:01 +02:00
state - > nbtsock = nbt_name_socket_init ( state , event_ctx ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > nbtsock , c ) ) return c ;
2005-01-21 13:13:24 +00:00
/* count the address_list size */
for ( i = 0 ; address_list [ i ] ; i + + ) /* noop */ ;
state - > num_queries = i ;
state - > io_queries = talloc_array ( state , struct nbt_name_query , state - > num_queries ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > io_queries , c ) ) return c ;
2005-01-21 13:13:24 +00:00
state - > queries = talloc_array ( state , struct nbt_name_request * , state - > num_queries ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > queries , c ) ) return c ;
2005-01-21 13:13:24 +00:00
for ( i = 0 ; i < state - > num_queries ; i + + ) {
2005-09-29 22:37:15 +00:00
state - > io_queries [ i ] . in . name = state - > name ;
state - > io_queries [ i ] . in . dest_addr = talloc_strdup ( state - > io_queries , address_list [ i ] ) ;
2007-12-13 22:46:44 +01:00
state - > io_queries [ i ] . in . dest_port = nbt_port ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > io_queries [ i ] . in . dest_addr , c ) ) return c ;
2005-09-29 22:37:15 +00:00
state - > io_queries [ i ] . in . broadcast = broadcast ;
2005-01-21 13:13:24 +00:00
state - > io_queries [ i ] . in . wins_lookup = wins_lookup ;
2008-02-21 17:17:37 +01:00
state - > io_queries [ i ] . in . timeout = nbt_timeout ;
2005-09-29 22:37:15 +00:00
state - > io_queries [ i ] . in . retries = 2 ;
2005-01-21 13:13:24 +00:00
state - > queries [ i ] = nbt_name_query_send ( state - > nbtsock , & state - > io_queries [ i ] ) ;
2006-11-08 21:20:45 +00:00
if ( composite_nomem ( state - > queries [ i ] , c ) ) return c ;
2005-01-21 13:13:24 +00:00
2005-09-29 22:37:15 +00:00
state - > queries [ i ] - > async . fn = nbtlist_handler ;
2008-09-23 09:02:16 +02:00
state - > queries [ i ] - > async . private_data = c ;
2005-01-21 13:13:24 +00:00
}
return c ;
}
/*
nbt list of addresses name resolution method - recv side
*/
2005-01-31 08:30:44 +00:00
NTSTATUS resolve_name_nbtlist_recv ( struct composite_context * c ,
2008-12-11 15:43:47 +01:00
TALLOC_CTX * mem_ctx ,
2008-12-13 20:50:36 +01:00
struct socket_address * * * addrs ,
char * * * names )
2005-01-21 13:13:24 +00:00
{
NTSTATUS status ;
2005-01-31 08:30:44 +00:00
status = composite_wait ( c ) ;
2005-01-21 13:13:24 +00:00
if ( NT_STATUS_IS_OK ( status ) ) {
2005-09-26 11:47:55 +00:00
struct nbtlist_state * state = talloc_get_type ( c - > private_data , struct nbtlist_state ) ;
2008-12-11 15:43:47 +01:00
* addrs = talloc_steal ( mem_ctx , state - > addrs ) ;
2008-12-13 20:50:36 +01:00
if ( names ) {
* names = talloc_steal ( mem_ctx , state - > names ) ;
}
2005-01-21 13:13:24 +00:00
}
talloc_free ( c ) ;
return status ;
}