2007-06-10 21:02:09 +04:00
/*
Unix SMB / CIFS implementation .
Samba internal messaging functions
Copyright ( C ) 2007 by Volker Lendecke
2011-06-25 17:14:25 +04:00
2007-06-10 21:02:09 +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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2007-06-10 21:02:09 +04:00
( at your option ) any later version .
2011-06-25 17:14:25 +04:00
2007-06-10 21:02:09 +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 .
2011-06-25 17:14:25 +04:00
2007-06-10 21:02:09 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2007-06-10 21:02:09 +04:00
*/
# include "includes.h"
2017-06-01 20:25:48 +03:00
# include "lib/messages_ctdbd.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2015-02-14 18:48:54 +03:00
# include "lib/util/iov_buf.h"
2015-05-25 20:59:22 +03:00
# include "lib/messages_util.h"
2008-01-16 12:09:48 +03:00
# include "ctdbd_conn.h"
2015-10-01 13:28:21 +03:00
# include "lib/cluster_support.h"
2008-01-16 12:09:48 +03:00
2017-06-08 13:51:29 +03:00
struct messaging_ctdbd_context ;
struct messaging_ctdbd_fde_ev {
struct messaging_ctdbd_fde_ev * prev , * next ;
/*
* Backreference to enable DLIST_REMOVE from our
* destructor . Also , set to NULL when the dgm_context dies
* before the messaging_dgm_fde_ev .
*/
struct messaging_ctdbd_context * ctx ;
struct tevent_context * ev ;
struct tevent_fd * fde ;
} ;
2007-06-10 21:02:09 +04:00
struct messaging_ctdbd_context {
struct ctdbd_connection * conn ;
2017-06-08 13:51:29 +03:00
struct messaging_ctdbd_fde_ev * fde_evs ;
2017-06-01 19:58:16 +03:00
void ( * recv_cb ) ( struct tevent_context * ev ,
const uint8_t * msg , size_t msg_len ,
int * fds , size_t num_fds ,
void * private_data ) ;
void * private_data ;
2007-06-10 21:02:09 +04:00
} ;
/*
* This is a Samba3 hack / optimization . Routines like process_exists need to
* talk to ctdbd , and they don ' t get handed a messaging context .
*/
2008-04-15 03:18:06 +04:00
static struct ctdbd_connection * global_ctdbd_connection ;
static int global_ctdb_connection_pid ;
2007-06-10 21:02:09 +04:00
2010-08-31 18:52:56 +04:00
struct ctdbd_connection * messaging_ctdbd_connection ( void )
2007-06-10 21:02:09 +04:00
{
2012-04-04 13:27:08 +04:00
if ( ! lp_clustering ( ) ) {
return NULL ;
}
2008-04-15 03:18:50 +04:00
if ( global_ctdb_connection_pid = = 0 & &
global_ctdbd_connection = = NULL ) {
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ;
2008-04-15 03:18:50 +04:00
struct messaging_context * msg ;
2013-02-18 12:10:34 +04:00
ev = samba_tevent_context_init ( NULL ) ;
2008-04-19 19:04:46 +04:00
if ( ! ev ) {
2013-02-18 12:10:34 +04:00
DEBUG ( 0 , ( " samba_tevent_context_init failed \n " ) ) ;
2015-06-23 12:06:02 +03:00
return NULL ;
2008-04-15 03:18:50 +04:00
}
2011-12-12 17:55:54 +04:00
msg = messaging_init ( NULL , ev ) ;
2008-04-15 03:18:50 +04:00
if ( ! msg ) {
DEBUG ( 0 , ( " messaging_init failed \n " ) ) ;
2008-06-13 14:01:31 +04:00
return NULL ;
2008-04-15 03:18:50 +04:00
}
}
2008-04-15 03:18:06 +04:00
if ( global_ctdb_connection_pid ! = getpid ( ) ) {
DEBUG ( 0 , ( " messaging_ctdbd_connection(): "
2014-10-05 19:44:08 +04:00
" valid for pid[%jd] but it's [%jd] \n " ,
( intmax_t ) global_ctdb_connection_pid ,
( intmax_t ) getpid ( ) ) ) ;
2008-04-15 03:18:06 +04:00
smb_panic ( " messaging_ctdbd_connection() invalid process \n " ) ;
}
2007-06-10 21:02:09 +04:00
return global_ctdbd_connection ;
}
2014-06-04 18:36:57 +04:00
static int messaging_ctdb_send ( struct server_id src ,
struct server_id pid , int msg_type ,
const struct iovec * iov , int iovlen ,
2014-05-17 17:16:02 +04:00
const int * fds , size_t num_fds ,
2014-06-04 18:36:57 +04:00
struct messaging_backend * backend )
2007-06-10 21:02:09 +04:00
{
struct messaging_ctdbd_context * ctx = talloc_get_type_abort (
backend - > private_data , struct messaging_ctdbd_context ) ;
2015-05-25 20:59:22 +03:00
uint8_t hdr [ MESSAGE_HDR_LENGTH ] ;
struct iovec iov2 [ iovlen + 1 ] ;
2014-05-13 13:55:37 +04:00
2014-05-17 17:16:02 +04:00
if ( num_fds > 0 ) {
return ENOSYS ;
}
2015-05-25 20:59:22 +03:00
message_hdr_put ( hdr , msg_type , src , pid ) ;
iov2 [ 0 ] = ( struct iovec ) { . iov_base = hdr , . iov_len = sizeof ( hdr ) } ;
memcpy ( & iov2 [ 1 ] , iov , iovlen * sizeof ( * iov ) ) ;
2015-05-25 09:50:35 +03:00
2015-10-03 06:42:05 +03:00
return ctdbd_messaging_send_iov ( ctx - > conn , pid . vnn , pid . pid ,
iov2 , iovlen + 1 ) ;
2007-06-10 21:02:09 +04:00
}
static int messaging_ctdbd_destructor ( struct messaging_ctdbd_context * ctx )
{
/*
* The global connection just went away
*/
2008-04-15 03:18:06 +04:00
global_ctdb_connection_pid = 0 ;
2007-06-10 21:02:09 +04:00
global_ctdbd_connection = NULL ;
return 0 ;
}
2015-06-23 17:55:09 +03:00
static int messaging_ctdb_recv (
2017-06-01 18:45:47 +03:00
struct tevent_context * ev ,
2015-06-02 23:30:06 +03:00
uint32_t src_vnn , uint32_t dst_vnn , uint64_t dst_srvid ,
const uint8_t * msg , size_t msg_len , void * private_data )
2015-05-19 17:55:32 +03:00
{
2017-06-01 19:58:16 +03:00
struct messaging_ctdbd_context * ctx = talloc_get_type_abort (
private_data , struct messaging_ctdbd_context ) ;
2015-05-19 17:55:32 +03:00
2017-06-01 19:58:16 +03:00
ctx - > recv_cb ( ev , msg , msg_len , NULL , 0 , ctx - > private_data ) ;
2015-06-23 17:55:09 +03:00
return 0 ;
2015-05-19 17:55:32 +03:00
}
2016-04-24 18:37:33 +03:00
static void messaging_ctdbd_readable ( struct tevent_context * ev ,
struct tevent_fd * fde ,
uint16_t flags ,
void * private_data )
{
struct ctdbd_connection * conn = talloc_get_type_abort (
private_data , struct ctdbd_connection ) ;
if ( ( flags & TEVENT_FD_READ ) = = 0 ) {
return ;
}
2017-06-01 19:00:45 +03:00
ctdbd_socket_readable ( ev , conn ) ;
2016-04-24 18:37:33 +03:00
}
2017-06-01 19:58:16 +03:00
static int messaging_ctdbd_init_internal (
struct messaging_context * msg_ctx , TALLOC_CTX * mem_ctx ,
struct messaging_ctdbd_context * ctx ,
void ( * recv_cb ) ( struct tevent_context * ev ,
const uint8_t * msg , size_t msg_len ,
int * fds , size_t num_fds ,
void * private_data ) ,
void * private_data ,
bool reinit )
2007-06-10 21:02:09 +04:00
{
2017-06-08 13:51:29 +03:00
int ret ;
2007-06-10 21:02:09 +04:00
2016-07-09 14:20:01 +03:00
if ( reinit ) {
ret = ctdbd_reinit_connection ( ctx ,
lp_ctdbd_socket ( ) ,
lp_ctdb_timeout ( ) ,
ctx - > conn ) ;
if ( ret ! = 0 ) {
DBG_ERR ( " ctdbd_reinit_connection failed: %s \n " ,
strerror ( ret ) ) ;
return ret ;
}
} else {
ret = ctdbd_init_connection ( ctx ,
lp_ctdbd_socket ( ) ,
lp_ctdb_timeout ( ) ,
& ctx - > conn ) ;
if ( ret ! = 0 ) {
DBG_ERR ( " ctdbd_init_connection failed: %s \n " ,
strerror ( ret ) ) ;
return ret ;
}
2016-04-05 11:11:44 +03:00
}
ret = register_with_ctdbd ( ctx - > conn , MSG_SRVID_SAMBA , NULL , NULL ) ;
if ( ret ! = 0 ) {
DBG_DEBUG ( " Could not register MSG_SRVID_SAMBA: %s \n " ,
strerror ( ret ) ) ;
2015-10-03 06:42:05 +03:00
return ret ;
2007-06-10 21:02:09 +04:00
}
2017-06-01 19:58:16 +03:00
ctx - > recv_cb = recv_cb ;
ctx - > private_data = private_data ;
2015-10-03 06:42:05 +03:00
ret = register_with_ctdbd ( ctx - > conn , getpid ( ) ,
2017-06-01 19:58:16 +03:00
messaging_ctdb_recv , ctx ) ;
2015-10-03 06:42:05 +03:00
if ( ret ! = 0 ) {
DEBUG ( 10 , ( " register_with_ctdbd failed: %s \n " ,
strerror ( ret ) ) ) ;
2015-10-03 06:42:05 +03:00
return ret ;
2015-10-03 06:42:05 +03:00
}
2015-05-19 17:55:32 +03:00
2008-04-15 03:18:06 +04:00
global_ctdb_connection_pid = getpid ( ) ;
2007-06-10 21:02:09 +04:00
global_ctdbd_connection = ctx - > conn ;
talloc_set_destructor ( ctx , messaging_ctdbd_destructor ) ;
set_my_vnn ( ctdbd_vnn ( ctx - > conn ) ) ;
2016-07-09 14:20:01 +03:00
return 0 ;
}
int messaging_ctdbd_init ( struct messaging_context * msg_ctx ,
TALLOC_CTX * mem_ctx ,
2017-06-01 19:58:16 +03:00
void ( * recv_cb ) ( struct tevent_context * ev ,
const uint8_t * msg , size_t msg_len ,
int * fds , size_t num_fds ,
void * private_data ) ,
void * private_data ,
2016-07-09 14:20:01 +03:00
struct messaging_backend * * presult )
{
struct messaging_backend * result ;
struct messaging_ctdbd_context * ctx ;
int ret ;
if ( ! ( result = talloc ( mem_ctx , struct messaging_backend ) ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return ENOMEM ;
}
2017-06-08 13:51:29 +03:00
if ( ! ( ctx = talloc_zero ( result , struct messaging_ctdbd_context ) ) ) {
2016-07-09 14:20:01 +03:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( result ) ;
return ENOMEM ;
}
2017-06-01 19:58:16 +03:00
ret = messaging_ctdbd_init_internal ( msg_ctx , mem_ctx , ctx ,
recv_cb , private_data , false ) ;
2016-07-09 14:20:01 +03:00
if ( ret ! = 0 ) {
TALLOC_FREE ( result ) ;
return ret ;
}
2007-06-10 21:02:09 +04:00
result - > send_fn = messaging_ctdb_send ;
result - > private_data = ( void * ) ctx ;
* presult = result ;
2015-10-03 06:42:05 +03:00
return 0 ;
2007-06-10 21:02:09 +04:00
}
2016-07-09 15:30:35 +03:00
int messaging_ctdbd_reinit ( struct messaging_context * msg_ctx ,
TALLOC_CTX * mem_ctx ,
2017-06-01 19:58:16 +03:00
void ( * recv_cb ) ( struct tevent_context * ev ,
const uint8_t * msg , size_t msg_len ,
int * fds , size_t num_fds ,
void * private_data ) ,
void * private_data ,
2016-07-09 15:30:35 +03:00
struct messaging_backend * backend )
{
struct messaging_ctdbd_context * ctx = talloc_get_type_abort (
backend - > private_data , struct messaging_ctdbd_context ) ;
int ret ;
2017-06-01 19:58:16 +03:00
ret = messaging_ctdbd_init_internal ( msg_ctx , mem_ctx , ctx ,
recv_cb , private_data , true ) ;
2016-07-09 15:30:35 +03:00
if ( ret ! = 0 ) {
return ret ;
}
return 0 ;
}
2017-06-08 13:51:29 +03:00
struct messaging_ctdbd_fde {
struct tevent_fd * fde ;
} ;
static int messaging_ctdbd_fde_ev_destructor (
struct messaging_ctdbd_fde_ev * fde_ev )
{
if ( fde_ev - > ctx ! = NULL ) {
DLIST_REMOVE ( fde_ev - > ctx - > fde_evs , fde_ev ) ;
fde_ev - > ctx = NULL ;
}
return 0 ;
}
struct messaging_ctdbd_fde * messaging_ctdbd_register_tevent_context (
TALLOC_CTX * mem_ctx , struct tevent_context * ev ,
struct messaging_backend * backend )
{
struct messaging_ctdbd_context * ctx = talloc_get_type_abort (
backend - > private_data , struct messaging_ctdbd_context ) ;
struct messaging_ctdbd_fde_ev * fde_ev ;
struct messaging_ctdbd_fde * fde ;
if ( ctx = = NULL ) {
return NULL ;
}
fde = talloc ( mem_ctx , struct messaging_ctdbd_fde ) ;
if ( fde = = NULL ) {
return NULL ;
}
for ( fde_ev = ctx - > fde_evs ; fde_ev ! = NULL ; fde_ev = fde_ev - > next ) {
if ( ( fde_ev - > ev = = ev ) & &
( tevent_fd_get_flags ( fde_ev - > fde ) ! = 0 ) ) {
break ;
}
}
if ( fde_ev = = NULL ) {
int fd = ctdbd_conn_get_fd ( ctx - > conn ) ;
fde_ev = talloc ( fde , struct messaging_ctdbd_fde_ev ) ;
if ( fde_ev = = NULL ) {
return NULL ;
}
fde_ev - > fde = tevent_add_fd (
ev , fde_ev , fd , TEVENT_FD_READ ,
messaging_ctdbd_readable , ctx - > conn ) ;
if ( fde_ev - > fde = = NULL ) {
TALLOC_FREE ( fde ) ;
return NULL ;
}
fde_ev - > ev = ev ;
fde_ev - > ctx = ctx ;
DLIST_ADD ( ctx - > fde_evs , fde_ev ) ;
talloc_set_destructor (
fde_ev , messaging_ctdbd_fde_ev_destructor ) ;
} else {
/*
* Same trick as with tdb_wrap : The caller will never
* see the talloc_referenced object , the
* messaging_ctdbd_fde_ev , so problems with
* talloc_unlink will not happen .
*/
if ( talloc_reference ( fde , fde_ev ) = = NULL ) {
TALLOC_FREE ( fde ) ;
return NULL ;
}
}
fde - > fde = fde_ev - > fde ;
return fde ;
}