2005-01-21 11:18:56 +00:00
/*
Unix SMB / CIFS implementation .
general name resolution interface
Copyright ( C ) Andrew Tridgell 2005
2007-12-10 18:41:19 +01:00
Copyright ( C ) Jelmer Vernooij 2007
2005-01-21 11:18:56 +00: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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-01-21 11:18:56 +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 11:18:56 +00:00
*/
# include "includes.h"
# include "libcli/composite/composite.h"
2006-03-07 11:07:23 +00:00
# include "libcli/resolve/resolve.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_nbt.h"
2007-10-13 20:24:37 +02:00
# include "system/network.h"
2008-12-11 15:43:47 +01:00
# include "lib/socket/socket.h"
2008-10-11 21:31:42 +02:00
# include "../lib/util/dlinklist.h"
2010-03-10 15:56:13 +11:00
# include "lib/tsocket/tsocket.h"
2010-03-26 17:36:02 +11:00
# include "lib/util/util_net.h"
2005-01-21 11:18:56 +00:00
2020-08-07 13:27:39 -07:00
# undef strcasecmp
2005-01-21 13:13:24 +00:00
struct resolve_state {
2007-12-10 18:41:19 +01:00
struct resolve_context * ctx ;
struct resolve_method * method ;
2008-12-13 11:03:52 +01:00
uint32_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 ;
2005-09-26 11:47:55 +00:00
struct composite_context * creq ;
2008-12-11 15:43:47 +01:00
struct socket_address * * addrs ;
2008-12-13 20:50:36 +01:00
char * * names ;
2005-01-21 13:13:24 +00:00
} ;
2005-01-31 08:30:44 +00:00
static struct composite_context * setup_next_method ( struct composite_context * c ) ;
2005-01-21 13:13:24 +00:00
2005-06-18 22:32:14 +00:00
2007-12-10 18:41:19 +01:00
struct resolve_context {
struct resolve_method {
resolve_name_send_fn send_fn ;
resolve_name_recv_fn recv_fn ;
void * privdata ;
struct resolve_method * prev , * next ;
} * methods ;
2005-01-22 00:52:54 +00:00
} ;
2007-12-10 18:41:19 +01:00
/**
* Initialize a resolve context
*/
struct resolve_context * resolve_context_init ( TALLOC_CTX * mem_ctx )
{
return talloc_zero ( mem_ctx , struct resolve_context ) ;
}
2005-01-22 00:52:54 +00:00
2007-12-10 18:41:19 +01:00
/**
* Add a resolve method
*/
bool resolve_context_add_method ( struct resolve_context * ctx , resolve_name_send_fn send_fn ,
resolve_name_recv_fn recv_fn , void * userdata )
2005-01-22 00:52:54 +00:00
{
2007-12-10 18:41:19 +01:00
struct resolve_method * method = talloc_zero ( ctx , struct resolve_method ) ;
if ( method = = NULL )
return false ;
method - > send_fn = send_fn ;
method - > recv_fn = recv_fn ;
method - > privdata = userdata ;
2016-02-05 11:32:18 +01:00
DLIST_ADD_END ( ctx - > methods , method ) ;
2007-12-10 18:41:19 +01:00
return true ;
2005-01-22 00:52:54 +00:00
}
2007-12-10 18:41:19 +01:00
/**
2005-01-21 13:13:24 +00:00
handle completion of one name resolve method
*/
2005-09-26 11:47:55 +00:00
static void resolve_handler ( struct composite_context * creq )
2005-01-21 13:13:24 +00:00
{
2007-09-07 15:08:14 +00:00
struct composite_context * c = ( struct composite_context * ) creq - > async . private_data ;
2005-09-26 11:47:55 +00:00
struct resolve_state * state = talloc_get_type ( c - > private_data , struct resolve_state ) ;
2007-12-10 18:41:19 +01:00
const struct resolve_method * method = state - > method ;
2005-01-21 13:13:24 +00:00
2008-12-13 20:50:36 +01:00
c - > status = method - > recv_fn ( creq , state , & state - > addrs , & state - > names ) ;
2005-01-21 13:13:24 +00:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2007-12-10 18:41:19 +01:00
state - > method = state - > method - > next ;
2005-09-26 11:47:55 +00:00
state - > creq = setup_next_method ( c ) ;
if ( state - > creq ! = NULL ) {
2005-01-21 13:13:24 +00:00
return ;
}
}
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
2005-01-21 13:13:24 +00:00
} else {
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_DONE ;
2005-01-21 13:13:24 +00:00
}
if ( c - > async . fn ) {
c - > async . fn ( c ) ;
}
}
2005-01-31 08:30:44 +00:00
static struct composite_context * setup_next_method ( struct composite_context * c )
2005-01-21 13:13:24 +00:00
{
2005-09-26 11:47:55 +00:00
struct resolve_state * state = talloc_get_type ( c - > private_data , struct resolve_state ) ;
struct composite_context * creq = NULL ;
2005-01-21 13:13:24 +00:00
do {
2007-12-10 18:41:19 +01:00
if ( state - > method ) {
2008-12-13 11:03:52 +01:00
creq = state - > method - > send_fn ( c , c - > event_ctx ,
state - > method - > privdata ,
state - > flags ,
2008-12-17 17:25:40 +01:00
state - > port ,
2008-12-13 11:03:52 +01:00
& state - > name ) ;
2005-01-21 13:13:24 +00:00
}
2007-12-10 18:41:19 +01:00
if ( creq = = NULL & & state - > method ) state - > method = state - > method - > next ;
2005-09-29 22:37:15 +00:00
2007-12-10 18:41:19 +01:00
} while ( ! creq & & state - > method ) ;
2005-01-21 13:13:24 +00:00
2005-09-26 11:47:55 +00:00
if ( creq ) {
creq - > async . fn = resolve_handler ;
creq - > async . private_data = c ;
2005-01-21 13:13:24 +00:00
}
2005-09-26 11:47:55 +00:00
return creq ;
2005-01-21 13:13:24 +00:00
}
2005-01-21 11:18:56 +00:00
/*
general name resolution - async send
*/
2008-12-11 15:43:47 +01:00
struct composite_context * resolve_name_all_send ( struct resolve_context * ctx ,
2009-09-19 08:23:03 -07:00
TALLOC_CTX * mem_ctx ,
2010-08-31 14:00:37 +10:00
uint32_t flags , /* RESOLVE_NAME_FLAG_* */
2008-12-17 17:25:40 +01:00
uint16_t port ,
2008-12-11 15:43:47 +01:00
struct nbt_name * name ,
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx )
2005-01-21 11:18:56 +00:00
{
2005-01-31 08:30:44 +00:00
struct composite_context * c ;
2005-01-21 13:13:24 +00:00
struct resolve_state * state ;
2010-03-10 15:56:13 +11:00
if ( event_ctx = = NULL ) {
2008-05-14 19:49:38 +02:00
return NULL ;
2006-11-08 21:18:24 +00:00
}
2005-09-29 22:37:15 +00:00
2009-09-19 08:23:03 -07:00
c = composite_create ( mem_ctx , event_ctx ) ;
2008-04-21 17:58:23 -04:00
if ( c = = NULL ) return NULL ;
2006-11-08 21:18:24 +00:00
if ( composite_nomem ( c - > event_ctx , c ) ) return c ;
state = talloc ( c , struct resolve_state ) ;
if ( composite_nomem ( state , c ) ) return c ;
c - > private_data = state ;
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:18:24 +00:00
c - > status = nbt_name_dup ( state , name , & state - > name ) ;
if ( ! composite_is_ok ( c ) ) return c ;
2007-12-10 18:41:19 +01:00
state - > ctx = talloc_reference ( state , ctx ) ;
if ( composite_nomem ( state - > ctx , c ) ) return c ;
2005-01-21 13:13:24 +00:00
2005-09-13 12:46:03 +00:00
if ( is_ipaddress ( state - > name . name ) | |
strcasecmp ( state - > name . name , " localhost " ) = = 0 ) {
2008-12-11 15:43:47 +01:00
state - > addrs = talloc_array ( state , struct socket_address * , 2 ) ;
if ( composite_nomem ( state - > addrs , c ) ) return c ;
2011-06-06 10:13:20 +10:00
state - > addrs [ 0 ] = socket_address_from_strings ( state - > addrs , " ip " ,
state - > name . name , 0 ) ;
2008-12-11 15:43:47 +01:00
if ( composite_nomem ( state - > addrs [ 0 ] , c ) ) return c ;
state - > addrs [ 1 ] = NULL ;
2008-12-13 20:50:36 +01:00
state - > names = talloc_array ( state , char * , 2 ) ;
if ( composite_nomem ( state - > names , c ) ) return c ;
state - > names [ 0 ] = talloc_strdup ( state - > names , state - > name . name ) ;
if ( composite_nomem ( state - > names [ 0 ] , c ) ) return c ;
state - > names [ 1 ] = NULL ;
2005-12-08 01:13:45 +00:00
composite_done ( c ) ;
2005-09-13 12:46:03 +00:00
return c ;
}
2007-12-10 18:41:19 +01:00
state - > method = ctx - > methods ;
2008-09-29 21:59:04 -07:00
if ( state - > method = = NULL ) {
2008-09-30 08:42:12 -07:00
composite_error ( c , NT_STATUS_BAD_NETWORK_NAME ) ;
2008-09-29 21:59:04 -07:00
return c ;
}
2005-09-26 11:47:55 +00:00
state - > creq = setup_next_method ( c ) ;
2006-11-08 21:18:24 +00:00
if ( composite_nomem ( state - > creq , c ) ) return c ;
2005-01-21 13:13:24 +00:00
return c ;
2005-01-21 11:18:56 +00:00
}
/*
general name resolution method - recv side
*/
2008-12-11 15:43:47 +01:00
NTSTATUS resolve_name_all_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
2008-12-13 20:50:36 +01:00
struct socket_address * * * addrs ,
char * * * names )
2005-01-21 11:18:56 +00:00
{
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 resolve_state * state = talloc_get_type ( c - > private_data , struct resolve_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 ;
2005-01-21 11:18:56 +00:00
}
2010-08-31 14:00:37 +10:00
struct composite_context * resolve_name_ex_send ( struct resolve_context * ctx ,
TALLOC_CTX * mem_ctx ,
uint32_t flags , /* RESOLVE_NAME_FLAG_* */
uint16_t port ,
struct nbt_name * name ,
struct tevent_context * event_ctx )
{
return resolve_name_all_send ( ctx , mem_ctx , flags , port , name , event_ctx ) ;
}
2008-12-11 15:43:47 +01:00
struct composite_context * resolve_name_send ( struct resolve_context * ctx ,
2009-09-19 08:23:03 -07:00
TALLOC_CTX * mem_ctx ,
2008-12-11 15:43:47 +01:00
struct nbt_name * name ,
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx )
2008-12-11 15:43:47 +01:00
{
2010-08-31 14:00:37 +10:00
return resolve_name_ex_send ( ctx , mem_ctx , 0 , 0 , name , event_ctx ) ;
2008-12-11 15:43:47 +01:00
}
NTSTATUS resolve_name_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
const char * * reply_addr )
{
NTSTATUS status ;
struct socket_address * * addrs = NULL ;
2008-12-13 20:50:36 +01:00
status = resolve_name_all_recv ( c , mem_ctx , & addrs , NULL ) ;
2008-12-11 15:43:47 +01:00
if ( NT_STATUS_IS_OK ( status ) ) {
2010-03-10 15:56:13 +11:00
struct tsocket_address * t_addr = socket_address_to_tsocket_address ( addrs , addrs [ 0 ] ) ;
if ( ! t_addr ) {
return NT_STATUS_NO_MEMORY ;
}
* reply_addr = tsocket_address_inet_addr_string ( t_addr , mem_ctx ) ;
2008-12-11 15:43:47 +01:00
talloc_free ( addrs ) ;
2010-03-10 15:56:13 +11:00
if ( ! * reply_addr ) {
return NT_STATUS_NO_MEMORY ;
}
2008-12-11 15:43:47 +01:00
}
return status ;
}
2010-09-13 23:08:28 +10:00
/*
receive multiple responses from resolve_name_send ( )
*/
NTSTATUS resolve_name_multiple_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
const char * * * reply_addrs )
{
NTSTATUS status ;
struct socket_address * * addrs = NULL ;
int i ;
status = resolve_name_all_recv ( c , mem_ctx , & addrs , NULL ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
/* count the addresses */
for ( i = 0 ; addrs [ i ] ; i + + ) ;
* reply_addrs = talloc_array ( mem_ctx , const char * , i + 1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( * reply_addrs ) ;
for ( i = 0 ; addrs [ i ] ; i + + ) {
struct tsocket_address * t_addr = socket_address_to_tsocket_address ( addrs , addrs [ i ] ) ;
NT_STATUS_HAVE_NO_MEMORY ( t_addr ) ;
( * reply_addrs ) [ i ] = tsocket_address_inet_addr_string ( t_addr , * reply_addrs ) ;
NT_STATUS_HAVE_NO_MEMORY ( ( * reply_addrs ) [ i ] ) ;
}
( * reply_addrs ) [ i ] = NULL ;
talloc_free ( addrs ) ;
return status ;
}
2008-12-11 15:43:47 +01:00
/*
general name resolution - sync call
*/
2010-08-31 14:00:37 +10:00
NTSTATUS resolve_name_ex ( struct resolve_context * ctx ,
uint32_t flags , /* RESOLVE_NAME_FLAG_* */
uint16_t port ,
struct nbt_name * name ,
TALLOC_CTX * mem_ctx ,
const char * * reply_addr ,
struct tevent_context * ev )
2005-01-21 11:18:56 +00:00
{
2010-08-31 14:00:37 +10:00
struct composite_context * c = resolve_name_ex_send ( ctx , mem_ctx , flags , port , name , ev ) ;
2005-01-21 11:18:56 +00:00
return resolve_name_recv ( c , mem_ctx , reply_addr ) ;
}
2005-05-22 10:23:01 +00:00
2010-08-31 14:00:37 +10:00
2005-05-22 10:23:01 +00:00
/* Initialise a struct nbt_name with a NULL scope */
void make_nbt_name ( struct nbt_name * nbt , const char * name , int type )
{
nbt - > name = name ;
nbt - > scope = NULL ;
nbt - > type = type ;
}
/* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
void make_nbt_name_client ( struct nbt_name * nbt , const char * name )
{
make_nbt_name ( nbt , name , NBT_NAME_CLIENT ) ;
}
/* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
void make_nbt_name_server ( struct nbt_name * nbt , const char * name )
{
make_nbt_name ( nbt , name , NBT_NAME_SERVER ) ;
}
2007-12-10 18:41:19 +01:00