2017-05-19 22:22:40 +02:00
/*****************************************************************************
*
* NEBMODS . C - Event Broker Module Functions
*
*
* License :
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* 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 "../include/config.h"
# include "../include/common.h"
# include "../include/nebmods.h"
# include "../include/neberrors.h"
# include "../include/nagios.h"
# ifdef USE_EVENT_BROKER
2017-05-19 23:37:19 +02:00
static nebmodule * neb_module_list ;
static nebcallback * * neb_callback_list ;
2017-05-19 22:22:40 +02:00
2017-05-19 23:37:19 +02:00
/* compat stuff for USE_LTDL */
# ifdef USE_LTDL
# define dlopen(p, flags) lt_dlopen(p)
# define dlclose(p) lt_dlclose(p)
# define dlerror() lt_dlerror()
# define dlsym(hdl, sym) lt_dlsym(hdl, sym)
# define RTLD_NOW 0
# define RTLD_GLOBAL 0
# else
# define lt_dlinit() 0
# define lt_dlexit() 0
# endif
2017-05-19 22:22:40 +02:00
/****************************************************************************/
/****************************************************************************/
/* INITIALIZATION/CLEANUP FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* initialize module routines */
int neb_init_modules ( void ) {
2017-05-19 23:37:19 +02:00
if ( lt_dlinit ( ) )
2017-05-19 22:22:40 +02:00
return ERROR ;
return OK ;
}
/* deinitialize module routines */
int neb_deinit_modules ( void ) {
2017-05-19 23:37:19 +02:00
if ( lt_dlexit ( ) )
2017-05-19 22:22:40 +02:00
return ERROR ;
return OK ;
}
/* add a new module to module list */
int neb_add_module ( char * filename , char * args , int should_be_loaded ) {
nebmodule * new_module = NULL ;
int x = OK ;
if ( filename = = NULL )
return ERROR ;
/* allocate memory */
2017-05-19 23:37:19 +02:00
new_module = ( nebmodule * ) calloc ( 1 , sizeof ( nebmodule ) ) ;
2017-05-19 22:22:40 +02:00
if ( new_module = = NULL )
return ERROR ;
/* initialize vars */
new_module - > filename = ( char * ) strdup ( filename ) ;
new_module - > args = ( args = = NULL ) ? NULL : ( char * ) strdup ( args ) ;
new_module - > should_be_loaded = should_be_loaded ;
new_module - > is_currently_loaded = FALSE ;
for ( x = 0 ; x < NEBMODULE_MODINFO_NUMITEMS ; x + + )
new_module - > info [ x ] = NULL ;
new_module - > module_handle = NULL ;
new_module - > init_func = NULL ;
new_module - > deinit_func = NULL ;
/* add module to head of list */
new_module - > next = neb_module_list ;
neb_module_list = new_module ;
log_debug_info ( DEBUGL_EVENTBROKER , 0 , " Added module: name='%s', args='%s', should_be_loaded='%d' \n " , filename , args , should_be_loaded ) ;
return OK ;
}
2017-05-19 23:37:19 +02:00
int neb_add_core_module ( nebmodule * mod ) {
mod - > should_be_loaded = FALSE ;
mod - > is_currently_loaded = TRUE ;
mod - > core_module = TRUE ;
# ifdef USE_LTDL
mod - > module_handle = ( lt_dlhandle ) mod ;
# else
mod - > module_handle = mod ;
# endif
mod - > next = neb_module_list ;
neb_module_list = mod ;
return 0 ;
}
2017-05-19 22:22:40 +02:00
/* free memory allocated to module list */
int neb_free_module_list ( void ) {
nebmodule * temp_module = NULL ;
nebmodule * next_module = NULL ;
int x = OK ;
2017-05-19 23:37:19 +02:00
for ( temp_module = neb_module_list ; temp_module ; temp_module = next_module ) {
2017-05-19 22:22:40 +02:00
next_module = temp_module - > next ;
2017-05-19 23:37:19 +02:00
2017-05-19 22:22:40 +02:00
for ( x = 0 ; x < NEBMODULE_MODINFO_NUMITEMS ; x + + )
my_free ( temp_module - > info [ x ] ) ;
2017-05-19 23:37:19 +02:00
/* don't free this stuff for core modules */
if ( temp_module - > core_module )
continue ;
my_free ( temp_module - > filename ) ;
my_free ( temp_module - > args ) ;
2017-05-19 22:22:40 +02:00
my_free ( temp_module ) ;
}
neb_module_list = NULL ;
return OK ;
}
/****************************************************************************/
/****************************************************************************/
/* LOAD/UNLOAD FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* load all modules */
int neb_load_all_modules ( void ) {
nebmodule * temp_module = NULL ;
2017-05-19 23:37:19 +02:00
int ret , errors = 0 ;
2017-05-19 22:22:40 +02:00
for ( temp_module = neb_module_list ; temp_module ; temp_module = temp_module - > next ) {
2017-05-19 23:37:19 +02:00
ret = neb_load_module ( temp_module ) ;
if ( ret ! = OK ) {
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Failed to load module '%s'. \n " , temp_module - > filename ? temp_module - > filename : " (no file?) " ) ;
errors + + ;
}
2017-05-19 22:22:40 +02:00
}
2017-05-19 23:37:19 +02:00
return errors ? ERROR : OK ;
2017-05-19 22:22:40 +02:00
}
/* load a particular module */
int neb_load_module ( nebmodule * mod ) {
int ( * initfunc ) ( int , char * , void * ) ;
int * module_version_ptr = NULL ;
2017-05-19 23:37:19 +02:00
int result = OK ;
2017-05-19 22:22:40 +02:00
2017-05-19 23:37:19 +02:00
if ( mod = = NULL )
2017-05-19 22:22:40 +02:00
return ERROR ;
/* don't reopen the module */
if ( mod - > is_currently_loaded = = TRUE )
return OK ;
/* don't load modules unless they should be loaded */
2017-05-19 23:37:19 +02:00
if ( mod - > should_be_loaded = = FALSE | | mod - > filename = = NULL )
2017-05-19 22:22:40 +02:00
return ERROR ;
2017-05-19 23:37:19 +02:00
/* load the module */
mod - > module_handle = dlopen ( mod - > filename , RTLD_NOW | RTLD_GLOBAL ) ;
2017-05-19 22:22:40 +02:00
if ( mod - > module_handle = = NULL ) {
2017-05-19 23:37:19 +02:00
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Could not load module '%s' -> %s \n " , mod - > filename , dlerror ( ) ) ;
2017-05-19 22:22:40 +02:00
return ERROR ;
}
/* mark the module as being loaded */
mod - > is_currently_loaded = TRUE ;
/* find module API version */
module_version_ptr = ( int * ) dlsym ( mod - > module_handle , " __neb_api_version " ) ;
/* check the module API version */
if ( module_version_ptr = = NULL | | ( ( * module_version_ptr ) ! = CURRENT_NEB_API_VERSION ) ) {
2017-05-19 23:37:19 +02:00
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Module '%s' is using an old or unspecified version of the event broker API. Module will be unloaded. \n " , mod - > filename ) ;
2017-05-19 22:22:40 +02:00
neb_unload_module ( mod , NEBMODULE_FORCE_UNLOAD , NEBMODULE_ERROR_API_VERSION ) ;
return ERROR ;
}
/* locate the initialization function */
2017-05-19 23:37:19 +02:00
mod - > init_func = dlsym ( mod - > module_handle , " nebmodule_init " ) ;
2017-05-19 22:22:40 +02:00
/* if the init function could not be located, unload the module */
if ( mod - > init_func = = NULL ) {
2017-05-19 23:37:19 +02:00
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Could not locate nebmodule_init() in module '%s'. Module will be unloaded. \n " , mod - > filename ) ;
2017-05-19 22:22:40 +02:00
neb_unload_module ( mod , NEBMODULE_FORCE_UNLOAD , NEBMODULE_ERROR_NO_INIT ) ;
return ERROR ;
}
/* run the module's init function */
initfunc = mod - > init_func ;
result = ( * initfunc ) ( NEBMODULE_NORMAL_LOAD , mod - > args , mod - > module_handle ) ;
/* if the init function returned an error, unload the module */
if ( result ! = OK ) {
2017-05-19 23:37:19 +02:00
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Function nebmodule_init() in module '%s' returned an error. Module will be unloaded. \n " , mod - > filename ) ;
2017-05-19 22:22:40 +02:00
neb_unload_module ( mod , NEBMODULE_FORCE_UNLOAD , NEBMODULE_ERROR_BAD_INIT ) ;
return ERROR ;
}
2017-05-19 23:37:19 +02:00
logit ( NSLOG_INFO_MESSAGE , TRUE , " Event broker module '%s' initialized successfully. \n " , mod - > filename ) ;
2017-05-19 22:22:40 +02:00
/* locate the de-initialization function (may or may not be present) */
2017-05-19 23:37:19 +02:00
mod - > deinit_func = dlsym ( mod - > module_handle , " nebmodule_deinit " ) ;
2017-05-19 22:22:40 +02:00
log_debug_info ( DEBUGL_EVENTBROKER , 0 , " Module '%s' loaded with return code of '%d' \n " , mod - > filename , result ) ;
if ( mod - > deinit_func ! = NULL )
log_debug_info ( DEBUGL_EVENTBROKER , 0 , " nebmodule_deinit() found \n " ) ;
return OK ;
}
/* close (unload) all modules that are currently loaded */
int neb_unload_all_modules ( int flags , int reason ) {
nebmodule * temp_module ;
for ( temp_module = neb_module_list ; temp_module ; temp_module = temp_module - > next ) {
/* skip modules that are not loaded */
if ( temp_module - > is_currently_loaded = = FALSE )
continue ;
/* skip modules that do not have a valid handle */
if ( temp_module - > module_handle = = NULL )
continue ;
/* close/unload the module */
neb_unload_module ( temp_module , flags , reason ) ;
}
return OK ;
}
/* close (unload) a particular module */
int neb_unload_module ( nebmodule * mod , int flags , int reason ) {
int ( * deinitfunc ) ( int , int ) ;
int result = OK ;
if ( mod = = NULL )
return ERROR ;
log_debug_info ( DEBUGL_EVENTBROKER , 0 , " Attempting to unload module '%s': flags=%d, reason=%d \n " , mod - > filename , flags , reason ) ;
2017-05-19 23:37:19 +02:00
/* remove the module's demand-loaded file */
if ( daemon_dumps_core = = TRUE & & mod - > dl_file ) {
( void ) unlink ( mod - > dl_file ) ;
my_free ( mod - > dl_file ) ;
}
2017-05-19 22:22:40 +02:00
/* call the de-initialization function if available (and the module was initialized) */
if ( mod - > deinit_func & & reason ! = NEBMODULE_ERROR_BAD_INIT ) {
deinitfunc = mod - > deinit_func ;
/* module can opt to not be unloaded */
result = ( * deinitfunc ) ( flags , reason ) ;
/* if module doesn't want to be unloaded, exit with error (unless its being forced) */
if ( result ! = OK & & ! ( flags & NEBMODULE_FORCE_UNLOAD ) )
return ERROR ;
}
/* deregister all of the module's callbacks */
neb_deregister_module_callbacks ( mod ) ;
2017-05-19 23:37:19 +02:00
if ( mod - > core_module = = FALSE ) {
/* unload the module */
result = dlclose ( mod - > module_handle ) ;
if ( result ! = 0 ) {
logit ( NSLOG_RUNTIME_ERROR , TRUE , " Error: Could not unload module '%s' -> %s \n " , mod - > filename , dlerror ( ) ) ;
return ERROR ;
}
}
2017-05-19 22:22:40 +02:00
/* mark the module as being unloaded */
mod - > is_currently_loaded = FALSE ;
log_debug_info ( DEBUGL_EVENTBROKER , 0 , " Module '%s' unloaded successfully. \n " , mod - > filename ) ;
logit ( NSLOG_INFO_MESSAGE , FALSE , " Event broker module '%s' deinitialized successfully. \n " , mod - > filename ) ;
return OK ;
}
/****************************************************************************/
/****************************************************************************/
/* INFO FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* sets module information */
int neb_set_module_info ( void * handle , int type , char * data ) {
nebmodule * temp_module = NULL ;
if ( handle = = NULL )
return NEBERROR_NOMODULE ;
/* check type */
if ( type < 0 | | type > = NEBMODULE_MODINFO_NUMITEMS )
return NEBERROR_MODINFOBOUNDS ;
/* find the module */
for ( temp_module = neb_module_list ; temp_module ! = NULL ; temp_module = temp_module - > next ) {
2017-05-19 23:37:19 +02:00
if ( temp_module - > module_handle = = handle )
2017-05-19 22:22:40 +02:00
break ;
}
if ( temp_module = = NULL )
return NEBERROR_BADMODULEHANDLE ;
/* free any previously allocated memory */
my_free ( temp_module - > info [ type ] ) ;
/* allocate memory for the new data */
if ( ( temp_module - > info [ type ] = ( char * ) strdup ( data ) ) = = NULL )
return NEBERROR_NOMEM ;
return OK ;
}
/****************************************************************************/
/****************************************************************************/
/* CALLBACK FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* allows a module to register a callback function */
int neb_register_callback ( int callback_type , void * mod_handle , int priority , int ( * callback_func ) ( int , void * ) ) {
nebmodule * temp_module = NULL ;
nebcallback * new_callback = NULL ;
nebcallback * temp_callback = NULL ;
nebcallback * last_callback = NULL ;
if ( callback_func = = NULL )
return NEBERROR_NOCALLBACKFUNC ;
if ( neb_callback_list = = NULL )
return NEBERROR_NOCALLBACKLIST ;
if ( mod_handle = = NULL )
return NEBERROR_NOMODULEHANDLE ;
/* make sure the callback type is within bounds */
if ( callback_type < 0 | | callback_type > = NEBCALLBACK_NUMITEMS )
return NEBERROR_CALLBACKBOUNDS ;
/* make sure module handle is valid */
for ( temp_module = neb_module_list ; temp_module ; temp_module = temp_module - > next ) {
2017-05-19 23:37:19 +02:00
if ( temp_module - > module_handle = = mod_handle )
2017-05-19 22:22:40 +02:00
break ;
}
if ( temp_module = = NULL )
return NEBERROR_BADMODULEHANDLE ;
/* allocate memory */
new_callback = ( nebcallback * ) malloc ( sizeof ( nebcallback ) ) ;
if ( new_callback = = NULL )
return NEBERROR_NOMEM ;
new_callback - > priority = priority ;
2017-05-19 23:37:19 +02:00
new_callback - > module_handle = mod_handle ;
new_callback - > callback_func = callback_func ;
2019-08-03 18:28:19 +02:00
new_callback - > next = NULL ;
2017-05-19 22:22:40 +02:00
/* add new function to callback list, sorted by priority (first come, first served for same priority) */
2019-08-03 18:28:19 +02:00
for ( last_callback = NULL , temp_callback = neb_callback_list [ callback_type ] ;
temp_callback ! = NULL ;
last_callback = temp_callback , temp_callback = temp_callback - > next ) {
if ( new_callback - > priority < temp_callback - > priority ) {
break ;
}
}
new_callback - > next = temp_callback ;
if ( last_callback = = NULL ) {
2017-05-19 22:22:40 +02:00
neb_callback_list [ callback_type ] = new_callback ;
2019-08-03 18:28:19 +02:00
}
2017-05-19 22:22:40 +02:00
else {
2019-08-03 18:28:19 +02:00
last_callback - > next = new_callback ;
2017-05-19 22:22:40 +02:00
}
2019-08-03 18:28:19 +02:00
2017-05-19 22:22:40 +02:00
return OK ;
}
/* dregisters all callback functions for a given module */
int neb_deregister_module_callbacks ( nebmodule * mod ) {
nebcallback * temp_callback = NULL ;
nebcallback * next_callback = NULL ;
int callback_type = 0 ;
if ( mod = = NULL )
return NEBERROR_NOMODULE ;
if ( neb_callback_list = = NULL )
return OK ;
for ( callback_type = 0 ; callback_type < NEBCALLBACK_NUMITEMS ; callback_type + + ) {
for ( temp_callback = neb_callback_list [ callback_type ] ; temp_callback ! = NULL ; temp_callback = next_callback ) {
next_callback = temp_callback - > next ;
2017-05-19 23:37:19 +02:00
if ( temp_callback - > module_handle = = mod - > module_handle )
2017-05-19 22:22:40 +02:00
neb_deregister_callback ( callback_type , ( int ( * ) ( int , void * ) ) temp_callback - > callback_func ) ;
}
}
return OK ;
}
/* allows a module to deregister a callback function */
int neb_deregister_callback ( int callback_type , int ( * callback_func ) ( int , void * ) ) {
nebcallback * temp_callback = NULL ;
nebcallback * last_callback = NULL ;
nebcallback * next_callback = NULL ;
if ( callback_func = = NULL )
return NEBERROR_NOCALLBACKFUNC ;
if ( neb_callback_list = = NULL )
return NEBERROR_NOCALLBACKLIST ;
/* make sure the callback type is within bounds */
if ( callback_type < 0 | | callback_type > = NEBCALLBACK_NUMITEMS )
return NEBERROR_CALLBACKBOUNDS ;
/* find the callback to remove */
for ( temp_callback = last_callback = neb_callback_list [ callback_type ] ; temp_callback ! = NULL ; temp_callback = next_callback ) {
next_callback = temp_callback - > next ;
/* we found it */
2017-05-19 23:37:19 +02:00
if ( temp_callback - > callback_func = = callback_func )
2017-05-19 22:22:40 +02:00
break ;
last_callback = temp_callback ;
}
/* we couldn't find the callback */
if ( temp_callback = = NULL )
return NEBERROR_CALLBACKNOTFOUND ;
else {
/* only one item in the list */
if ( temp_callback ! = last_callback - > next )
neb_callback_list [ callback_type ] = NULL ;
else
last_callback - > next = next_callback ;
my_free ( temp_callback ) ;
}
return OK ;
}
/* make callbacks to modules */
int neb_make_callbacks ( int callback_type , void * data ) {
nebcallback * temp_callback , * next_callback ;
int ( * callbackfunc ) ( int , void * ) ;
register int cbresult = 0 ;
int total_callbacks = 0 ;
/* make sure callback list is initialized */
if ( neb_callback_list = = NULL )
return ERROR ;
/* make sure the callback type is within bounds */
if ( callback_type < 0 | | callback_type > = NEBCALLBACK_NUMITEMS )
return ERROR ;
log_debug_info ( DEBUGL_EVENTBROKER , 1 , " Making callbacks (type %d)... \n " , callback_type ) ;
/* make the callbacks... */
for ( temp_callback = neb_callback_list [ callback_type ] ; temp_callback ; temp_callback = next_callback ) {
next_callback = temp_callback - > next ;
callbackfunc = temp_callback - > callback_func ;
cbresult = callbackfunc ( callback_type , data ) ;
temp_callback = next_callback ;
total_callbacks + + ;
log_debug_info ( DEBUGL_EVENTBROKER , 2 , " Callback #%d (type %d) return code = %d \n " , total_callbacks , callback_type , cbresult ) ;
/* module wants to cancel callbacks to other modules (and potentially cancel the default Nagios handling of an event) */
if ( cbresult = = NEBERROR_CALLBACKCANCEL )
break ;
/* module wants to override default Nagios handling of an event */
/* not sure if we should bail out here just because one module wants to override things - what about other modules? EG 12/11/2006 */
else if ( cbresult = = NEBERROR_CALLBACKOVERRIDE )
break ;
}
return cbresult ;
}
/* initialize callback list */
int neb_init_callback_list ( void ) {
register int x = 0 ;
/* allocate memory for the callback list */
neb_callback_list = ( nebcallback * * ) malloc ( NEBCALLBACK_NUMITEMS * sizeof ( nebcallback * ) ) ;
if ( neb_callback_list = = NULL )
return ERROR ;
/* initialize list pointers */
for ( x = 0 ; x < NEBCALLBACK_NUMITEMS ; x + + )
neb_callback_list [ x ] = NULL ;
return OK ;
}
/* free memory allocated to callback list */
int neb_free_callback_list ( void ) {
nebcallback * temp_callback = NULL ;
nebcallback * next_callback = NULL ;
register int x = 0 ;
if ( neb_callback_list = = NULL )
return OK ;
for ( x = 0 ; x < NEBCALLBACK_NUMITEMS ; x + + ) {
for ( temp_callback = neb_callback_list [ x ] ; temp_callback ! = NULL ; temp_callback = next_callback ) {
next_callback = temp_callback - > next ;
my_free ( temp_callback ) ;
}
neb_callback_list [ x ] = NULL ;
}
my_free ( neb_callback_list ) ;
return OK ;
}
# endif