Imported Upstream version 0.6.24+dfsg1

This commit is contained in:
Mario Fetka
2017-05-20 15:26:21 +02:00
commit 32a360eca6
705 changed files with 87250 additions and 0 deletions

137
src/Makefile.in Normal file
View File

@@ -0,0 +1,137 @@
############################
# Makefile for PNP
#
# Last Modified: 11-17-2008
############################
# Source code directories
SRC_INCLUDE=../include
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE
# Compiler flags for use with Valgrind
#CFLAGS=-O0 -g -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (overrides default)
#CFLAGS=-O3 -Wall -fno-strict-aliasing -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (complements default)
#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
#CFLAGS_DEBUG=-ggdb3 -g3
#CFLAGS_GPROF=-pg
#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG) $(CFLAGS_GPROF)
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
MOD_LDFLAGS=@MOD_LDFLAGS@
MOD_CFLAGS=@MOD_CFLAGS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
LIBEXECDIR=@libexecdir@
LIBDIR=@libdir@
CGIDIR=@sbindir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
STRIP=@STRIP@
DATAROOTDIR=@datarootdir@
PERFDATA_DIR=@PERFDATA_DIR@
PERFDATA_SPOOL_DIR=@PERFDATA_SPOOL_DIR@
MATHLIBS=-lm
CP=@CP@
OBJS=pnpsender.o npcd.o config.o
NPCDOBJS=utils.o config.o logging.o
NPCDHEAD=$(SRC_INCLUDE)/pnp.h $(SRC_INCLUDE)/config.h
OBJDEPS=
all: npcd npcdmod.o
# Required Objects
logging: logging.c $(NPCDHEAD)
$(CC) $(CFLAGS) -o $@ logging.c
config: config.c $(NPCDHEAD)
$(CC) $(CFLAGS) -o $@ config.c
utils: utils.c $(NPCDHEAD)
$(CC) $(CFLAGS) -o $@ utils.c
###############################
#
# PNPSENDER
#
###############################
pnpsender: pnpsender.c
$(CC) $(CFLAGS) -o $@ pnpsender.c
###############################
#
# NPCD
#
###############################
npcd: npcd.c $(NPCDOBJS) $(NPCDHEAD)
$(CC) $(CFLAGS) -o $@ npcd.c $(NPCDOBJS) -lpthread
###############################
#
# NPCDMOD
#
###############################
npcdmod.o: npcdmod.c
$(CC) $(MOD_CFLAGS) $(CFLAGS) -o npcdmod.o npcdmod.c $(MOD_LDFLAGS) $(LDFLAGS) $(LIBS) -fPIC
###############################
#
# Cleanups
#
###############################
clean:
-rm -f pnpsender *.o
-rm -f npcd *.o
-rm -f *~ *.*~
distclean: clean
-rm -f Makefile
devclean: distclean
###############################
#
# Install
#
################################
install:
$(MAKE) install-basic
$(MAKE) strip-post-install
install-unstripped:
$(MAKE) install-basic
install-basic:
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATA_DIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATA_SPOOL_DIR)
$(INSTALL) -m 754 $(INSTALL_OPTS) @npcd_name@ $(DESTDIR)$(BINDIR)
$(INSTALL) -m 754 $(INSTALL_OPTS) npcdmod.o $(DESTDIR)$(LIBDIR)
strip-post-install:
$(STRIP) $(DESTDIR)$(BINDIR)/@npcd_name@
$(STRIP) $(DESTDIR)$(LIBDIR)/npcdmod.o

584
src/config.c Normal file
View File

@@ -0,0 +1,584 @@
// Copyright (C) 2007-2009 Hendrik Baecker <andurin@process-zero.de>
// Inspired by Ethan Galstad <egalstad@nagios.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
#include "../include/config.h"
#include "../include/pnp.h"
#include <ctype.h>
extern void pnp_strip(char *);
extern char *macro_x[CONFIG_OPT_COUNT];
extern char *log_file, *log_type;
extern char *command, *command_args, *user, *group, *directory, *pidfile;
extern int daemon_mode;
extern int sighup_detected;
extern int use_syslog;
extern int loglevel;
extern int max_logfile_size;
extern int max_threads;
extern int use_load_threshold;
extern int sleeptime;
extern int identmyself;
extern double load_threshold;
void process_configfile(char *config_file) {
FILE *fh_config_file = NULL;
char current_config_line[MAX_BUFFER_SIZE];
char error_msg[MAX_BUFFER_SIZE];
char variable[MAX_VARIABLE_LENGTH];
char value[MAX_VALUE_LENGTH];
// char *input = NULL;
char *temp;
extern int loglevel;
int error = FALSE;
// int warning = FALSE;
int line_number = 0;
fh_config_file = fopen(config_file, (const char*) "r");
/* check if we can not open that file */
if (fh_config_file == NULL) {
snprintf(error_msg, MAX_BUFFER_SIZE,
"ERROR - Could not open config file - %s", strerror(errno));
error = TRUE;
}
/* ok - parsing the config file line by line */
else {
while (feof(fh_config_file) == 0) {
line_number++;
temp = fgets(current_config_line, 1024, fh_config_file);
temp = NULL;
if (current_config_line == NULL) {
printf("Error reading config\n");
exit(1);
}
if (current_config_line[0] == '#' || current_config_line[0] == '\n')
continue;
pnp_strip(current_config_line);
temp = strtok(current_config_line, "=");
pnp_strip(temp);
/* if there is no variable name, return error */
if (temp == NULL) {
strcpy(error_msg, "No variable found - exiting");
error = TRUE;
break;
}
/* else the variable is good */
strncpy(variable, temp, sizeof(variable));
variable[sizeof(variable) - 1] = '\x0';
/* get the value */
temp = strtok(NULL, "\n");
pnp_strip(temp);
/* if no value exists, return error */
if (temp == NULL) {
strcpy(error_msg, "NULL value");
error = TRUE;
break;
}
/* else the value is good */
strncpy(value, temp, sizeof(value));
value[sizeof(value) - 1] = '\x0';
pnp_strip(value);
/* process the variable/value */
/* log_file directive */
if (!strcmp(variable, "log_file")) {
if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
strcpy(error_msg, "Log file is too long");
error = TRUE;
break;
}
if (log_file != NULL)
free(log_file);
log_file = (char *) strdup(value);
pnp_strip(log_file);
/* save the macro */
if (macro_x[CONFIG_OPT_LOGFILE] != NULL)
free(macro_x[CONFIG_OPT_LOGFILE]);
macro_x[CONFIG_OPT_LOGFILE] = (char *) strdup(log_file);
if (macro_x[CONFIG_OPT_LOGFILE] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro logfile");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOGFILE]);
}
/* log_file_size directive */
else if (!strcmp(variable, "max_logfile_size")) {
if (strlen(value) == 1) {
if (isdigit((int)value[strlen(value)-1]) == FALSE) {
strcpy(error_msg, "log_file_size should be an integer");
error = TRUE;
break;
}
}
/* save the macro */
if (macro_x[CONFIG_OPT_LOGFILESIZE] != NULL)
free(macro_x[CONFIG_OPT_LOGFILESIZE]);
macro_x[CONFIG_OPT_LOGFILESIZE] = (char *) strdup(value);
max_logfile_size = atoi(value);
if (macro_x[CONFIG_OPT_LOGFILESIZE] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro logfilesize");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOGFILESIZE]);
}
/* log_level directive */
else if (!strcmp(variable, "log_level")) {
if (strlen(value) == 1) {
if (isdigit((int)value[strlen(value)-1]) == FALSE) {
strcpy(error_msg, "log_level should be an integer");
error = TRUE;
break;
}
}
/* save the macro */
if (macro_x[CONFIG_OPT_LOGLEVEL] != NULL)
free(macro_x[CONFIG_OPT_LOGLEVEL]);
macro_x[CONFIG_OPT_LOGLEVEL] = (char *) strdup(value);
loglevel = atoi(value);
if (macro_x[CONFIG_OPT_LOGLEVEL] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro loglevel");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOGLEVEL]);
}
/* log_type directive */
else if (!strcmp(variable, "log_type")) {
if (log_type != NULL)
free(log_type);
log_type = (char *) strdup(value);
pnp_strip(log_type);
/* save the macro */
if (macro_x[CONFIG_OPT_LOGTYPE] != NULL)
free(macro_x[CONFIG_OPT_LOGTYPE]);
macro_x[CONFIG_OPT_LOGTYPE] = (char *) strdup(log_type);
if (macro_x[CONFIG_OPT_LOGTYPE] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro log_type");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOGTYPE]);
if (strcmp(macro_x[CONFIG_OPT_LOGTYPE], "syslog") == 0)
use_syslog = TRUE;
else if (strcmp(macro_x[CONFIG_OPT_LOGTYPE], "file") == 0)
use_syslog = FALSE;
else {
strcpy(error_msg,
"Please define \"syslog\" or \"file\" as log_type!");
error = TRUE;
break;
}
}
else if (!strcmp(variable, "perfdata_spool_dir")) {
if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
strcpy(error_msg, "Perfdata Spool Path is too long");
error = TRUE;
break;
}
/* save the macro */
if (macro_x[CONFIG_OPT_SCANDIR] != NULL)
free(macro_x[CONFIG_OPT_SCANDIR]);
macro_x[CONFIG_OPT_SCANDIR] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_SCANDIR] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro Scandir");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOGFILE]);
}
else if (!strcmp(variable, "perfdata_file"))
;
else if (!strcmp(variable, "perfdata_spool_filename"))
;
else if (!strcmp(variable, "perfdata_file_processing_interval"))
;
else if (!strcmp(variable, "user")) {
/* save the macro */
if (macro_x[CONFIG_OPT_USER] != NULL)
free(macro_x[CONFIG_OPT_USER]);
macro_x[CONFIG_OPT_USER] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_USER] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro user");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_USER]);
}
else if (!strcmp(variable, "group")) {
/* save the macro */
if (macro_x[CONFIG_OPT_GROUP] != NULL)
free(macro_x[CONFIG_OPT_GROUP]);
macro_x[CONFIG_OPT_GROUP] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_GROUP] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro group");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_GROUP]);
}
else if (!strcmp(variable, "perfdata_file_run_cmd")) {
/* save the macro */
if (macro_x[CONFIG_OPT_RUNCMD] != NULL)
free(macro_x[CONFIG_OPT_RUNCMD]);
macro_x[CONFIG_OPT_RUNCMD] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_RUNCMD] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro runcmd");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_RUNCMD]);
}
else if (!strcmp(variable, "perfdata_file_run_cmd_args")) {
/* save the macro */
if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL)
free(macro_x[CONFIG_OPT_RUNCMD_ARG]);
macro_x[CONFIG_OPT_RUNCMD_ARG] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_RUNCMD_ARG] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro runcmd_arg");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_RUNCMD_ARG]);
}
else if (!strcmp(variable, "npcd_max_threads")) {
if (strlen(value) == 1) {
if (isdigit((int)value[strlen(value)-1]) == FALSE) {
strcpy(error_msg,
"npcd_max_threads should be an integer");
error = TRUE;
break;
}
}
/* save the macro */
if (macro_x[CONFIG_OPT_MAXTHREADS] != NULL)
free(macro_x[CONFIG_OPT_MAXTHREADS]);
macro_x[CONFIG_OPT_MAXTHREADS] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_MAXTHREADS] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro MAXTHREADS");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_MAXTHREADS]);
}
else if (!strcmp(variable, "use_load_threshold")) {
strcpy(error_msg,
"The option 'use_load_threshold' is obsolete.");
printf(
"An Warning occured while reading your config on line %d. Message was: \"%s\"\n",
line_number, error_msg);
} else if (!strcmp(variable, "load_threshold")) {
/* save the macro */
if (macro_x[CONFIG_OPT_LOAD] != NULL)
free(macro_x[CONFIG_OPT_LOAD]);
macro_x[CONFIG_OPT_LOAD] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_LOAD] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro LOAD");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_LOAD]);
}
else if (!strcmp(variable, "pid_file")) {
FILE *fppid;
/* save the macro */
if (macro_x[CONFIG_OPT_PIDFILE] != NULL)
free(macro_x[CONFIG_OPT_PIDFILE]);
macro_x[CONFIG_OPT_PIDFILE] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_PIDFILE] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro PIDFILE");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_PIDFILE]);
if (daemon_mode == TRUE && sighup_detected == FALSE) {
fppid = fopen(macro_x[CONFIG_OPT_PIDFILE], "w");
if (fppid == NULL) {
snprintf(error_msg, sizeof(error_msg),
"Could not open pidfile '%s': %s",
macro_x[CONFIG_OPT_PIDFILE], strerror(errno));
error = TRUE;
} else {
fclose(fppid);
}
}
}
else if (!strcmp(variable, "sleep_time")) {
if (strlen(value) == 1) {
if (isdigit((int)value[strlen(value)-1]) == FALSE) {
strcpy(error_msg, "sleep_time should be an integer");
error = TRUE;
break;
}
}
/* save the macro */
if (macro_x[CONFIG_OPT_SLEEPTIME] != NULL)
free(macro_x[CONFIG_OPT_SLEEPTIME]);
macro_x[CONFIG_OPT_SLEEPTIME] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_MAXTHREADS] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro SLEEPTIME");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_SLEEPTIME]);
}
else if (!strcmp(variable, "identify_npcd")) {
if (strlen(value) == 1) {
if (isdigit((int)value[strlen(value)-1]) == FALSE) {
strcpy(error_msg, "identify_npcd should be an integer");
error = TRUE;
break;
}
}
/* save the macro */
if (macro_x[CONFIG_OPT_IDENTMYSELF] != NULL)
free(macro_x[CONFIG_OPT_IDENTMYSELF]);
macro_x[CONFIG_OPT_IDENTMYSELF] = (char *) strdup(value);
if (macro_x[CONFIG_OPT_IDENTMYSELF] == NULL) {
strcpy(error_msg,
"Could not allocate memory for macro IDENTMYSELF");
error = TRUE;
break;
}
pnp_strip(macro_x[CONFIG_OPT_IDENTMYSELF]);
}
else {
strcpy(error_msg,
"There is a config directive that I don't know");
error = TRUE;
break;
}
}
}
if (fh_config_file != NULL)
fclose(fh_config_file);
if (error) {
printf(
"An Error occured while reading your config on line %d\nMessage was: \"%s\"\n",
line_number, error_msg);
exit(EXIT_FAILURE);
}
}
/************************************
*
* check if we have all we need
*
* **********************************/
int check_needed_config_options() {
/* Needed config options are:
* logtype
* if syslog: ignore logfile
* if file: logfile is needed
* command
* if command args: command is needed
*/
char error_msg[MAX_BUFFER_SIZE];
int error = FALSE;
int warning = FALSE;
if (macro_x[CONFIG_OPT_LOGTYPE] == NULL) {
strcpy(error_msg, "You have to define a logtype.");
error = TRUE;
} else if ((strcmp(macro_x[CONFIG_OPT_LOGTYPE], "file") == 0)
&& (macro_x[CONFIG_OPT_LOGFILE] == NULL)) {
strcpy(error_msg,
"You have to define a logfile if you wish to use a file for logging.");
error = TRUE;
} else if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL
&& macro_x[CONFIG_OPT_RUNCMD] == NULL) {
strcpy(error_msg, "There should no argument to no command.");
error = TRUE;
} else if (macro_x[CONFIG_OPT_RUNCMD] == NULL) {
strcpy(error_msg,
"There is nothing I can do - please give me a 'perfdata_file_run_cmd'.");
error = TRUE;
} else if (macro_x[CONFIG_OPT_SCANDIR] == NULL) {
strcpy(error_msg,
"You should define a performance data spool directory.");
warning = TRUE;
}
if (error) {
printf("ERROR - %s\n", error_msg);
return ERROR;
} else if (warning) {
printf("WARNING - %s\n", error_msg);
return OK;
} else
return OK;
}
/* Prepare config file variables to program vars */
int prepare_vars() {
if (macro_x[CONFIG_OPT_MAXTHREADS] != NULL) {
max_threads = atoi(macro_x[CONFIG_OPT_MAXTHREADS]);
} else
max_threads = 5;
if (macro_x[CONFIG_OPT_LOAD] != NULL) {
load_threshold = strtod(macro_x[CONFIG_OPT_LOAD], NULL);
if (load_threshold != 0.0)
use_load_threshold = TRUE;
} else {
load_threshold = 0.0;
use_load_threshold = FALSE;
}
if (macro_x[CONFIG_OPT_RUNCMD] != NULL) {
command = macro_x[CONFIG_OPT_RUNCMD];
}
if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL) {
command_args = macro_x[CONFIG_OPT_RUNCMD_ARG];
}
if (macro_x[CONFIG_OPT_USER] != NULL) {
user = macro_x[CONFIG_OPT_USER];
} else
user = "nagios";
if (macro_x[CONFIG_OPT_GROUP] != NULL) {
group = macro_x[CONFIG_OPT_GROUP];
} else
group = "nagios";
if (macro_x[CONFIG_OPT_SCANDIR] != NULL) {
directory = macro_x[CONFIG_OPT_SCANDIR];
} else {
directory = "/usr/local/nagios/var/spool/perfdata/";
printf(
"WARNING - Adapting a hardcoded default perfdata spooldir - '%s'\n",
directory);
}
if (macro_x[CONFIG_OPT_PIDFILE] != NULL) {
pidfile = macro_x[CONFIG_OPT_PIDFILE];
} else
pidfile = "/var/run/npcd.pid";
if (macro_x[CONFIG_OPT_LOGLEVEL] != NULL) {
loglevel = atoi(macro_x[CONFIG_OPT_LOGLEVEL]);
} else
loglevel = 0;
if (macro_x[CONFIG_OPT_SLEEPTIME] != NULL) {
sleeptime = atoi(macro_x[CONFIG_OPT_SLEEPTIME]);
} else
sleeptime = 15;
if (macro_x[CONFIG_OPT_IDENTMYSELF] != NULL) {
identmyself = atoi(macro_x[CONFIG_OPT_IDENTMYSELF]);
} else
identmyself = TRUE;
return OK;
}

93
src/logging.c Normal file
View File

@@ -0,0 +1,93 @@
// Copyright (C) 2007-2009 Hendrik Baecker <andurin@process-zero.de>
//
// 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
#include <stdio.h>
#include <sys/time.h>
#include "../include/config.h"
#include "../include/pnp.h"
int write_log(char *);
extern char* log_file;
extern int use_syslog;
extern int loglevel;
extern int max_logfile_size;
int do_log(char *message) {
if (use_syslog) {
syslog(LOG_NOTICE, "%s", message);
return OK;
} else if (use_syslog == FALSE) {
if (write_log(message)==0)
return OK;
else
return ERROR;
}
return OK;
}
int write_log(char *message) {
int fd;
long filelen;
struct timeval tv;
char temp_buffer[2048];
time_t curtime;
gettimeofday(&tv, NULL);
curtime = tv.tv_sec;
strftime(temp_buffer, sizeof(temp_buffer) - 1, "[%m-%d-%Y %T] NPCD: ",
localtime(&curtime));
strcat(temp_buffer, message);
/* open / create logfile */
if ((fd = open(log_file, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR
| S_IRGRP | S_IROTH)) == -1) {
printf("Cannot open log file %s\n", log_file);
return 0;
}
/* write log message */
if (write(fd, temp_buffer, strlen(temp_buffer)) != strlen(temp_buffer)) {
perror("NPCD: Error writing to log file");
close(fd);
return 0;
}
/* rotate logfile if size > max_logfile_size */
if ((filelen = lseek(fd, 0L, SEEK_END)) > max_logfile_size) {
/* LOG(0, "Begin Logrotation!\n"); */
char buffer[PATH_MAX];
close(fd);
/* delete .old log file */
strncpy(buffer, log_file, sizeof(buffer) - 1);
strncat(buffer, ".old", sizeof(buffer) - 1);
unlink(buffer);
/* rename log_file to log_file.old */
if (rename(log_file, buffer) != 0) {
snprintf(buffer, sizeof(buffer) - 1, "Error rename() logfile - %s",
strerror(errno));
LOG(0, buffer);
//perror("Error renaming logfile\n");
return 0;
}
LOG(0, "Logfile rotated!\n");
} else {
close(fd);
}
return filelen;
}

297
src/module/modpnpsender.c Normal file
View File

@@ -0,0 +1,297 @@
/*****************************************************************************
*
* modpnpsender.c - NEB Module for sending PNP performance data
*
* Copyright (c) 2007-2009 Hendrik Baecker (http://www.process-zero.de)
*
* Last Modified: $LastChangedDate: 2009-01-07 19:53:58 +0100 (Wed, 07 Jan 2009) $
* by: $Author: hendrikb $
*
*
* Description:
*
* Will follow soon....
*
*
* Instructions:
*
* Compile with the following command:
*
* gcc -shared -o modpnpsender.o modpnpsender.c
*
*****************************************************************************/
/* 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 <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <time.h>
#define OPEN 1
#define CLOSE 0
#define BUFFER 1024
/* specify event broker API version (required) */
NEB_API_VERSION(CURRENT_NEB_API_VERSION);
#define DEFAULT_SERVERPORT 5661
void *modpnpsender_module_handle=NULL;
int modpnpsender_handle_data(int,void *);
int send_data(nebstruct_service_check_data *);
int open_sock();
char *serverip="127.0.0.1";
char *port, *saveptr1;
int serverport=DEFAULT_SERVERPORT;
int socket_status=CLOSE;
/* 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 */
modpnpsender_module_handle=handle;
/* log module info to the Nagios log file */
write_to_all_logs("modpnpsender: Copyright (c)2007 Hendrik Baecker (andurin@process-zero.de)",NSLOG_INFO_MESSAGE);
/* log a message to the Nagios log file */
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: PNPSender module starting the engines!\n");
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
if(args == NULL) {
write_to_all_logs("modpnpsender: WARNING assuming '127.0.0.1' as destination IP Address)",NSLOG_INFO_MESSAGE);
}
else {
if((serverip = strtok_r(args, " ", &saveptr1))!=NULL){
serverip = serverip;
}
if((port = strtok_r(NULL, " ", &saveptr1))!=NULL){
serverport=atoi(port);
}
}
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Arguments are %s - %d",serverip,serverport);
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
/* register to be notified of certain events... */
neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA,modpnpsender_module_handle,0,modpnpsender_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_SERVICE_CHECK_DATA,modpnpsender_handle_data);
/* log a message to the Nagios log file */
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Exiting - Thanks for for the flight!\n");
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
return 0;
}
/* handle data from Nagios daemon */
int modpnpsender_handle_data(int event_type, void *data){
nebstruct_service_check_data *scdata=NULL;
char temp_buffer[1024];
/* what type of event/data do we have? */
switch(event_type){
case NEBCALLBACK_SERVICE_CHECK_DATA:
/* a service check event occurs */
if((scdata=(nebstruct_service_check_data *)data)!=NULL){
if (scdata->type==NEBTYPE_SERVICECHECK_INITIATE) {
/* Check if this service check has performance data */
if (scdata->perf_data != NULL) {
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Processing PNP for %s / %s with perfdata %s",scdata->host_name,scdata->service_description,scdata->perf_data);
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
if(send_data(scdata)!=0) {
write_to_all_logs("modpnpsender: An error occured while sending data!",NSLOG_INFO_MESSAGE);
}
else {
write_to_all_logs("modpnpsender: Message sent - finish for now.",NSLOG_INFO_MESSAGE);
return 0;
}
}
}
}
break;
default:
break;
}
return 0;
}
/*********************************************
*
* Sending Data
*
* *******************************************/
int send_data(nebstruct_service_check_data *data){
char temp_buffer[1024];
char *message;
int socket;
int message_length = 1024;
char cmd[1024];
time_t t;
if (socket_status == CLOSE) {
socket = open_sock();
if (socket == -1) {
write_to_all_logs("modpnpsender: Arg! Socket is -1",NSLOG_INFO_MESSAGE);
return (-1);
}
}
if (!(message = (char *) malloc(message_length))) {
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: cannot allocate memory for message. Aborting...\n");
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
return (-1);
}
bzero((void *)message, message_length);
strcat(message,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
strcat(message,"<NAGIOS>\n<NAGIOS_DATATYPE>serviceperfdata</NAGIOS_DATATYPE>\n");
strcat(message,"<NAGIOS_HOSTNAME>");
strcat(message,data->host_name);
strcat(message,"</NAGIOS_HOSTNAME>\n");
strcat(message,"<NAGIOS_SERVICEDESC>");
strcat(message,data->service_description);
strcat(message,"</NAGIOS_SERVICEDESC>\n");
strcat(message,"<NAGIOS_SERVICEPERFDATA>");
strcat(message,data->perf_data);
strcat(message,"</NAGIOS_SERVICEPERFDATA>\n");
strcat(message,"<NAGIOS_SERVICECHECKCOMMAND>");
if (data->command_name != NULL) {
strcat(message,data->command_name);
}
strcat(message,"</NAGIOS_SERVICECHECKCOMMAND>\n");
strcat(message,"<NAGIOS_SERVICECHECKCOMMAND_ARGS>");
if (data->command_args != NULL) strcat(message,data->command_args);
strcat(message,"</NAGIOS_SERVICECHECKCOMMAND>\n");
strcat(message,"<NAGIOS_SERVICECHECKCOMMAND_LINE>");
if (data->command_line != NULL) strcat(message,data->command_line);
strcat(message,"</NAGIOS_SERVICECHECKCOMMAND>\n");
strcat(message,"<NAGIOS_SERVICEOUTPUT>");
if (data->output != NULL) strcat(message,data->output);
strcat(message,"</NAGIOS_SERVICEOUTPUT>\n");
time(&t);
snprintf(temp_buffer, sizeof(temp_buffer)-1,"%ld",t);
temp_buffer[sizeof(temp_buffer)-1]='\x0';
strcat(message,"<NAGIOS_TIMET>");
strcat(message, temp_buffer);
strcat(message,"</NAGIOS_TIMET>\n");
bzero((void *)temp_buffer,sizeof(temp_buffer)-1);
strcat(message,"</NAGIOS>\n");
if(send(socket, message, strlen(message), 0) == -1) {
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: error while sending message to server. - %s\n",strerror(errno));
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
}
close (socket);
socket_status = CLOSE;
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Sending perfdata for %s / %s with perfdata %s",data->host_name,data->service_description,data->perf_data);
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
return 0;
}
int open_sock(){
int tosocket; /* the socket descriptor*/
char temp_buffer[BUFFER];
/* description of struct sockaddr_in is mentioned in netinet/in.h */
struct sockaddr_in toaddr; /* store address of server here */
/* create tcp socket */
tosocket = socket(PF_INET,SOCK_STREAM,0);
if(tosocket == -1){
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Unable to create socket. Aborting...\n");
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
return(-1);
}
/* else {
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Socket is OK....\n");
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
} */
/* define server address */
toaddr.sin_family = PF_INET;
toaddr.sin_addr.s_addr = inet_addr(serverip);
toaddr.sin_port = htons(serverport);
/* connect to server */
if(connect(tosocket, (struct sockaddr *)&toaddr, sizeof(toaddr)) == -1){
snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Unable to connect to server '%s' on port %d. Aborting...\n", serverip, serverport);
temp_buffer[sizeof(temp_buffer)-1]='\x0';
write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);
// write_to_all_logs("modpnpsender: Connect failed... closing the socket...",NSLOG_INFO_MESSAGE);
close (tosocket);
// write_to_all_logs("modpnpsender: Socket closed...",NSLOG_INFO_MESSAGE);
return(-1);
}
else {
socket_status=OPEN;
return tosocket;
}
return (-1);
}

572
src/npcd.c Normal file
View File

@@ -0,0 +1,572 @@
/* Copyright (C) 2007-2009 Hendrik Baecker <andurin@process-zero.de>
*
* 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
*/
#include "../include/config.h"
#include "../include/pnp.h"
typedef void (*sighandler_t)(int);
void *processfile(void *);
static void *exit_handler_mem(void *);
extern int process_arguments(int, char **);
extern void process_configfile(char *);
extern void check_sig(int);
extern int prepare_vars(void);
extern int drop_privileges(char *, char *);
extern sighandler_t handle_signal(int, sighandler_t);
extern int is_file(const struct dirent *d);
extern int check_needed_config_options();
double getload(int);
static int thread_counter = 0;
int max_threads = 5;
int daemon_mode = FALSE;
int use_syslog = TRUE;
int loglevel = 0;
int max_logfile_size = 10485760; /* default 10Mbyte */
int use_load_threshold = FALSE;
int we_should_stop = FALSE;
int sleeptime = 15;
int identmyself = TRUE;
double load_threshold = 10.0;
extern int sighup_detected;
char *command, *command_args, *user, *group, *pidfile;
char *macro_x[CONFIG_OPT_COUNT];
char *log_file, *log_type;
char *config_file = NULL;
const char *directory = NULL;
const char progname[5] = "npcd";
static void start_daemon(const char *log_name, int facility) {
int i;
pid_t pid;
/* Kill parent after for to get a waise */
if ((pid = fork()) != 0)
exit(EXIT_SUCCESS);
/* Get this waise to sessionleader */
if (setsid() < 0) {
printf("%s could not get sessionleader\n", log_name);
exit(EXIT_FAILURE);
}
/* Ignore SIGHUP */
handle_signal(SIGHUP, SIG_IGN);
/* terminate child */
if ((pid = fork()) != 0)
exit(EXIT_SUCCESS);
/* for core dump handling and better unmounting behavior */
/* Its return should not be ignored.
* npcd.c:79: warning: ignoring return value of chdir */
if (chdir("/") != 0)
exit(EXIT_FAILURE);
/* change umask to defined value - be independet from parent umask */
umask(002);
/* close all possible file handles */
for (i = sysconf(_SC_OPEN_MAX); i > 0; i--)
close(i);
/* to hear the daemon you are calling... use syslog */
if (use_syslog == TRUE && log_name != NULL)
openlog(log_name, LOG_PID | LOG_CONS | LOG_NDELAY, facility);
/* close existing stdin, stdout, stderr */
close(0);
close(1);
close(2);
/* re-open stdin, stdout, stderr with known values */
open("/dev/null",O_RDONLY);
open("/dev/null",O_WRONLY);
open("/dev/null",O_WRONLY);
}
int main(int argc, char **argv) {
int i = 0;
int filecounter = 0, pthread_ret = 0;
double load;
char buffer[MAX_LOGMESSAGE_SIZE];
FILE *fppid = NULL;
struct dirent **namelist;
load = 0.0;
if (process_arguments(argc, argv) == EXIT_FAILURE)
exit(EXIT_FAILURE);
process_configfile(config_file);
if (loglevel == -1) {
printf("DEBUG: Config File = %s\n", config_file);
printf("CONFIG_OPT_LOGTYPE = %s\n", macro_x[CONFIG_OPT_LOGTYPE]);
printf("CONFIG_OPT_LOGFILE = %s\n", macro_x[CONFIG_OPT_LOGFILE]);
printf("CONFIG_OPT_LOGFILESIZE = %s\n", macro_x[CONFIG_OPT_LOGFILESIZE]);
printf("CONFIG_OPT_LOGLEVEL = %s\n", macro_x[CONFIG_OPT_LOGLEVEL]);
printf("CONFIG_OPT_SCANDIR = %s\n", macro_x[CONFIG_OPT_SCANDIR]);
printf("CONFIG_OPT_RUNCMD = %s\n", macro_x[CONFIG_OPT_RUNCMD]);
printf("CONFIG_OPT_RUNCMD_ARG = %s\n", macro_x[CONFIG_OPT_RUNCMD_ARG]);
printf("CONFIG_OPT_MAXTHREADS = %s\n", macro_x[CONFIG_OPT_MAXTHREADS]);
printf("CONFIG_OPT_LOAD = %s\n", macro_x[CONFIG_OPT_LOAD]);
printf("CONFIG_OPT_USER = %s\n", macro_x[CONFIG_OPT_USER]);
printf("CONFIG_OPT_GROUP = %s\n", macro_x[CONFIG_OPT_GROUP]);
printf("CONFIG_OPT_PIDFILE = %s\n", macro_x[CONFIG_OPT_PIDFILE]);
printf("CONFIG_OPT_SLEEPTIME = %s\n", macro_x[CONFIG_OPT_SLEEPTIME]);
printf("CONFIG_OPT_IDENTMYSELF = %s\n", macro_x[CONFIG_OPT_IDENTMYSELF]);
printf("---------------------------\n");
if (check_needed_config_options() != 0) {
printf("There is an Error! Exiting...\n");
exit(EXIT_FAILURE);
}
}
if (prepare_vars() != 0)
exit(EXIT_FAILURE);
if (loglevel == -1)
printf("DEBUG: load_threshold is %s - ('%f')\n",
use_load_threshold ? "enabled" : "disabled", load_threshold);
pthread_t th[max_threads];
for (i=0;i<max_threads;i++){
th[i] = (pthread_t) NULL;
}
i = 0;
/* Nice point for another function to set
* the internal vars from macro_x[] */
/* Start in Daemon Mode or in foreground? */
if (daemon_mode == TRUE)
start_daemon("NPCD", LOG_LOCAL0);
else if (use_syslog)
openlog("NPCD", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_LOCAL0);
/* Create PID File or exit on failure */
if (daemon_mode == TRUE && sighup_detected == FALSE) {
fppid = fopen(pidfile, "w");
if (fppid == NULL) {
printf("Could not open pidfile '%s': %s\n", pidfile,
strerror(errno));
exit(EXIT_FAILURE);
} else {
fprintf(fppid, "%d", getpid());
fclose(fppid);
}
}
/* Try to drop the privileges */
if (drop_privileges(user, group) == EXIT_FAILURE)
exit(EXIT_FAILURE);
snprintf(buffer, sizeof(buffer) - 1,
"%s Daemon (%s) started with PID=%d\n", progname, PACKAGE_VERSION,
getpid());
LOG(0, buffer);
snprintf(buffer, sizeof(buffer) - 1,
"Please have a look at '%s -V' to get license information\n",
progname);
LOG(0, buffer);
//sigemptyset();
handle_signal(SIGINT, check_sig);
handle_signal(SIGHUP, check_sig);
handle_signal(SIGTERM, check_sig);
snprintf(buffer, sizeof(buffer) - 1,
"HINT: load_threshold is %s - ('%f')\n",
use_load_threshold ? "enabled" : "disabled", load_threshold);
LOG(0, buffer);
/* beginn main loop */
while (1) {
if (chdir(directory) != 0)
exit(EXIT_FAILURE);
/* is_file() filter may cause trouble on some systems
* like Solaris or HP-UX that don't have a d-type
* member in struct dirent
*/
/* #ifdef HAVE_STRUCT_DIRENT_D_TYPE
if ( ( filecounter = scandir( directory, &namelist, is_file, alphasort ) ) < 0 ) {
#else */
if ((filecounter = scandir(directory, &namelist, 0, alphasort)) < 0) {
/* #endif */
snprintf(buffer, sizeof(buffer) - 1,
"Error while get file list from spooldir (%s) - %s\n",
directory, strerror(errno));
LOG(0, buffer);
snprintf(buffer, sizeof(buffer) - 1, "Exiting...\n");
LOG(0, buffer);
if (daemon_mode != TRUE)
printf("Error while get file list from spooldir (%s) - %s\n",
directory, strerror(errno));
break;
}
snprintf(buffer, sizeof(buffer) - 1, "Found %d files in %s\n",
filecounter, directory);
LOG(2, buffer);
for (i = 0, namelist; i < filecounter; i++) {
#ifdef HAVE_GETLOADAVG
if (use_load_threshold == TRUE) {
load = getload(1);
snprintf(buffer, sizeof(buffer) - 1, "DEBUG: load %f/%f\n",
load, load_threshold);
LOG(2, buffer);
}
if (use_load_threshold && (load > load_threshold)) {
snprintf(buffer, sizeof(buffer) - 1,
"WARN: MAX load reached: load %f/%f at i=%d", load,
load_threshold, i);
LOG(0, buffer);
if (i > 0)
i--;
sleep(sleeptime);
continue;
}
#endif
snprintf(buffer, sizeof(buffer) - 1,
"ThreadCounter %d/%d File is %s\n", thread_counter,
max_threads, namelist[i]->d_name);
LOG(2, buffer);
struct stat attribute;
if (stat(namelist[i]->d_name, &attribute) == -1) {
LOG(0, "Error while getting file status");
break;
}
if (strstr((namelist[i]->d_name), "-PID-") != NULL) {
snprintf(
buffer,
sizeof(buffer) - 1,
"File '%s' is an already in process PNP file. Leaving it untouched.\n",
namelist[i]->d_name);
LOG(1, buffer);
continue;
}
if (S_ISREG(attribute.st_mode)) {
snprintf(buffer, sizeof(buffer) - 1, "Regular File: %s\n",
namelist[i]->d_name);
LOG(2, buffer);
/* only start new threads if the max_thread config option is not reached */
if (thread_counter < max_threads && we_should_stop == FALSE) {
if ((pthread_ret = pthread_create(&th[thread_counter],
NULL, processfile, namelist[i]->d_name)) != 0) {
snprintf(buffer, sizeof(buffer) - 1,
"Could not create thread... exiting with error '%s'\n", strerror(errno));
LOG(0, buffer);
exit(EXIT_FAILURE);
}
snprintf(buffer, sizeof(buffer) - 1,
"A thread was started on thread_counter = %d\n",
thread_counter);
LOG(2, buffer);
thread_counter++;
}
else if (we_should_stop == TRUE)
break;
else {
snprintf(
buffer,
sizeof(buffer) - 1,
"WARN: MAX Thread reached: %s comes later with ThreadCounter: %d\n",
namelist[i]->d_name, thread_counter);
LOG(2, buffer);
i--;
for (thread_counter = thread_counter; thread_counter > 0; thread_counter--) {
snprintf(buffer, sizeof(buffer) - 1,
"DEBUG: Will wait for th['%d']\n",
thread_counter - 1);
LOG(2, buffer);
pthread_join(th[thread_counter - 1], NULL);
}
}
}
}
if (thread_counter > 0) {
/* Wait for open threads before working on the next run */
snprintf(buffer, sizeof(buffer) - 1,
"Have to wait: Filecounter = %d - thread_counter = %d\n",
filecounter - 2, thread_counter);
LOG(2, buffer);
for (thread_counter = thread_counter; thread_counter > 0; thread_counter--)
pthread_join(th[thread_counter - 1], NULL);
}
if (we_should_stop == TRUE)
break;
for (i = 0, namelist; i < filecounter; i++) {
free(namelist[i]);
}
free(namelist);
snprintf(buffer, sizeof(buffer) - 1,
"No more files to process... waiting for %d seconds\n",
sleeptime);
LOG(1, buffer);
sleep(sleeptime);
}
snprintf(buffer, sizeof(buffer) - 1, "Daemon ended. PID was '%d'\n",
getpid());
LOG(0, buffer);
if (use_syslog)
closelog();
return EXIT_SUCCESS;
}
/* **************************************************************
*
* Function to parse and check the commandline arguments
*
* *************************************************************/
int process_arguments(int argc, char **argv) {
int c;
int error = FALSE;
int display_license = FALSE;
int display_help = FALSE;
#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = { { "help", no_argument, 0, 'h' }, {
"version", no_argument, 0, 'V' },
{ "license", no_argument, 0, 'V' },
{ "daemon", no_argument, 0, 'd' }, { "config", required_argument,
0, 'f' }, { 0, 0, 0, 0 } };
#endif
/* make sure we have the correct number of command line arguments */
if (argc < 2)
error = TRUE;
while (1) {
#ifdef HAVE_GETOPT_H
c = getopt_long(argc, argv, "+hVdf:", long_options, &option_index);
#else
c = getopt(argc, argv, "+hVdf:");
#endif
if (c == -1 || c == EOF)
break;
switch (c) {
case '?': /* usage */
case 'h':
display_help = TRUE;
break;
case 'V': /* version */
printf("%s %s - $Revision: 637 $\n\n", progname, PACKAGE_VERSION);
display_license = TRUE;
break;
case 'd': /* run in daemon mode */
daemon_mode = TRUE;
break;
case 'f': /* config file */
if (optarg != NULL)
config_file = optarg;
break;
default:
break;
}
}
if (display_license == TRUE) {
printf(
"This program is free software; you can redistribute it and/or modify\n");
printf(
"it under the terms of the GNU General Public License version 2 as\n");
printf("published by the Free Software Foundation.\n\n");
printf(
"This program is distributed in the hope that it will be useful,\n");
printf(
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf(
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf("GNU General Public License for more details.\n\n");
printf(
"You should have received a copy of the GNU General Public License\n");
printf("along with this program; if not, write to the Free Software\n");
printf(
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n\n");
exit(EXIT_SUCCESS);
}
/* if there are no command line options (or if we encountered an error), print usage */
if (error == TRUE || display_help == TRUE) {
printf("\nUsage: %s -f <configfile> [-d] \n", argv[0]);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -d | --daemon \n");
printf("\t\tRun as daemon in background\n");
printf("\n");
printf(" -f | --config \n");
printf("\t\tPath to config file\n");
printf("\n");
printf(
"Visit the Website at http://sourceforge.net/projects/pnp4nagios/ for bug fixes, \n");
printf("new releases, online documentation, FAQs, Mailinglists.\n");
printf("\n");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
/********************************************************************
* *
* processfile - this is the function for each thread *
* *
********************************************************************/
void * processfile(void *filename) {
char *file = (char *) filename;
char command_line[MAX_COMMANDLINE_LENGTH];
char buffer[MAX_LOGMESSAGE_SIZE];
int result;
FILE *proc;
/* npcd.c:493: warning: result may be used uninitialized in this function */
result = 0;
snprintf(command_line, sizeof(command_line), "%s %s %s %s/%s", command,
identmyself ? "-n" : "\b", command_args, directory, file);
pthread_cleanup_push((void *) &exit_handler_mem, file);
snprintf(buffer, sizeof(buffer) - 1,
"Processing file %s with ID %ld - going to exec %s\n", file,
pthread_self(), command_line);
LOG(2, buffer);
snprintf(buffer, sizeof(buffer) - 1, "Processing file '%s'\n", file);
LOG(1, buffer);
if ((proc = popen(command_line, "r")) != NULL)
result = pclose(proc);
result >>= 8;
if (result != 0) {
snprintf(buffer, sizeof(buffer) - 1,
"ERROR: Executed command exits with return code '%d'\n",
result);
LOG(0, buffer);
snprintf(buffer, sizeof(buffer) - 1,
"ERROR: Command line was '%s'\n", command_line);
LOG(0, buffer);
we_should_stop = FALSE;
}
if (loglevel == -1)
sleep(2);
pthread_cleanup_pop(1);
pthread_exit((void *) pthread_self());
}
/* ******************************************************************
* *
* processfile - this is the function for each thread *
* *
* ******************************************************************/
static void *exit_handler_mem(void * arg) {
// syslog( LOG_NOTICE, "Will now clean up thread %ld\n",pthread_self());
//if (thread_counter > 0)
//thread_counter--;
return 0;
}
#ifdef HAVE_GETLOADAVG
double getload(int which_sample) {
double loadavg[3];
char buffer[MAX_LOGMESSAGE_SIZE];
if (which_sample == 1) {
which_sample = 0;
} else if (which_sample == 5) {
which_sample = 1;
} else if (which_sample == 15) {
which_sample = 2;
} else {
snprintf(buffer, sizeof(buffer) - 1,
"Invalid load sample %d - allowed is 1,5,15\n", which_sample);
LOG(0, buffer);
return -1;
}
getloadavg(loadavg, 3);
return loadavg[which_sample];
}
#endif

598
src/npcdmod.c Normal file
View File

@@ -0,0 +1,598 @@
/*****************************************************************************
*
* 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;
}

384
src/pnpsender.c Normal file
View File

@@ -0,0 +1,384 @@
// Copyright (C) 2006-2009 Hendrik Baecker <andurin@process-zero.de>
//
// 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
#include "../include/config.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define BUFFER_SIZE 255
#define DEFAULT_SERVERPORT 5661 /* Ein Port der auch von 'gewhnlichen' Benutzern verwendet werden darf */
#define MSG_SIZE 8192 /* Die maximale Anzahl an Zeichen, die 'msg' enhalten darf */
#define OPEN 1
#define CLOSE 0
#define TRUE 1
#define FALSE 0
#define OK 0
#define ERROR -1
struct Nagios_Env {
char varname[128];
char varvalue[128];
struct Nagios_Env *next;
};
/* function prototypes */
void print_list(int, struct Nagios_Env *);
int parse_env(char *, struct Nagios_Env **);
int process_env(char *[]);
int open_sock();
int process_arguments(int, char **);
void timeout_sighandler(int);
/* variable declaration*/
pid_t fork(void);
int socket_status = CLOSE;
int serverport = DEFAULT_SERVERPORT;
int timeout = 10; /* Default time out to 10 seconds */
char *serverip, *datatype;
char msg[MSG_SIZE]; /* Buffer for sending the message to remote server */
int main(int argc, char *argv[], char *envp[]) {
if (process_arguments(argc, argv) == ERROR)
exit(ERROR);
pid_t pid;
int error_code = 0;
switch (pid = fork()) {
case -1:
/* Here pid is -1, the fork failed */
/* Some possible reasons are that you're */
/* out of process slots or virtual memory */
perror("The fork failed!");
error_code = -1;
break;
case 0:
/* pid of zero is the child */
signal(SIGALRM, timeout_sighandler);
alarm(timeout);
process_env(envp);
_exit(0);
default:
/* pid greater than zero is parent getting the child's pid */
//printf("Child's pid is %d\n",pid);
error_code = 0;
}
exit(error_code);
}
void timeout_sighandler(int sig) {
/* force the child process to exit... */
fprintf(stderr, "Caught SIGALRM - timeout\n");
_exit(-1);
}
/***************************************************
* processing command line arguments
*
* Gets number of args and pointer reference to argv
***************************************************/
int process_arguments(int argc, char **argv) {
int c;
int error = FALSE;
int test_mode = FALSE;
int display_license = FALSE;
int display_help = FALSE;
#ifdef HAVE_GETOPT_H
int option_index=0;
static struct option long_options[]= {
{ "help",no_argument,0,'h'},
{ "version",no_argument,0,'V'},
{ "license",no_argument,0,'V'},
{ "test",no_argument,0,'t'},
{ "host",required_argument,0,'H'},
{ "port",required_argument,0,'p'},
{ "datatype",required_argument,0,'d'},
{ "timeout",required_argument,0,'t'},
{ 0,0,0,0}
};
#endif
/* make sure we have the correct number of command line arguments */
if (argc < 2)
error = TRUE;
while (1) {
#ifdef HAVE_GETOPT_H
c=getopt_long(argc,argv,"+hH:p:d:Vt:",long_options,&option_index);
#else
c = getopt(argc, argv, "+hH:p:d:Vt:");
#endif
if (c == -1 || c == EOF)
break;
switch (c) {
case '?': /* usage */
case 'h':
display_help = TRUE;
break;
case 'V': /* version */
display_license = TRUE;
break;
case 'H': /* host ip */
// ToDo: Check if it there
if (optarg != NULL) {
serverip = optarg;
} else
error = TRUE;
break;
case 'p': /* port to use */
// ToDo: Check for port
if (optarg != NULL)
serverport = atoi(optarg);
break;
case 'd': /* datatype like hostperfdata, serviceperfdata and so on */
if (optarg != NULL)
datatype = optarg;
else
error = TRUE;
break;
case 't': /* timeout */
if (optarg != NULL)
timeout = atoi(optarg);
else
error = TRUE;
break;
default:
break;
}
}
/* it makes no sense to do anything without a target host*/
if (serverip == NULL)
error = TRUE;
if (display_license == TRUE) {
printf(
"This program is free software; you can redistribute it and/or modify\n");
printf(
"it under the terms of the GNU General Public License version 2 as\n");
printf("published by the Free Software Foundation.\n\n");
printf(
"This program is distributed in the hope that it will be useful,\n");
printf(
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf(
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf("GNU General Public License for more details.\n\n");
printf(
"You should have received a copy of the GNU General Public License\n");
printf("along with this program; if not, write to the Free Software\n");
printf(
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n\n");
exit(OK);
}
/* if there are no command line options (or if we encountered an error), print usage */
if (error == TRUE || display_help == TRUE) {
printf(
"Usage: %s -H <serverip> [-p <serverport>] -d <datatype> -t <timeout>\n",
argv[0]);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -H | --host Host IP Address to send data to.\n");
printf("\n");
printf(
" -p | --port Host Port to send data to. (Default: tcp/1500)\n");
printf("\n");
printf(
" -t | --timeout Timeout value to kill process (Default: 10 seconds)\n");
printf("\n");
printf(" -d | --datatype Free string what this Data stands for\n");
printf(
" like \"serviceperfdata\", \"hostperfdata\", \"eventhandler\"\n");
printf("\n\n");
printf(
"Visit the PNP website at http://www.pnp4nagios.org/pnp/ for bug fixes, new\n");
printf(
"releases, online documentation, FAQs, information on subscribing to\n");
printf("the mailing lists.\n");
printf("\n");
exit(ERROR);
}
return OK;
}
int process_env(char *envp[]) {
int count = 0;
int socket;
struct Nagios_Env *base = NULL;
struct Nagios_Env *ptr = NULL;
while (1) {
if (socket_status == CLOSE) {
socket = open_sock(serverip);
}
if (envp[count] == NULL) {
break;
}
parse_env(envp[count], &base);
count++;
}
print_list(socket, base);
return (0);
}
void print_list(int socket, struct Nagios_Env *base) {
struct Nagios_Env *ptr = NULL;
char *message, dtype[BUFFER_SIZE];
int message_length = sizeof(struct Nagios_Env) - sizeof(ptr->next);
ptr = base;
strcat(dtype,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
strcat(dtype, "<NAGIOS>\n");
strcat(dtype, " <NAGIOS_DATATYPE>");
strcat(dtype, datatype);
strcat(dtype, "</NAGIOS_DATATYPE>\n");
if (send(socket, dtype, strlen(dtype), 0) == -1) {
fprintf(stderr, "error while sending request to server\n");
}
bzero((void *) dtype, BUFFER_SIZE);
while (ptr != NULL) {
if (!(message = (char *) malloc(sizeof(struct Nagios_Env)))) {
fprintf(stderr, "Cannot allocate memory for this message\n");
exit(ERROR);
}
strncat(message, " <", message_length);
strncat(message, ptr->varname, message_length);
strncat(message, ">", message_length);
strncat(message, ptr->varvalue, message_length);
strncat(message, "</", message_length);
strncat(message, ptr->varname, message_length);
strncat(message, ">\n", message_length);
message[message_length] = '\0';
if (send(socket, message, strlen(message), 0) == -1) {
fprintf(stderr, "error while sending request to server\n");
}
ptr = ptr->next;
}
strcat(dtype, "</NAGIOS>\n");
if (send(socket, dtype, strlen(dtype), 0) == -1) {
fprintf(stderr, "error while sending request to server\n");
}
}
int parse_env(char *curr, struct Nagios_Env **base) {
char tmpbuf[BUFFER_SIZE];
char *var1;
char *var2;
struct Nagios_Env *ptr = NULL;
ptr = *base;
strncpy(tmpbuf, curr, BUFFER_SIZE);
var1 = strtok(tmpbuf, "=");
var2 = strtok(NULL, "");
if (strncmp(var1, (char *) "NAGIOS_", 7) == 0) {
if (var2 != NULL) {
if (ptr == NULL) {
/* create first list element */
ptr = (struct Nagios_Env *) malloc(sizeof(struct Nagios_Env));
if (ptr == NULL)
return ERROR;
*base = ptr;
} else {
/* create a new list element */
/* first look for the end of list */
while (ptr->next != NULL)
ptr = ptr->next;
/* neues Listenelement erzeugen */
ptr->next = (struct Nagios_Env *) malloc(
sizeof(struct Nagios_Env));
if (ptr->next == NULL)
return ERROR;
ptr = ptr->next;
}
// Building dynamic list
strcpy(ptr->varname, var1);
strcpy(ptr->varvalue, var2);
ptr->next = NULL;
}
}
bzero((void *) tmpbuf, BUFFER_SIZE);
return (0);
}
int open_sock() {
int tosocket; /* the socket descriptor*/
/* description of struct sockaddr_in is mentioned in netinet/in.h */
struct sockaddr_in toaddr; /* store address of server here */
/* create tcp socket */
tosocket = socket(PF_INET, SOCK_STREAM, 0);
if (tosocket == -1) {
fprintf(stderr, "cannot open socket\n");
exit(1);
}
/* define server address */
toaddr.sin_family = PF_INET;
toaddr.sin_addr.s_addr = inet_addr(serverip);
toaddr.sin_port = htons(serverport);
/* connect to server */
if (connect(tosocket, (struct sockaddr *) &toaddr, sizeof(toaddr)) == -1) {
fprintf(stderr,
"Unable to connect to server '%s' on port %d. Exiting...\n",
serverip, serverport);
close(tosocket);
exit(1);
} else {
socket_status = OPEN;
return tosocket;
}
return -1;
}

228
src/utils.c Normal file
View File

@@ -0,0 +1,228 @@
// Copyright (C) 2006-2009 Hendrik Baecker <andurin@process-zero.de>
//
// 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
#include "../include/config.h"
#include "../include/pnp.h"
extern int prepare_vars();
extern int thread_counter;
extern int max_threads;
extern int daemon_mode;
extern int loglevel;
extern int use_syslog;
int sighup_detected = FALSE;
extern char** command;
extern char *command_args;
extern char *user;
extern char *group;
extern char *directory;
extern char *macro_x;
extern char *config_file;
extern char buffer[MAX_LOGMESSAGE_SIZE];
extern void process_configfile(char *);
extern int check_needed_config_options(void);
typedef void (*sighandler_t)(int);
// This function has special copyright!!!
/* Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) */
/* strip newline, carriage return, and tab characters from beginning and end of a string */
void pnp_strip(char *buffer) {
register int x;
register int y;
register int z;
if (buffer == NULL || buffer[0] == '\x0')
return;
/* strip end of string */
y = (int) strlen(buffer);
for (x = y - 1; x >= 0; x--) {
if (buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r'
|| buffer[x] == '\t' || buffer[x] == 13)
buffer[x] = '\x0';
else
break;
}
/* strip beginning of string (by shifting) */
y = (int) strlen(buffer);
for (x = 0; x < y; x++) {
if (buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r'
|| buffer[x] == '\t' || buffer[x] == 13)
continue;
else
break;
}
if (x > 0) {
for (z = x; z < y; z++)
buffer[z - x] = buffer[z];
buffer[y - x] = '\x0';
}
return;
}
/******************************************************************/
/*********************** SECURITY FUNCTIONS ***********************/
/******************************************************************/
/* drops privileges */
int drop_privileges(char *user, char *group) {
uid_t uid = -1;
gid_t gid = -1;
struct group *grp = NULL;
struct passwd *pw = NULL;
int result = OK;
/* only drop privileges if we're running as root, so we don't interfere with being debugged while running as some random user */
if (getuid() != 0)
return OK;
/* set effective group ID */
if (group != NULL) {
/* see if this is a group name */
if (strspn(group, "0123456789") < strlen(group)) {
grp = (struct group *) getgrnam(group);
if (grp != NULL) {
gid = (gid_t) (grp->gr_gid);
} else {
printf("Warning: Could not get group entry for '%s'\n", group);
}
}
/* else we were passed the GID */
else
gid = (gid_t) atoi(group);
/* set effective group ID if other than current EGID */
if (gid != getegid()) {
if (setgid(gid) == -1) {
printf("Warning: Could not set effective GID=%d\n", (int) gid);
result = ERROR;
}
}
}
/* set effective user ID */
if (user != NULL) {
/* see if this is a user name */
if (strspn(user, "0123456789") < strlen(user)) {
pw = (struct passwd *) getpwnam(user);
if (pw != NULL)
uid = (uid_t) (pw->pw_uid);
else {
printf("Warning: Could not get passwd entry for '%s'\n", user);
}
}
/* else we were passed the UID */
else
uid = (uid_t) atoi(user);
#ifdef HAVE_INITGROUPS
if(uid!=geteuid()) {
/* initialize supplementary groups */
if(initgroups(user,gid)==-1) {
if(errno==EPERM) {
printf("Warning: Unable to change supplementary groups using initgroups() -- I hope you know what you're doing\n");
}
else {
printf("Warning: Possibly root user failed dropping privileges with initgroups()\n");
return ERROR;
}
}
}
#endif
if (setuid(uid) == -1) {
printf("Warning: Could not set effective UID=%d\n", (int) uid);
result = ERROR;
}
}
return result;
}
/*******************
*
* Signal functions
*
*******************/
sighandler_t handle_signal(int sig_nr, sighandler_t signalhandler) {
struct sigaction new_sig, old_sig;
new_sig.sa_handler = signalhandler;
sigemptyset(&new_sig.sa_mask);
new_sig.sa_flags = SA_RESTART;
if (sigaction(sig_nr, &new_sig, &old_sig) < 0)
return SIG_ERR;
return old_sig.sa_handler;
}
void check_sig(int signr) {
char buffer[MAX_LOGMESSAGE_SIZE];
switch (signr) {
case SIGINT:
LOG(0, "Caught SIGINT - Good bye\n");
exit(EXIT_SUCCESS);
break;
case SIGTERM:
LOG(0, "Caught Termination Signal - Astalavista... baby\n");
exit(EXIT_SUCCESS);
break;
case SIGHUP:
LOG(0, "Caught SIGHUP - reloading configuration\n");
sighup_detected = TRUE;
process_configfile(config_file);
if (check_needed_config_options() != 0) {
LOG(0, "There is an error in the config! Exiting...\n");
exit(EXIT_FAILURE);
}
prepare_vars();
LOG(0, "Configuration reload succesfull.\n");
break;
default:
snprintf(buffer, sizeof(buffer - 1),
"Caught the Signal '%d' but don't care about this.\n", signr);
LOG(2, buffer);
break;
}
}
/* This won't compile on Solaris and HP UX */
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
int is_file(const struct dirent *d) {
if (d->d_type == DT_REG)
return 1;
//free(d);
return 0;
}
#endif