Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

599 lines (481 sloc) 17.741 kb
/*****************************************************************************
*
* NPCDMOD.C
*
* Copyright (c) 2008-2010 Hendrik Baecker (http://www.pnp4nagios.org)
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Last Modified: 07-30-2010
*
*****************************************************************************/
/* include (minimum required) event broker header files */
#include "../include/nebmodules.h"
#include "../include/nebcallbacks.h"
/* include other event broker header files that we need for our work */
#include "../include/nebstructs.h"
#include "../include/broker.h"
/* include some Nagios stuff as well */
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nagios.h"
/* include some pnp stuff */
#include "../include/pnp.h"
#include "../include/npcdmod.h"
/* specify event broker API version (required) */
NEB_API_VERSION(CURRENT_NEB_API_VERSION);
extern int process_performance_data;
FILE *fp = NULL;
void *npcdmod_module_handle = NULL;
char *perfdata_file = "/usr/local/nagios/var/perfdata";
char *perfdata_spool_filename = "perfdata";
char *spool_dir = NULL;
char *perfdata_file_processing_interval = "15";
void npcdmod_file_roller();
int npcdmod_handle_data(int, void *);
int npcdmod_process_config_var(char *arg);
int npcdmod_process_module_args(char *args);
/* this function gets called when the module is loaded by the event broker */
int nebmodule_init(int flags, char *args, nebmodule *handle) {
char temp_buffer[1024];
time_t current_time;
//unsigned long interval;
/* save our handle */
npcdmod_module_handle = handle;
/* set some info - this is completely optional, as Nagios doesn't do anything with this data */
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_TITLE, "npcdmod");
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_AUTHOR, "Hendrik Baecker");
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_TITLE, "Copyright (c) 2008-2009 Hendrik Baecker");
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_VERSION, "0.0.2");
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_LICENSE, "GPL v2");
neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_DESC, "A simple performance data extractor.");
/* log module info to the Nagios log file */
write_to_all_logs("npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org", NSLOG_INFO_MESSAGE);
if (process_performance_data == FALSE) {
write_to_all_logs("npcdmod: I can not work with disabled performance data in nagios.cfg.", NSLOG_INFO_MESSAGE);
write_to_all_logs("npcdmod: Please enable it with 'process_performance_data=1' in nagios.cfg", NSLOG_INFO_MESSAGE);
return -1;
}
/* process arguments */
if (npcdmod_process_module_args(args) == ERROR) {
write_to_all_logs("npcdmod: An error occurred while attempting to process module arguments.", NSLOG_INFO_MESSAGE);
return -1;
}
/* de-initialize if there is no perfdata file nor spool dir */
if (spool_dir == NULL || perfdata_file == NULL) {
write_to_all_logs("npcdmod: An error occurred process your config file. Check your perfdata_file or perfdata_spool_dir.", NSLOG_INFO_MESSAGE);
return -1;
}
/* Log some health data */
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: spool_dir = '%s'.", spool_dir);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: perfdata file '%s'.", perfdata_file);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
/* open perfdata_file to write perfdata in it */
if ((fp = fopen(perfdata_file, "a")) == NULL) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: Could not open file. %s", strerror(errno));
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
return -1;
}
/* log a message to the Nagios log file that we're ready */
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: Ready to run to have some fun!\n");
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
/* register for a 15 seconds file move event */
time(&current_time);
//interval = 15;
schedule_new_event(EVENT_USER_FUNCTION,TRUE, current_time + atoi(perfdata_file_processing_interval), TRUE,
atoi(perfdata_file_processing_interval), NULL, TRUE, (void *) npcdmod_file_roller, "", 0);
/* register to be notified of certain events... */
neb_register_callback(NEBCALLBACK_HOST_CHECK_DATA, npcdmod_module_handle,
0, npcdmod_handle_data);
neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA,
npcdmod_module_handle, 0, npcdmod_handle_data);
return 0;
}
/* this function gets called when the module is unloaded by the event broker */
int nebmodule_deinit(int flags, int reason) {
char temp_buffer[1024];
/* deregister for all events we previously registered for... */
neb_deregister_callback(NEBCALLBACK_HOST_CHECK_DATA,npcdmod_handle_data);
neb_deregister_callback(NEBCALLBACK_SERVICE_CHECK_DATA,npcdmod_handle_data);
/* log a message to the Nagios log file */
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: If you don't like me, I will go out! Bye.\n");
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
return 0;
}
/* gets called every X seconds by an event in the scheduling queue */
void npcdmod_file_roller() {
char temp_buffer[1024];
char spool_file[1024];
int result = 0;
time_t current_time;
time(&current_time);
sprintf(spool_file, "%s/%s.%d", spool_dir, perfdata_spool_filename, (int)current_time);
spool_file[sizeof(spool_file) - 1] = '\x0';
/* close actual file */
fclose(fp);
/* move the original file */
result = my_rename(perfdata_file, spool_file);
/* open a new file */
if ((fp = fopen(perfdata_file, "a")) == NULL) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: Could not reopen file. %s", strerror(errno));
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
}
return;
}
/* handle data from Nagios daemon */
int npcdmod_handle_data(int event_type, void *data) {
nebstruct_host_check_data *hostchkdata = NULL;
nebstruct_service_check_data *srvchkdata = NULL;
host *host=NULL;
service *service=NULL;
char temp_buffer[1024];
char perfdatafile_template[PERFDATA_BUFFER];
int written;
/* what type of event/data do we have? */
switch (event_type) {
case NEBCALLBACK_HOST_CHECK_DATA:
/* an aggregated status data dump just started or ended... */
if ((hostchkdata = (nebstruct_host_check_data *) data)) {
host = find_host(hostchkdata->host_name);
if(host->process_performance_data == 0) {
break;
}
/* Do some Debuglog */
/*
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: DEBUG >>> %s\n",
host->host_check_command);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
*/
if (hostchkdata->type == NEBTYPE_HOSTCHECK_PROCESSED
&& hostchkdata->perf_data != NULL) {
written = snprintf(perfdatafile_template, PERFDATA_BUFFER,
"DATATYPE::HOSTPERFDATA\t"
"TIMET::%d\t"
"HOSTNAME::%s\t"
"HOSTPERFDATA::%s\t"
"HOSTCHECKCOMMAND::%s!%s\t"
"HOSTSTATE::%d\t"
"HOSTSTATETYPE::%d\n", (int)hostchkdata->timestamp.tv_sec,
hostchkdata->host_name, hostchkdata->perf_data,
hostchkdata->command_name, hostchkdata->command_args,
hostchkdata->state, hostchkdata->state_type);
if (written >= PERFDATA_BUFFER) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: Buffer size of %d in npcdmod.h is too small, ignoring data for %s\n", PERFDATA_BUFFER, hostchkdata->host_name);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
} else {
fputs(perfdatafile_template, fp);
}
}
}
break;
case NEBCALLBACK_SERVICE_CHECK_DATA:
/* an aggregated status data dump just started or ended... */
if ((srvchkdata = (nebstruct_service_check_data *) data)) {
if (srvchkdata->type == NEBTYPE_SERVICECHECK_PROCESSED
&& srvchkdata->perf_data != NULL) {
/* find the nagios service object for this service */
service = find_service(srvchkdata->host_name, srvchkdata->service_description);
if(service->process_performance_data == 0) {
break;
}
/* Do some Debuglog */
/*
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: DEBUG >>> %s\n",
service->service_check_command);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
*/
written = snprintf(perfdatafile_template, PERFDATA_BUFFER,
"DATATYPE::SERVICEPERFDATA\t"
"TIMET::%d\t"
"HOSTNAME::%s\t"
"SERVICEDESC::%s\t"
"SERVICEPERFDATA::%s\t"
"SERVICECHECKCOMMAND::%s\t"
"SERVICESTATE::%d\t"
"SERVICESTATETYPE::%d\n", (int)srvchkdata->timestamp.tv_sec,
srvchkdata->host_name, srvchkdata->service_description,
srvchkdata->perf_data, service->service_check_command,
srvchkdata->state, srvchkdata->state_type);
if (written >= PERFDATA_BUFFER) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: Buffer size of %d in npcdmod.h is too small, ignoring data for %s / %s\n", PERFDATA_BUFFER, srvchkdata->host_name, srvchkdata->service_description);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
} else {
fputs(perfdatafile_template, fp);
}
}
}
break;
default:
break;
}
return 0;
}
/****************************************************************************/
/* CONFIG FUNCTIONS */
/****************************************************************************/
/* process arguments that were passed to the module at startup */
int npcdmod_process_module_args(char *args) {
char *ptr = NULL;
char **arglist = NULL;
char **newarglist = NULL;
int argcount = 0;
int memblocks = 64;
int arg = 0;
if (args == NULL)
return OK;
/* get all the var/val argument pairs */
/* allocate some memory */
if ((arglist = (char **) malloc(memblocks * sizeof(char **))) == NULL)
return ERROR;
/* process all args */
ptr = strtok(args, ",");
while (ptr) {
/* save the argument */
arglist[argcount++] = strdup(ptr);
/* allocate more memory if needed */
if (!(argcount % memblocks)) {
if ((newarglist = (char **) realloc(arglist, (argcount + memblocks)
* sizeof(char **))) == NULL) {
for (arg = 0; arg < argcount; arg++)
free(arglist[argcount]);
free(arglist);
return ERROR;
} else
arglist = newarglist;
}
ptr = strtok(NULL, ",");
}
/* terminate the arg list */
arglist[argcount] = '\x0';
/* process each argument */
for (arg = 0; arg < argcount; arg++) {
if (npcdmod_process_config_var(arglist[arg]) == ERROR) {
for (arg = 0; arg < argcount; arg++)
free(arglist[arg]);
free(arglist);
return ERROR;
}
}
/* free allocated memory */
for (arg = 0; arg < argcount; arg++)
free(arglist[arg]);
free(arglist);
return OK;
}
/* process all config vars in a file */
int npcdmod_process_config_file(char *filename) {
pnp_mmapfile *thefile = NULL;
char *buf = NULL;
char temp_buffer[1024];
int result = OK;
/* open the file */
if ((thefile = pnp_mmap_fopen(filename)) == NULL) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod ERROR: failed to open %s\n", filename);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
return ERROR;
} else {
snprintf(temp_buffer, sizeof(temp_buffer) - 1,
"npcdmod: %s initialized\n", filename);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
}
/* process each line of the file */
while ((buf = pnp_mmap_fgets(thefile))) {
/* skip comments */
if (buf[0] == '#') {
free(buf);
continue;
}
/* skip blank lines */
if (!strcmp(buf, "")) {
free(buf);
continue;
}
/* skip new lines */
if (!strcmp(buf, "\n")) {
free(buf);
continue;
}
/* process the variable */
result = npcdmod_process_config_var(buf);
/* free memory */
free(buf);
if (result != OK)
break;
}
/* close the file */
pnp_mmap_fclose(thefile);
return result;
}
/* process a single module config variable */
int npcdmod_process_config_var(char *arg) {
char *var = NULL;
char *val = NULL;
/* split var/val */
var = strtok(arg, "=");
val = strtok(NULL, "\n");
/* skip incomplete var/val pairs */
if (var == NULL || val == NULL)
return OK;
/* strip var/val */
strip(var);
strip(val);
/* process the variable... */
if (!strcmp(var, "config_file"))
npcdmod_process_config_file(val);
else if (!strcmp(var, "perfdata_spool_dir"))
spool_dir = strdup(val);
else if (!strcmp(var, "perfdata_file"))
perfdata_file = strdup(val);
else if (!strcmp(var, "perfdata_spool_filename"))
perfdata_spool_filename = strdup(val);
else if (!strcmp(var, "perfdata_file_processing_interval"))
perfdata_file_processing_interval = strdup(val);
else if (!strcmp(var, "user"))
;
else if (!strcmp(var, "group"))
;
else if (!strcmp(var, "log_type"))
;
else if (!strcmp(var, "log_file"))
;
else if (!strcmp(var, "max_logfile_size"))
;
else if (!strcmp(var, "log_level"))
;
else if (!strcmp(var, "perfdata_file_run_cmd"))
;
else if (!strcmp(var, "perfdata_file_run_cmd_args"))
;
else if (!strcmp(var, "identify_npcd"))
;
else if (!strcmp(var, "npcd_max_threads"))
;
else if (!strcmp(var, "sleep_time"))
;
else if (!strcmp(var, "load_threshold"))
;
else if (!strcmp(var, "pid_file"))
;
else
return ERROR;
return OK;
}
/**************************************************************/
/****** MMAP()'ED FILE FUNCTIONS ******************************/
/**************************************************************/
/* open a file read-only via mmap() */
pnp_mmapfile *pnp_mmap_fopen(char *filename) {
pnp_mmapfile *new_mmapfile;
int fd;
void *mmap_buf;
struct stat statbuf;
int mode = O_RDONLY;
/* allocate memory */
if ((new_mmapfile = (pnp_mmapfile *) malloc(sizeof(pnp_mmapfile))) == NULL)
return NULL;
/* open the file */
if ((fd = open(filename, mode)) == -1) {
free(new_mmapfile);
return NULL;
}
/* get file info */
if ((fstat(fd, &statbuf)) == -1) {
close(fd);
free(new_mmapfile);
return NULL;
}
/* mmap() the file */
if ((mmap_buf = (void *) mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE,
fd, 0)) == MAP_FAILED) {
close(fd);
free(new_mmapfile);
return NULL;
}
/* populate struct info for later use */
/*new_mmapfile->path=strdup(filename);*/
new_mmapfile->path = NULL;
new_mmapfile->fd = fd;
new_mmapfile->file_size = (unsigned long) (statbuf.st_size);
new_mmapfile->current_position = 0L;
new_mmapfile->current_line = 0L;
new_mmapfile->mmap_buf = mmap_buf;
return new_mmapfile;
}
/* close a file originally opened via mmap() */
int pnp_mmap_fclose(pnp_mmapfile *temp_mmapfile) {
if (temp_mmapfile == NULL)
return ERROR;
/* un-mmap() the file */
munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size);
/* close the file */
close(temp_mmapfile->fd);
/* free memory */
if (temp_mmapfile->path != NULL)
free(temp_mmapfile->path);
free(temp_mmapfile);
return OK;
}
/* gets one line of input from an mmap()'ed file */
char *pnp_mmap_fgets(pnp_mmapfile *temp_mmapfile) {
char *buf = NULL;
unsigned long x = 0L;
int len = 0;
if (temp_mmapfile == NULL)
return NULL;
/* we've reached the end of the file */
if (temp_mmapfile->current_position >= temp_mmapfile->file_size)
return NULL;
/* find the end of the string (or buffer) */
for (x = temp_mmapfile->current_position; x < temp_mmapfile->file_size; x++) {
if (*((char *) (temp_mmapfile->mmap_buf) + x) == '\n') {
x++;
break;
}
}
/* calculate length of line we just read */
len = (int) (x - temp_mmapfile->current_position);
/* allocate memory for the new line */
if ((buf = (char *) malloc(len + 1)) == NULL) {
write_to_all_logs("could not allocate a new buf", NSLOG_INFO_MESSAGE);
return NULL;
}
/* copy string to newly allocated memory and terminate the string */
memcpy(buf, ((char *) (temp_mmapfile->mmap_buf)
+ temp_mmapfile->current_position), len);
buf[len] = '\x0';
/* update the current position */
temp_mmapfile->current_position = x;
/* increment the current line */
temp_mmapfile->current_line++;
return buf;
}
Jump to Line
Something went wrong with that request. Please try again.