2014-03-26 17:08:13 +04:00
/*
2004-10-17 14:04:49 +04:00
Unix SMB / CIFS implementation .
Samba internal messaging functions
Copyright ( C ) Andrew Tridgell 2004
2014-03-26 17:08:13 +04:00
2004-10-17 14:04:49 +04: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 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-10-17 14:04:49 +04:00
( at your option ) any later version .
2014-03-26 17:08:13 +04:00
2004-10-17 14:04:49 +04:00
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 .
2014-03-26 17:08:13 +04:00
2004-10-17 14:04:49 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-10-17 14:04:49 +04:00
*/
# include "includes.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-01-03 18:40:05 +03:00
# include "messaging/messaging.h"
2017-03-14 02:39:13 +03:00
# include "messaging/messaging_internal.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2005-02-10 09:59:29 +03:00
# include "lib/socket/socket.h"
2005-06-05 10:53:07 +04:00
# include "librpc/gen_ndr/ndr_irpc.h"
# include "lib/messaging/irpc.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/unix_privs.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2007-01-10 13:52:09 +03:00
# include "cluster/cluster.h"
2010-08-30 15:44:01 +04:00
# include "../lib/util/tevent_ntstatus.h"
2011-10-13 13:01:56 +04:00
# include "lib/param/param.h"
2015-02-04 14:31:24 +03:00
# include "lib/util/server_id_db.h"
2015-02-11 18:31:26 +03:00
# include "lib/util/talloc_report.h"
2015-02-08 17:33:39 +03:00
# include "../source3/lib/messages_dgm.h"
# include "../source3/lib/messages_dgm_ref.h"
# include "../source3/lib/messages_util.h"
2015-02-04 14:31:24 +03:00
# include <tdb.h>
2004-10-17 14:04:49 +04:00
/* change the message version with any incompatible changes in the protocol */
2011-05-03 04:40:33 +04:00
# define IMESSAGING_VERSION 1
2004-10-17 14:04:49 +04:00
2010-09-03 18:05:38 +04:00
/*
a pending irpc call
*/
struct irpc_request {
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg_ctx ;
2010-09-03 18:05:38 +04:00
int callid ;
struct {
void ( * handler ) ( struct irpc_request * irpc , struct irpc_message * m ) ;
void * private_data ;
} incoming ;
} ;
2006-04-12 10:08:24 +04:00
/* we have a linked list of dispatch handlers for each msg_type that
this messaging server can deal with */
2004-10-17 14:04:49 +04:00
struct dispatch_fn {
struct dispatch_fn * next , * prev ;
uint32_t msg_type ;
2009-02-01 01:57:02 +03:00
void * private_data ;
2006-04-12 10:08:24 +04:00
msg_callback_t fn ;
2004-10-17 14:04:49 +04:00
} ;
/* an individual message */
2005-06-03 08:21:25 +04:00
2019-09-18 19:19:37 +03:00
static void irpc_handler ( struct imessaging_context * ,
void * ,
uint32_t ,
struct server_id ,
size_t ,
int * ,
DATA_BLOB * ) ;
2005-06-05 10:53:07 +04:00
2004-10-17 14:04:49 +04:00
/*
A useful function for testing the message system .
*/
2019-09-18 19:19:37 +03:00
static void ping_message ( struct imessaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
size_t num_fds ,
int * fds ,
DATA_BLOB * data )
2004-10-17 14:04:49 +04:00
{
2014-07-17 13:09:25 +04:00
struct server_id_buf idbuf ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2011-05-02 04:05:46 +04:00
DEBUG ( 1 , ( " INFO: Received PING message from server %s [%.*s] \n " ,
2014-07-17 13:09:25 +04:00
server_id_str_buf ( src , & idbuf ) , ( int ) data - > length ,
2005-07-17 13:20:52 +04:00
data - > data ? ( const char * ) data - > data : " " ) ) ;
2011-05-03 04:40:33 +04:00
imessaging_send ( msg , src , MSG_PONG , data ) ;
2004-10-17 14:04:49 +04:00
}
2019-09-18 19:19:37 +03:00
static void pool_message ( struct imessaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
size_t num_fds ,
int * fds ,
2015-02-11 18:31:26 +03:00
DATA_BLOB * data )
{
char * report ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2015-02-11 18:31:26 +03:00
report = talloc_report_str ( msg , NULL ) ;
if ( report ! = NULL ) {
DATA_BLOB blob = { . data = ( uint8_t * ) report ,
. length = talloc_get_size ( report ) - 1 } ;
imessaging_send ( msg , src , MSG_POOL_USAGE , & blob ) ;
}
talloc_free ( report ) ;
}
2017-01-10 00:33:55 +03:00
static void ringbuf_log_msg ( struct imessaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
2019-09-18 19:19:37 +03:00
size_t num_fds ,
int * fds ,
2017-01-10 00:33:55 +03:00
DATA_BLOB * data )
{
char * log = debug_get_ringbuf ( ) ;
size_t logsize = debug_get_ringbuf_size ( ) ;
DATA_BLOB blob ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2017-01-10 00:33:55 +03:00
if ( log = = NULL ) {
log = discard_const_p ( char , " *disabled* \n " ) ;
logsize = strlen ( log ) + 1 ;
}
blob . data = ( uint8_t * ) log ;
blob . length = logsize ;
imessaging_send ( msg , src , MSG_RINGBUF_LOG , & blob ) ;
}
2019-01-15 03:39:06 +03:00
/****************************************************************************
Receive a " set debug level " message .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void debug_imessage ( struct imessaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
2019-09-18 19:19:37 +03:00
size_t num_fds ,
int * fds ,
2019-01-15 03:39:06 +03:00
DATA_BLOB * data )
{
const char * params_str = ( const char * ) data - > data ;
struct server_id_buf src_buf ;
struct server_id dst = imessaging_get_server_id ( msg_ctx ) ;
struct server_id_buf dst_buf ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2019-01-15 03:39:06 +03:00
/* Check, it's a proper string! */
if ( params_str [ ( data - > length ) - 1 ] ! = ' \0 ' ) {
DBG_ERR ( " Invalid debug message from pid %s to pid %s \n " ,
server_id_str_buf ( src , & src_buf ) ,
server_id_str_buf ( dst , & dst_buf ) ) ;
return ;
}
DBG_ERR ( " INFO: Remote set of debug to `%s' (pid %s from pid %s) \n " ,
params_str ,
server_id_str_buf ( dst , & dst_buf ) ,
server_id_str_buf ( src , & src_buf ) ) ;
debug_parse_levels ( params_str ) ;
}
/****************************************************************************
Return current debug level .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void debuglevel_imessage ( struct imessaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
2019-09-18 19:19:37 +03:00
size_t num_fds ,
int * fds ,
2019-01-15 03:39:06 +03:00
DATA_BLOB * data )
{
char * message = debug_list_class_names_and_levels ( ) ;
DATA_BLOB blob = data_blob_null ;
struct server_id_buf src_buf ;
struct server_id dst = imessaging_get_server_id ( msg_ctx ) ;
struct server_id_buf dst_buf ;
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2019-01-15 03:39:06 +03:00
DBG_DEBUG ( " Received REQ_DEBUGLEVEL message (pid %s from pid %s) \n " ,
server_id_str_buf ( dst , & dst_buf ) ,
server_id_str_buf ( src , & src_buf ) ) ;
if ( message = = NULL ) {
DBG_ERR ( " debug_list_class_names_and_levels returned NULL \n " ) ;
return ;
}
blob = data_blob_string_const_null ( message ) ;
imessaging_send ( msg_ctx , src , MSG_DEBUGLEVEL , & blob ) ;
TALLOC_FREE ( message ) ;
}
2005-07-19 13:28:13 +04:00
/*
return uptime of messaging server via irpc
*/
2014-03-26 17:08:13 +04:00
static NTSTATUS irpc_uptime ( struct irpc_message * msg ,
2005-07-19 13:28:13 +04:00
struct irpc_uptime * r )
{
2011-05-03 04:40:33 +04:00
struct imessaging_context * ctx = talloc_get_type ( msg - > private_data , struct imessaging_context ) ;
2005-07-19 13:28:13 +04:00
* r - > out . start_time = timeval_to_nttime ( & ctx - > start_time ) ;
return NT_STATUS_OK ;
}
2015-02-08 17:33:39 +03:00
static struct dispatch_fn * imessaging_find_dispatch (
struct imessaging_context * msg , uint32_t msg_type )
2004-10-17 14:04:49 +04:00
{
2006-04-12 10:08:24 +04:00
/* temporary IDs use an idtree, the rest use a array of pointers */
2015-02-08 17:33:39 +03:00
if ( msg_type > = MSG_TMP_BASE ) {
return ( struct dispatch_fn * ) idr_find ( msg - > dispatch_tree ,
msg_type ) ;
2005-05-01 22:49:07 +04:00
}
2015-02-08 17:33:39 +03:00
if ( msg_type < msg - > num_types ) {
return msg - > dispatch [ msg_type ] ;
2005-06-03 08:21:25 +04:00
}
2015-02-08 17:33:39 +03:00
return NULL ;
2005-06-03 08:21:25 +04:00
}
2004-10-17 14:04:49 +04:00
/*
Register a dispatch function for a particular message type .
*/
2011-05-03 04:40:33 +04:00
NTSTATUS imessaging_register ( struct imessaging_context * msg , void * private_data ,
2006-04-12 10:08:24 +04:00
uint32_t msg_type , msg_callback_t fn )
2004-10-17 14:04:49 +04:00
{
struct dispatch_fn * d ;
2006-04-12 10:08:24 +04:00
/* possibly expand dispatch array */
if ( msg_type > = msg - > num_types ) {
struct dispatch_fn * * dp ;
2016-09-24 04:43:04 +03:00
uint32_t i ;
2006-04-12 10:08:24 +04:00
dp = talloc_realloc ( msg , msg - > dispatch , struct dispatch_fn * , msg_type + 1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( dp ) ;
msg - > dispatch = dp ;
for ( i = msg - > num_types ; i < = msg_type ; i + + ) {
msg - > dispatch [ i ] = NULL ;
}
msg - > num_types = msg_type + 1 ;
}
2006-04-12 19:52:17 +04:00
d = talloc_zero ( msg - > dispatch , struct dispatch_fn ) ;
2006-04-12 10:08:24 +04:00
NT_STATUS_HAVE_NO_MEMORY ( d ) ;
2004-10-17 14:04:49 +04:00
d - > msg_type = msg_type ;
2009-02-01 01:57:02 +03:00
d - > private_data = private_data ;
2004-10-17 14:04:49 +04:00
d - > fn = fn ;
2006-04-12 10:08:24 +04:00
DLIST_ADD ( msg - > dispatch [ msg_type ] , d ) ;
return NT_STATUS_OK ;
}
/*
register a temporary message handler . The msg_type is allocated
above MSG_TMP_BASE
*/
2011-05-03 04:40:33 +04:00
NTSTATUS imessaging_register_tmp ( struct imessaging_context * msg , void * private_data ,
2006-04-12 10:08:24 +04:00
msg_callback_t fn , uint32_t * msg_type )
{
struct dispatch_fn * d ;
int id ;
d = talloc_zero ( msg - > dispatch , struct dispatch_fn ) ;
NT_STATUS_HAVE_NO_MEMORY ( d ) ;
2009-02-01 01:57:02 +03:00
d - > private_data = private_data ;
2006-04-12 10:08:24 +04:00
d - > fn = fn ;
id = idr_get_new_above ( msg - > dispatch_tree , d , MSG_TMP_BASE , UINT16_MAX ) ;
if ( id = = - 1 ) {
talloc_free ( d ) ;
return NT_STATUS_TOO_MANY_CONTEXT_IDS ;
}
d - > msg_type = ( uint32_t ) id ;
( * msg_type ) = d - > msg_type ;
return NT_STATUS_OK ;
2004-10-17 14:04:49 +04:00
}
/*
De - register the function for a particular message type .
*/
2011-05-03 04:40:33 +04:00
void imessaging_deregister ( struct imessaging_context * msg , uint32_t msg_type , void * private_data )
2004-10-17 14:04:49 +04:00
{
2006-04-12 19:52:17 +04:00
struct dispatch_fn * d , * next ;
2004-10-17 14:04:49 +04:00
2006-04-12 10:08:24 +04:00
if ( msg_type > = msg - > num_types ) {
2014-03-26 17:08:13 +04:00
d = ( struct dispatch_fn * ) idr_find ( msg - > dispatch_tree ,
2007-09-09 23:34:30 +04:00
msg_type ) ;
2006-04-12 19:52:17 +04:00
if ( ! d ) return ;
idr_remove ( msg - > dispatch_tree , msg_type ) ;
talloc_free ( d ) ;
2006-04-12 10:08:24 +04:00
return ;
}
2006-04-12 19:52:17 +04:00
for ( d = msg - > dispatch [ msg_type ] ; d ; d = next ) {
2004-10-17 14:04:49 +04:00
next = d - > next ;
2009-02-01 01:57:02 +03:00
if ( d - > private_data = = private_data ) {
2006-04-12 19:52:17 +04:00
DLIST_REMOVE ( msg - > dispatch [ msg_type ] , d ) ;
2004-10-17 14:04:49 +04:00
talloc_free ( d ) ;
}
2006-04-12 10:08:24 +04:00
}
2004-10-17 14:04:49 +04:00
}
/*
*/
2011-07-22 08:55:32 +04:00
int imessaging_cleanup ( struct imessaging_context * msg )
2004-10-17 14:04:49 +04:00
{
2011-08-26 10:05:46 +04:00
if ( ! msg ) {
return 0 ;
}
2004-10-17 14:04:49 +04:00
return 0 ;
}
2016-09-24 04:36:15 +03:00
static void imessaging_dgm_recv ( struct tevent_context * ev ,
const uint8_t * buf , size_t buf_len ,
2015-02-08 17:33:39 +03:00
int * fds , size_t num_fds ,
void * private_data ) ;
2016-09-09 08:12:11 +03:00
/* Keep a list of imessaging contexts */
static struct imessaging_context * msg_ctxs ;
2018-09-14 00:43:59 +03:00
/*
* A process has terminated , clean - up any names it has registered .
*/
NTSTATUS imessaging_process_cleanup (
struct imessaging_context * msg_ctx ,
pid_t pid )
{
struct irpc_name_records * names = NULL ;
2019-09-02 12:41:05 +03:00
uint32_t i = 0 ;
uint32_t j = 0 ;
2018-09-14 00:43:59 +03:00
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
if ( mem_ctx = = NULL ) {
DBG_ERR ( " OOM unable to clean up messaging for process (%d) \n " ,
pid ) ;
return NT_STATUS_NO_MEMORY ;
}
names = irpc_all_servers ( msg_ctx , mem_ctx ) ;
if ( names = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_OK ;
}
for ( i = 0 ; i < names - > num_records ; i + + ) {
for ( j = 0 ; j < names - > names [ i ] - > count ; j + + ) {
if ( names - > names [ i ] - > ids [ j ] . pid = = pid ) {
int ret = server_id_db_prune_name (
msg_ctx - > names ,
names - > names [ i ] - > name ,
names - > names [ i ] - > ids [ j ] ) ;
if ( ret ! = 0 & & ret ! = ENOENT ) {
TALLOC_FREE ( mem_ctx ) ;
return map_nt_error_from_unix_common (
ret ) ;
}
}
}
}
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_OK ;
}
2016-09-09 08:12:11 +03:00
static int imessaging_context_destructor ( struct imessaging_context * msg )
{
DLIST_REMOVE ( msg_ctxs , msg ) ;
2016-09-15 15:19:51 +03:00
TALLOC_FREE ( msg - > msg_dgm_ref ) ;
2016-09-09 08:12:11 +03:00
return 0 ;
}
/*
2017-04-03 20:58:24 +03:00
* Cleanup messaging dgm contexts on a specific event context .
2016-09-09 08:12:11 +03:00
*
* We must make sure to unref all messaging_dgm_ref ' s * before * the
* tevent context goes away . Only when the last ref is freed , the
* refcounted messaging dgm context will be freed .
*/
2017-04-03 20:58:24 +03:00
void imessaging_dgm_unref_ev ( struct tevent_context * ev )
2016-09-09 08:12:11 +03:00
{
struct imessaging_context * msg = NULL ;
for ( msg = msg_ctxs ; msg ! = NULL ; msg = msg - > next ) {
2017-04-03 20:58:24 +03:00
if ( msg - > ev = = ev ) {
TALLOC_FREE ( msg - > msg_dgm_ref ) ;
}
2016-09-09 08:12:11 +03:00
}
}
2017-03-29 21:11:37 +03:00
static NTSTATUS imessaging_reinit ( struct imessaging_context * msg )
{
int ret = - 1 ;
TALLOC_FREE ( msg - > msg_dgm_ref ) ;
msg - > server_id . pid = getpid ( ) ;
msg - > msg_dgm_ref = messaging_dgm_ref ( msg ,
msg - > ev ,
& msg - > server_id . unique_id ,
msg - > sock_dir ,
msg - > lock_dir ,
imessaging_dgm_recv ,
msg ,
& ret ) ;
if ( msg - > msg_dgm_ref = = NULL ) {
DEBUG ( 2 , ( " messaging_dgm_ref failed: %s \n " ,
strerror ( ret ) ) ) ;
return map_nt_error_from_unix_common ( ret ) ;
}
server_id_db_reinit ( msg - > names , msg - > server_id ) ;
return NT_STATUS_OK ;
}
/*
* Must be called after a fork .
*/
NTSTATUS imessaging_reinit_all ( void )
{
struct imessaging_context * msg = NULL ;
for ( msg = msg_ctxs ; msg ! = NULL ; msg = msg - > next ) {
NTSTATUS status = imessaging_reinit ( msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
return NT_STATUS_OK ;
}
2004-10-17 14:04:49 +04:00
/*
create the listening socket and setup the dispatcher
*/
2018-12-27 14:41:25 +03:00
struct imessaging_context * imessaging_init ( TALLOC_CTX * mem_ctx ,
2011-10-13 13:01:56 +04:00
struct loadparm_context * lp_ctx ,
2011-07-22 08:55:32 +04:00
struct server_id server_id ,
2016-07-22 21:17:24 +03:00
struct tevent_context * ev )
2004-10-17 14:04:49 +04:00
{
2017-03-31 21:07:35 +03:00
NTSTATUS status ;
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg ;
2012-12-13 19:10:38 +04:00
bool ok ;
2015-02-08 17:33:39 +03:00
int ret ;
2015-10-14 13:40:03 +03:00
const char * lock_dir = NULL ;
2015-10-20 12:35:23 +03:00
int tdb_flags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST ;
2004-10-17 14:04:49 +04:00
2008-04-22 01:58:23 +04:00
if ( ev = = NULL ) {
return NULL ;
}
2011-05-03 04:40:33 +04:00
msg = talloc_zero ( mem_ctx , struct imessaging_context ) ;
2004-10-17 14:04:49 +04:00
if ( msg = = NULL ) {
return NULL ;
}
2016-09-29 02:05:25 +03:00
msg - > ev = ev ;
2004-10-17 14:04:49 +04:00
2016-09-09 08:12:11 +03:00
talloc_set_destructor ( msg , imessaging_context_destructor ) ;
2004-10-17 14:04:49 +04:00
/* create the messaging directory if needed */
2015-10-14 13:40:03 +03:00
lock_dir = lpcfg_lock_directory ( lp_ctx ) ;
if ( lock_dir = = NULL ) {
goto fail ;
}
2015-09-16 13:44:43 +03:00
msg - > sock_dir = lpcfg_private_path ( msg , lp_ctx , " msg.sock " ) ;
2015-02-08 17:33:39 +03:00
if ( msg - > sock_dir = = NULL ) {
goto fail ;
}
ok = directory_create_or_exist_strict ( msg - > sock_dir , geteuid ( ) , 0700 ) ;
if ( ! ok ) {
2014-03-27 14:08:55 +04:00
goto fail ;
}
2011-10-13 13:01:56 +04:00
2015-09-16 13:44:43 +03:00
msg - > lock_dir = lpcfg_lock_path ( msg , lp_ctx , " msg.lock " ) ;
2015-02-08 17:33:39 +03:00
if ( msg - > lock_dir = = NULL ) {
goto fail ;
}
ok = directory_create_or_exist_strict ( msg - > lock_dir , geteuid ( ) , 0755 ) ;
2012-12-13 19:10:38 +04:00
if ( ! ok ) {
2014-03-27 14:07:34 +04:00
goto fail ;
2012-12-13 19:10:38 +04:00
}
2011-10-13 13:01:56 +04:00
2015-02-08 17:33:39 +03:00
msg - > msg_dgm_ref = messaging_dgm_ref (
2015-10-12 22:30:30 +03:00
msg , ev , & server_id . unique_id , msg - > sock_dir , msg - > lock_dir ,
2015-02-08 17:33:39 +03:00
imessaging_dgm_recv , msg , & ret ) ;
if ( msg - > msg_dgm_ref = = NULL ) {
2014-03-27 14:08:55 +04:00
goto fail ;
}
2006-04-12 10:08:24 +04:00
msg - > server_id = server_id ;
msg - > idr = idr_init ( msg ) ;
2014-03-27 14:08:55 +04:00
if ( msg - > idr = = NULL ) {
goto fail ;
}
2006-04-12 10:08:24 +04:00
msg - > dispatch_tree = idr_init ( msg ) ;
2014-03-27 14:08:55 +04:00
if ( msg - > dispatch_tree = = NULL ) {
goto fail ;
}
2006-04-12 10:08:24 +04:00
msg - > start_time = timeval_current ( ) ;
2004-10-17 14:04:49 +04:00
2015-10-20 12:35:23 +03:00
tdb_flags | = lpcfg_tdb_flags ( lp_ctx , 0 ) ;
2017-03-28 11:55:47 +03:00
/*
* This context holds a destructor that cleans up any names
* registered on this context on talloc_free ( )
*/
2015-10-20 12:35:23 +03:00
msg - > names = server_id_db_init ( msg , server_id , lock_dir , 0 , tdb_flags ) ;
2015-02-04 14:31:24 +03:00
if ( msg - > names = = NULL ) {
2014-03-27 14:16:08 +04:00
goto fail ;
}
2017-03-31 21:07:35 +03:00
status = imessaging_register ( msg , NULL , MSG_PING , ping_message ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
status = imessaging_register ( msg , NULL , MSG_REQ_POOL_USAGE ,
pool_message ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
status = imessaging_register ( msg , NULL , MSG_IRPC , irpc_handler ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
status = imessaging_register ( msg , NULL , MSG_REQ_RINGBUF_LOG ,
ringbuf_log_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2019-01-15 03:39:06 +03:00
status = imessaging_register ( msg , NULL , MSG_DEBUG ,
debug_imessage ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
status = imessaging_register ( msg , NULL , MSG_REQ_DEBUGLEVEL ,
debuglevel_imessage ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2017-03-31 21:07:35 +03:00
status = IRPC_REGISTER ( msg , irpc , IRPC_UPTIME , irpc_uptime , msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2018-12-11 01:04:25 +03:00
# if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
/*
* Register handlers for messages specific to developer and
* self test builds
*/
status = imessaging_register_extra_handlers ( msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
# endif /* defined(DEVELOPER) || defined(ENABLE_SELFTEST) */
2004-10-17 14:04:49 +04:00
2016-09-09 08:12:11 +03:00
DLIST_ADD ( msg_ctxs , msg ) ;
2004-10-17 14:04:49 +04:00
return msg ;
2014-03-27 14:07:34 +04:00
fail :
talloc_free ( msg ) ;
return NULL ;
2004-10-17 14:04:49 +04:00
}
2005-06-05 10:53:07 +04:00
2016-09-29 02:05:25 +03:00
struct imessaging_post_state {
struct imessaging_context * msg_ctx ;
2018-05-19 11:14:25 +03:00
struct imessaging_post_state * * busy_ref ;
2016-09-29 02:05:25 +03:00
size_t buf_len ;
uint8_t buf [ ] ;
} ;
2018-05-19 11:14:25 +03:00
static int imessaging_post_state_destructor ( struct imessaging_post_state * state )
{
if ( state - > busy_ref ! = NULL ) {
* state - > busy_ref = NULL ;
state - > busy_ref = NULL ;
}
return 0 ;
}
2016-09-29 02:05:25 +03:00
static void imessaging_post_handler ( struct tevent_context * ev ,
struct tevent_immediate * ti ,
void * private_data )
{
struct imessaging_post_state * state = talloc_get_type_abort (
private_data , struct imessaging_post_state ) ;
2018-05-19 11:14:25 +03:00
2019-05-08 06:58:08 +03:00
if ( state = = NULL ) {
return ;
}
2018-05-19 11:14:25 +03:00
/*
* In usecases like using messaging_client_init ( ) with irpc processing
* we may free the imessaging_context during the messaging handler .
* imessaging_post_state is a child of imessaging_context and
* might be implicitly free ' ed before the explicit TALLOC_FREE ( state ) .
*
* The busy_ref pointer makes sure the destructor clears
* the local ' state ' variable .
*/
SMB_ASSERT ( state - > busy_ref = = NULL ) ;
state - > busy_ref = & state ;
2016-09-29 02:05:25 +03:00
imessaging_dgm_recv ( ev , state - > buf , state - > buf_len , NULL , 0 ,
state - > msg_ctx ) ;
2018-05-19 11:14:25 +03:00
state - > busy_ref = NULL ;
2016-09-29 02:05:25 +03:00
TALLOC_FREE ( state ) ;
}
static int imessaging_post_self ( struct imessaging_context * msg ,
const uint8_t * buf , size_t buf_len )
{
struct tevent_immediate * ti ;
struct imessaging_post_state * state ;
state = talloc_size (
msg , offsetof ( struct imessaging_post_state , buf ) + buf_len ) ;
if ( state = = NULL ) {
return ENOMEM ;
}
talloc_set_name_const ( state , " struct imessaging_post_state " ) ;
2018-05-19 11:14:25 +03:00
talloc_set_destructor ( state , imessaging_post_state_destructor ) ;
2016-09-29 02:05:25 +03:00
ti = tevent_create_immediate ( state ) ;
if ( ti = = NULL ) {
TALLOC_FREE ( state ) ;
return ENOMEM ;
}
state - > msg_ctx = msg ;
2018-05-19 11:14:25 +03:00
state - > busy_ref = NULL ;
2016-09-29 02:05:25 +03:00
state - > buf_len = buf_len ;
memcpy ( state - > buf , buf , buf_len ) ;
tevent_schedule_immediate ( ti , msg - > ev , imessaging_post_handler ,
state ) ;
return 0 ;
}
2016-09-24 04:36:15 +03:00
static void imessaging_dgm_recv ( struct tevent_context * ev ,
const uint8_t * buf , size_t buf_len ,
2015-02-08 17:33:39 +03:00
int * fds , size_t num_fds ,
void * private_data )
{
struct imessaging_context * msg = talloc_get_type_abort (
private_data , struct imessaging_context ) ;
uint32_t msg_type ;
struct server_id src , dst ;
struct server_id_buf srcbuf , dstbuf ;
DATA_BLOB data ;
if ( buf_len < MESSAGE_HDR_LENGTH ) {
/* Invalid message, ignore */
return ;
}
2016-09-29 02:05:25 +03:00
if ( ev ! = msg - > ev ) {
int ret ;
ret = imessaging_post_self ( msg , buf , buf_len ) ;
if ( ret ! = 0 ) {
DBG_WARNING ( " imessaging_post_self failed: %s \n " ,
strerror ( ret ) ) ;
}
return ;
}
2015-02-08 17:33:39 +03:00
message_hdr_get ( & msg_type , & src , & dst , buf ) ;
data . data = discard_const_p ( uint8_t , buf + MESSAGE_HDR_LENGTH ) ;
data . length = buf_len - MESSAGE_HDR_LENGTH ;
if ( ( cluster_id_equal ( & dst , & msg - > server_id ) ) | |
( ( dst . task_id = = 0 ) & & ( msg - > server_id . pid = = 0 ) ) ) {
struct dispatch_fn * d , * next ;
DEBUG ( 10 , ( " %s: dst %s matches my id: %s, type=0x%x \n " ,
__func__ ,
server_id_str_buf ( dst , & dstbuf ) ,
server_id_str_buf ( msg - > server_id , & srcbuf ) ,
( unsigned ) msg_type ) ) ;
d = imessaging_find_dispatch ( msg , msg_type ) ;
for ( ; d ; d = next ) {
next = d - > next ;
2019-09-18 19:19:37 +03:00
d - > fn ( msg ,
d - > private_data ,
d - > msg_type ,
src ,
num_fds ,
fds ,
& data ) ;
2015-02-08 17:33:39 +03:00
}
} else {
DEBUG ( 10 , ( " %s: Ignoring type=0x%x dst %s, I am %s, \n " ,
__func__ , ( unsigned ) msg_type ,
server_id_str_buf ( dst , & dstbuf ) ,
server_id_str_buf ( msg - > server_id , & srcbuf ) ) ) ;
}
}
2014-03-26 17:08:13 +04:00
/*
A hack , for the short term until we get ' client only ' messaging in place
2006-02-04 01:30:30 +03:00
*/
2011-05-03 04:40:33 +04:00
struct imessaging_context * imessaging_client_init ( TALLOC_CTX * mem_ctx ,
2011-10-13 13:01:56 +04:00
struct loadparm_context * lp_ctx ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev )
2006-02-04 01:30:30 +03:00
{
2007-01-10 13:52:09 +03:00
struct server_id id ;
ZERO_STRUCT ( id ) ;
2012-04-30 09:44:01 +04:00
id . pid = getpid ( ) ;
id . task_id = generate_random ( ) ;
id . vnn = NONCLUSTER_VNN ;
/* This is because we are not in the s3 serverid database */
id . unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY ;
2012-04-25 11:53:18 +04:00
2018-12-27 14:41:25 +03:00
return imessaging_init ( mem_ctx , lp_ctx , id , ev ) ;
2006-02-04 01:30:30 +03:00
}
2005-06-05 10:53:07 +04:00
/*
a list of registered irpc server functions
*/
struct irpc_list {
struct irpc_list * next , * prev ;
struct GUID uuid ;
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ;
2005-06-05 10:53:07 +04:00
int callnum ;
irpc_function_t fn ;
2009-02-01 01:57:02 +03:00
void * private_data ;
2005-06-05 10:53:07 +04:00
} ;
/*
register a irpc server function
*/
2011-05-03 04:40:33 +04:00
NTSTATUS irpc_register ( struct imessaging_context * msg_ctx ,
2014-03-26 17:08:13 +04:00
const struct ndr_interface_table * table ,
2009-02-01 01:57:02 +03:00
int callnum , irpc_function_t fn , void * private_data )
2005-06-05 10:53:07 +04:00
{
struct irpc_list * irpc ;
2005-06-05 11:30:44 +04:00
/* override an existing handler, if any */
for ( irpc = msg_ctx - > irpc ; irpc ; irpc = irpc - > next ) {
if ( irpc - > table = = table & & irpc - > callnum = = callnum ) {
break ;
}
}
if ( irpc = = NULL ) {
irpc = talloc ( msg_ctx , struct irpc_list ) ;
NT_STATUS_HAVE_NO_MEMORY ( irpc ) ;
DLIST_ADD ( msg_ctx - > irpc , irpc ) ;
}
2005-06-05 10:53:07 +04:00
irpc - > table = table ;
2005-06-05 11:30:44 +04:00
irpc - > callnum = callnum ;
2005-06-05 10:53:07 +04:00
irpc - > fn = fn ;
2009-02-01 01:57:02 +03:00
irpc - > private_data = private_data ;
2006-03-26 04:59:17 +04:00
irpc - > uuid = irpc - > table - > syntax_id . uuid ;
2005-06-05 10:53:07 +04:00
return NT_STATUS_OK ;
}
/*
handle an incoming irpc reply message
*/
2011-05-03 04:40:33 +04:00
static void irpc_handler_reply ( struct imessaging_context * msg_ctx , struct irpc_message * m )
2005-06-05 10:53:07 +04:00
{
struct irpc_request * irpc ;
2007-09-09 23:34:30 +04:00
irpc = ( struct irpc_request * ) idr_find ( msg_ctx - > idr , m - > header . callid ) ;
2005-06-05 10:53:07 +04:00
if ( irpc = = NULL ) return ;
2010-09-03 18:05:38 +04:00
irpc - > incoming . handler ( irpc , m ) ;
2005-06-05 10:53:07 +04:00
}
2005-09-25 17:01:26 +04:00
/*
send a irpc reply
*/
2005-09-25 17:17:03 +04:00
NTSTATUS irpc_send_reply ( struct irpc_message * m , NTSTATUS status )
2005-09-25 17:01:26 +04:00
{
struct ndr_push * push ;
DATA_BLOB packet ;
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-09-25 17:01:26 +04:00
2005-09-25 17:17:03 +04:00
m - > header . status = status ;
2005-09-25 17:01:26 +04:00
/* setup the reply */
2010-05-09 19:20:01 +04:00
push = ndr_push_init_ctx ( m - > ndr ) ;
2005-09-25 17:01:26 +04:00
if ( push = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto failed ;
}
m - > header . flags | = IRPC_FLAG_REPLY ;
2010-09-27 03:42:26 +04:00
m - > header . creds . token = NULL ;
2005-09-25 17:01:26 +04:00
/* construct the packet */
2007-11-09 21:24:51 +03:00
ndr_err = ndr_push_irpc_header ( push , NDR_SCALARS | NDR_BUFFERS , & m - > header ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
goto failed ;
}
2005-09-25 17:01:26 +04:00
2007-11-09 21:24:51 +03:00
ndr_err = m - > irpc - > table - > calls [ m - > irpc - > callnum ] . ndr_push ( push , NDR_OUT , m - > data ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
goto failed ;
}
2005-09-25 17:01:26 +04:00
/* send the reply message */
packet = ndr_push_blob ( push ) ;
2011-05-03 04:40:33 +04:00
status = imessaging_send ( m - > msg_ctx , m - > from , MSG_IRPC , & packet ) ;
2005-09-25 17:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
failed :
talloc_free ( m ) ;
return status ;
}
2005-06-05 10:53:07 +04:00
/*
handle an incoming irpc request message
*/
2011-05-03 04:40:33 +04:00
static void irpc_handler_request ( struct imessaging_context * msg_ctx ,
2005-09-25 17:01:26 +04:00
struct irpc_message * m )
2005-06-05 10:53:07 +04:00
{
struct irpc_list * i ;
void * r ;
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-06-05 10:53:07 +04:00
for ( i = msg_ctx - > irpc ; i ; i = i - > next ) {
2005-09-25 17:01:26 +04:00
if ( GUID_equal ( & i - > uuid , & m - > header . uuid ) & &
2006-03-26 04:59:17 +04:00
i - > table - > syntax_id . if_version = = m - > header . if_version & &
2005-09-25 17:01:26 +04:00
i - > callnum = = m - > header . callnum ) {
2005-06-05 10:53:07 +04:00
break ;
}
}
if ( i = = NULL ) {
/* no registered handler for this message */
2005-09-25 17:01:26 +04:00
talloc_free ( m ) ;
2005-06-05 10:53:07 +04:00
return ;
}
/* allocate space for the structure */
2005-09-25 17:01:26 +04:00
r = talloc_zero_size ( m - > ndr , i - > table - > calls [ m - > header . callnum ] . struct_size ) ;
2005-06-05 10:53:07 +04:00
if ( r = = NULL ) goto failed ;
2010-09-23 06:04:58 +04:00
m - > ndr - > flags | = LIBNDR_FLAG_REF_ALLOC ;
2005-06-05 10:53:07 +04:00
/* parse the request data */
2007-11-09 21:24:51 +03:00
ndr_err = i - > table - > calls [ i - > callnum ] . ndr_pull ( m - > ndr , NDR_IN , r ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) goto failed ;
2005-06-05 10:53:07 +04:00
/* make the call */
2009-02-01 02:03:47 +03:00
m - > private_data = i - > private_data ;
2007-08-27 22:43:18 +04:00
m - > defer_reply = false ;
2010-09-12 04:02:02 +04:00
m - > no_reply = false ;
2005-09-25 17:01:26 +04:00
m - > msg_ctx = msg_ctx ;
m - > irpc = i ;
m - > data = r ;
2005-06-05 10:53:07 +04:00
2005-09-25 17:01:26 +04:00
m - > header . status = i - > fn ( m , r ) ;
2005-06-05 10:53:07 +04:00
2010-09-12 04:02:02 +04:00
if ( m - > no_reply ) {
/* the server function won't ever be replying to this request */
talloc_free ( m ) ;
return ;
}
2005-09-25 17:01:26 +04:00
if ( m - > defer_reply ) {
/* the server function has asked to defer the reply to later */
talloc_steal ( msg_ctx , m ) ;
return ;
}
2005-06-05 10:53:07 +04:00
2005-09-25 17:17:03 +04:00
irpc_send_reply ( m , m - > header . status ) ;
2005-09-25 17:01:26 +04:00
return ;
2005-06-05 10:53:07 +04:00
failed :
2005-09-25 17:01:26 +04:00
talloc_free ( m ) ;
2005-06-05 10:53:07 +04:00
}
/*
handle an incoming irpc message
*/
2019-09-18 19:19:37 +03:00
static void irpc_handler ( struct imessaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
size_t num_fds ,
int * fds ,
DATA_BLOB * packet )
2005-06-05 10:53:07 +04:00
{
2005-09-25 17:01:26 +04:00
struct irpc_message * m ;
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-06-05 10:53:07 +04:00
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2005-09-25 17:01:26 +04:00
m = talloc ( msg_ctx , struct irpc_message ) ;
if ( m = = NULL ) goto failed ;
m - > from = src ;
2005-06-05 10:53:07 +04:00
2010-05-09 19:20:01 +04:00
m - > ndr = ndr_pull_init_blob ( packet , m ) ;
2005-09-25 17:01:26 +04:00
if ( m - > ndr = = NULL ) goto failed ;
2005-07-19 13:28:13 +04:00
2005-09-25 17:01:26 +04:00
m - > ndr - > flags | = LIBNDR_FLAG_REF_ALLOC ;
2007-11-09 21:24:51 +03:00
ndr_err = ndr_pull_irpc_header ( m - > ndr , NDR_BUFFERS | NDR_SCALARS , & m - > header ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) goto failed ;
2005-06-05 10:53:07 +04:00
2005-09-25 17:01:26 +04:00
if ( m - > header . flags & IRPC_FLAG_REPLY ) {
irpc_handler_reply ( msg_ctx , m ) ;
2005-06-05 10:53:07 +04:00
} else {
2005-09-25 17:01:26 +04:00
irpc_handler_request ( msg_ctx , m ) ;
2005-06-05 10:53:07 +04:00
}
2005-07-10 12:35:18 +04:00
return ;
2005-06-05 10:53:07 +04:00
failed :
2005-09-25 17:01:26 +04:00
talloc_free ( m ) ;
2005-06-05 10:53:07 +04:00
}
/*
destroy a irpc request
*/
2006-05-24 11:34:11 +04:00
static int irpc_destructor ( struct irpc_request * irpc )
2005-06-05 10:53:07 +04:00
{
2007-05-01 13:55:36 +04:00
if ( irpc - > callid ! = - 1 ) {
idr_remove ( irpc - > msg_ctx - > idr , irpc - > callid ) ;
irpc - > callid = - 1 ;
}
2005-06-05 10:53:07 +04:00
return 0 ;
}
2005-07-10 05:08:10 +04:00
/*
add a string name that this irpc server can be called on
2017-03-28 11:55:47 +03:00
It will be removed from the DB either via irpc_remove_name or on
talloc_free ( msg_ctx - > names ) .
2005-07-10 05:08:10 +04:00
*/
2011-05-03 04:40:33 +04:00
NTSTATUS irpc_add_name ( struct imessaging_context * msg_ctx , const char * name )
2005-07-10 05:08:10 +04:00
{
2014-07-17 18:07:45 +04:00
int ret ;
2005-07-10 08:54:21 +04:00
2015-02-04 14:31:24 +03:00
ret = server_id_db_add ( msg_ctx - > names , name ) ;
2014-07-17 18:07:45 +04:00
if ( ret ! = 0 ) {
2015-02-04 14:31:24 +03:00
return map_nt_error_from_unix_common ( ret ) ;
2005-07-10 08:54:21 +04:00
}
2014-07-17 18:11:35 +04:00
return NT_STATUS_OK ;
2005-07-10 05:08:10 +04:00
}
2015-02-04 14:31:24 +03:00
static int all_servers_func ( const char * name , unsigned num_servers ,
const struct server_id * servers ,
void * private_data )
2012-10-29 08:32:21 +04:00
{
2015-02-04 14:31:24 +03:00
struct irpc_name_records * name_records = talloc_get_type (
private_data , struct irpc_name_records ) ;
2012-10-29 08:32:21 +04:00
struct irpc_name_record * name_record ;
2016-09-24 04:43:04 +03:00
uint32_t i ;
2012-10-29 08:32:21 +04:00
name_records - > names
= talloc_realloc ( name_records , name_records - > names ,
struct irpc_name_record * , name_records - > num_records + 1 ) ;
if ( ! name_records - > names ) {
return - 1 ;
}
name_records - > names [ name_records - > num_records ] = name_record
= talloc ( name_records - > names ,
struct irpc_name_record ) ;
if ( ! name_record ) {
return - 1 ;
}
name_records - > num_records + + ;
2015-02-04 14:31:24 +03:00
name_record - > name = talloc_strdup ( name_record , name ) ;
2012-10-29 08:32:21 +04:00
if ( ! name_record - > name ) {
return - 1 ;
}
2015-02-04 14:31:24 +03:00
name_record - > count = num_servers ;
name_record - > ids = talloc_array ( name_record , struct server_id ,
num_servers ) ;
2012-10-29 08:32:21 +04:00
if ( name_record - > ids = = NULL ) {
return - 1 ;
}
for ( i = 0 ; i < name_record - > count ; i + + ) {
2015-02-04 14:31:24 +03:00
name_record - > ids [ i ] = servers [ i ] ;
2012-10-29 08:32:21 +04:00
}
return 0 ;
}
/*
return a list of server ids for a server name
*/
struct irpc_name_records * irpc_all_servers ( struct imessaging_context * msg_ctx ,
TALLOC_CTX * mem_ctx )
{
int ret ;
struct irpc_name_records * name_records = talloc_zero ( mem_ctx , struct irpc_name_records ) ;
if ( name_records = = NULL ) {
return NULL ;
}
2015-02-04 14:31:24 +03:00
ret = server_id_db_traverse_read ( msg_ctx - > names , all_servers_func ,
name_records ) ;
2012-10-29 08:32:21 +04:00
if ( ret = = - 1 ) {
2014-09-14 16:33:53 +04:00
TALLOC_FREE ( name_records ) ;
2012-10-29 08:32:21 +04:00
return NULL ;
}
return name_records ;
}
2005-07-10 08:54:21 +04:00
/*
remove a name from a messaging context
*/
2011-05-03 04:40:33 +04:00
void irpc_remove_name ( struct imessaging_context * msg_ctx , const char * name )
2005-07-10 08:54:21 +04:00
{
2015-02-04 14:31:24 +03:00
server_id_db_remove ( msg_ctx - > names , name ) ;
2005-07-10 08:54:21 +04:00
}
2008-05-26 03:52:35 +04:00
2011-05-03 04:40:33 +04:00
struct server_id imessaging_get_server_id ( struct imessaging_context * msg_ctx )
2008-05-26 03:52:35 +04:00
{
return msg_ctx - > server_id ;
}
2010-08-30 15:44:01 +04:00
struct irpc_bh_state {
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg_ctx ;
2010-08-30 15:44:01 +04:00
struct server_id server_id ;
const struct ndr_interface_table * table ;
2010-09-03 21:52:59 +04:00
uint32_t timeout ;
2010-09-27 03:42:26 +04:00
struct security_token * token ;
2010-08-30 15:44:01 +04:00
} ;
static bool irpc_bh_is_connected ( struct dcerpc_binding_handle * h )
{
struct irpc_bh_state * hs = dcerpc_binding_handle_data ( h ,
struct irpc_bh_state ) ;
if ( ! hs - > msg_ctx ) {
return false ;
}
return true ;
}
2010-09-03 21:52:59 +04:00
static uint32_t irpc_bh_set_timeout ( struct dcerpc_binding_handle * h ,
uint32_t timeout )
{
struct irpc_bh_state * hs = dcerpc_binding_handle_data ( h ,
struct irpc_bh_state ) ;
uint32_t old = hs - > timeout ;
hs - > timeout = timeout ;
return old ;
}
2010-08-30 15:44:01 +04:00
struct irpc_bh_raw_call_state {
struct irpc_request * irpc ;
uint32_t opnum ;
DATA_BLOB in_data ;
DATA_BLOB in_packet ;
DATA_BLOB out_data ;
} ;
static void irpc_bh_raw_call_incoming_handler ( struct irpc_request * irpc ,
struct irpc_message * m ) ;
static struct tevent_req * irpc_bh_raw_call_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * h ,
const struct GUID * object ,
uint32_t opnum ,
uint32_t in_flags ,
const uint8_t * in_data ,
size_t in_length )
{
struct irpc_bh_state * hs =
dcerpc_binding_handle_data ( h ,
struct irpc_bh_state ) ;
struct tevent_req * req ;
struct irpc_bh_raw_call_state * state ;
bool ok ;
struct irpc_header header ;
struct ndr_push * ndr ;
NTSTATUS status ;
enum ndr_err_code ndr_err ;
req = tevent_req_create ( mem_ctx , & state ,
struct irpc_bh_raw_call_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > opnum = opnum ;
state - > in_data . data = discard_const_p ( uint8_t , in_data ) ;
state - > in_data . length = in_length ;
ok = irpc_bh_is_connected ( h ) ;
if ( ! ok ) {
2011-09-14 19:57:37 +04:00
tevent_req_nterror ( req , NT_STATUS_CONNECTION_DISCONNECTED ) ;
2010-08-30 15:44:01 +04:00
return tevent_req_post ( req , ev ) ;
}
state - > irpc = talloc_zero ( state , struct irpc_request ) ;
if ( tevent_req_nomem ( state - > irpc , req ) ) {
return tevent_req_post ( req , ev ) ;
}
state - > irpc - > msg_ctx = hs - > msg_ctx ;
state - > irpc - > callid = idr_get_new ( hs - > msg_ctx - > idr ,
state - > irpc , UINT16_MAX ) ;
if ( state - > irpc - > callid = = - 1 ) {
tevent_req_nterror ( req , NT_STATUS_INSUFFICIENT_RESOURCES ) ;
return tevent_req_post ( req , ev ) ;
}
state - > irpc - > incoming . handler = irpc_bh_raw_call_incoming_handler ;
state - > irpc - > incoming . private_data = req ;
talloc_set_destructor ( state - > irpc , irpc_destructor ) ;
/* setup the header */
header . uuid = hs - > table - > syntax_id . uuid ;
header . if_version = hs - > table - > syntax_id . if_version ;
header . callid = state - > irpc - > callid ;
header . callnum = state - > opnum ;
header . flags = 0 ;
header . status = NT_STATUS_OK ;
2010-09-27 03:42:26 +04:00
header . creds . token = hs - > token ;
2010-08-30 15:44:01 +04:00
/* construct the irpc packet */
ndr = ndr_push_init_ctx ( state - > irpc ) ;
if ( tevent_req_nomem ( ndr , req ) ) {
return tevent_req_post ( req , ev ) ;
}
ndr_err = ndr_push_irpc_header ( ndr , NDR_SCALARS | NDR_BUFFERS , & header ) ;
status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
ndr_err = ndr_push_bytes ( ndr , in_data , in_length ) ;
status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
/* and send it */
state - > in_packet = ndr_push_blob ( ndr ) ;
2011-05-03 04:40:33 +04:00
status = imessaging_send ( hs - > msg_ctx , hs - > server_id ,
2010-08-30 15:44:01 +04:00
MSG_IRPC , & state - > in_packet ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
2010-09-15 17:53:48 +04:00
if ( hs - > timeout ! = IRPC_CALL_TIMEOUT_INF ) {
/* set timeout-callback in case caller wants that */
ok = tevent_req_set_endtime ( req , ev , timeval_current_ofs ( hs - > timeout , 0 ) ) ;
if ( ! ok ) {
return tevent_req_post ( req , ev ) ;
}
2010-09-03 21:52:59 +04:00
}
2010-08-30 15:44:01 +04:00
return req ;
}
static void irpc_bh_raw_call_incoming_handler ( struct irpc_request * irpc ,
struct irpc_message * m )
{
struct tevent_req * req =
talloc_get_type_abort ( irpc - > incoming . private_data ,
struct tevent_req ) ;
struct irpc_bh_raw_call_state * state =
tevent_req_data ( req ,
struct irpc_bh_raw_call_state ) ;
talloc_steal ( state , m ) ;
if ( ! NT_STATUS_IS_OK ( m - > header . status ) ) {
tevent_req_nterror ( req , m - > header . status ) ;
return ;
}
state - > out_data = data_blob_talloc ( state ,
m - > ndr - > data + m - > ndr - > offset ,
m - > ndr - > data_size - m - > ndr - > offset ) ;
if ( ( m - > ndr - > data_size - m - > ndr - > offset ) > 0 & & ! state - > out_data . data ) {
2011-06-19 23:10:01 +04:00
tevent_req_oom ( req ) ;
2010-08-30 15:44:01 +04:00
return ;
}
tevent_req_done ( req ) ;
}
static NTSTATUS irpc_bh_raw_call_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
uint8_t * * out_data ,
size_t * out_length ,
uint32_t * out_flags )
{
struct irpc_bh_raw_call_state * state =
tevent_req_data ( req ,
struct irpc_bh_raw_call_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
* out_data = talloc_move ( mem_ctx , & state - > out_data . data ) ;
* out_length = state - > out_data . length ;
* out_flags = 0 ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
struct irpc_bh_disconnect_state {
uint8_t _dummy ;
} ;
static struct tevent_req * irpc_bh_disconnect_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * h )
{
struct irpc_bh_state * hs = dcerpc_binding_handle_data ( h ,
struct irpc_bh_state ) ;
struct tevent_req * req ;
struct irpc_bh_disconnect_state * state ;
bool ok ;
req = tevent_req_create ( mem_ctx , & state ,
struct irpc_bh_disconnect_state ) ;
if ( req = = NULL ) {
return NULL ;
}
ok = irpc_bh_is_connected ( h ) ;
if ( ! ok ) {
2011-09-14 19:57:37 +04:00
tevent_req_nterror ( req , NT_STATUS_CONNECTION_DISCONNECTED ) ;
2010-08-30 15:44:01 +04:00
return tevent_req_post ( req , ev ) ;
}
hs - > msg_ctx = NULL ;
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static NTSTATUS irpc_bh_disconnect_recv ( struct tevent_req * req )
{
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
static bool irpc_bh_ref_alloc ( struct dcerpc_binding_handle * h )
{
return true ;
}
static const struct dcerpc_binding_handle_ops irpc_bh_ops = {
. name = " wbint " ,
. is_connected = irpc_bh_is_connected ,
2010-09-03 21:52:59 +04:00
. set_timeout = irpc_bh_set_timeout ,
2010-08-30 15:44:01 +04:00
. raw_call_send = irpc_bh_raw_call_send ,
. raw_call_recv = irpc_bh_raw_call_recv ,
. disconnect_send = irpc_bh_disconnect_send ,
. disconnect_recv = irpc_bh_disconnect_recv ,
. ref_alloc = irpc_bh_ref_alloc ,
} ;
/* initialise a irpc binding handle */
struct dcerpc_binding_handle * irpc_binding_handle ( TALLOC_CTX * mem_ctx ,
2014-05-05 08:27:59 +04:00
struct imessaging_context * msg_ctx ,
struct server_id server_id ,
const struct ndr_interface_table * table )
2010-08-30 15:44:01 +04:00
{
struct dcerpc_binding_handle * h ;
struct irpc_bh_state * hs ;
h = dcerpc_binding_handle_create ( mem_ctx ,
& irpc_bh_ops ,
NULL ,
table ,
& hs ,
struct irpc_bh_state ,
__location__ ) ;
if ( h = = NULL ) {
return NULL ;
}
hs - > msg_ctx = msg_ctx ;
hs - > server_id = server_id ;
hs - > table = table ;
2010-09-03 21:52:59 +04:00
hs - > timeout = IRPC_CALL_TIMEOUT ;
2010-08-30 15:44:01 +04:00
return h ;
}
2010-08-30 15:44:41 +04:00
struct dcerpc_binding_handle * irpc_binding_handle_by_name ( TALLOC_CTX * mem_ctx ,
2014-05-05 08:27:59 +04:00
struct imessaging_context * msg_ctx ,
const char * dest_task ,
const struct ndr_interface_table * table )
2010-08-30 15:44:41 +04:00
{
struct dcerpc_binding_handle * h ;
2014-07-17 19:05:30 +04:00
unsigned num_sids ;
2010-08-30 15:44:41 +04:00
struct server_id * sids ;
struct server_id sid ;
2014-07-17 19:05:30 +04:00
NTSTATUS status ;
2010-08-30 15:44:41 +04:00
/* find the server task */
2014-07-17 19:05:30 +04:00
status = irpc_servers_byname ( msg_ctx , mem_ctx , dest_task ,
& num_sids , & sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-30 15:44:41 +04:00
errno = EADDRNOTAVAIL ;
return NULL ;
}
sid = sids [ 0 ] ;
talloc_free ( sids ) ;
h = irpc_binding_handle ( mem_ctx , msg_ctx ,
sid , table ) ;
if ( h = = NULL ) {
return NULL ;
}
return h ;
}
2010-09-27 04:04:43 +04:00
void irpc_binding_handle_add_security_token ( struct dcerpc_binding_handle * h ,
struct security_token * token )
{
struct irpc_bh_state * hs =
dcerpc_binding_handle_data ( h ,
struct irpc_bh_state ) ;
hs - > token = token ;
}