diff --git a/man/dhcpd-pools.1 b/man/dhcpd-pools.1 index 3d7188c..80bb632 100644 --- a/man/dhcpd-pools.1 +++ b/man/dhcpd-pools.1 @@ -129,6 +129,25 @@ Print total summary header .PD .RE .TP +\fB\-\-warning\fR=\fIpercent\fR +Turn on alarm output format, and specify percentage number which will +cause an alarm. If either a range or shared network will exceed +warning level return value of the command is +.BR 1 . +If critical level is not speficied it defaults to +.BR 90 . +The +.I percent +argument allows fractions to be used. Alarm output is intented to be +used with monitoring, such as Nagios. +.TP +\fB\-\-critical\fR=\fIpercent\fR +The option is similar to warning, with exception of return value which +is +.BR 2 . +If warning level is not specified it defaults to +.BR 80 . +.TP \fB\-v\fR, \fB\-\-version\fR Print version information to standard output and exit successfully. .TP diff --git a/src/defaults.h b/src/defaults.h index 76e1ec5..6d0a9c5 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -45,4 +45,8 @@ static const unsigned int SHARED_NETWORKS = 8192; /* Maximum number of ranges */ unsigned int RANGES; +/* Alarming defaults */ +#define ALARM_WARN 80 +#define ALARM_CRIT 90 + #endif /* DEFAULTS_H */ diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 6488657..7a2313a 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -52,6 +52,7 @@ extern char *malloc(); #include #include #include +#include #include "defaults.h" #include "dhcpd-pools.h" @@ -62,6 +63,11 @@ int main(int argc, char **argv) int option_index = 0; char *tmp; struct range_t *tmp_ranges; + enum { + OPT_WARN = CHAR_MAX + 1, + OPT_CRIT + }; + int ret_val; /* Options for getopt_long */ static struct option const long_options[] = { @@ -74,6 +80,8 @@ int main(int argc, char **argv) {"limit", required_argument, NULL, 'L'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, + {"warning", required_argument, NULL, OPT_WARN}, + {"critical", required_argument, NULL, OPT_CRIT}, {NULL, 0, NULL, 0} }; @@ -87,6 +95,9 @@ int main(int argc, char **argv) /* Make sure string has zero lenght if there is no * command line option */ config.output_file[0] = '\0'; + /* Alarming defaults. */ + config.warning = ALARM_WARN; + config.critical = ALARM_CRIT; /* File location defaults */ strncpy(config.dhcpdconf_file, DHCPDCONF_FILE, MAXLEN - 1); @@ -160,6 +171,14 @@ int main(int argc, char **argv) } } break; + case OPT_WARN: + strcpy(config.output_format, "a"); + config.warning = strtod_or_err(optarg, "illegal argument"); + break; + case OPT_CRIT: + strcpy(config.output_format, "a"); + config.critical = strtod_or_err(optarg, "illegal argument"); + break; case 'v': /* Print version */ print_version(); @@ -178,6 +197,9 @@ int main(int argc, char **argv) case 't': output_analysis = output_txt; break; + case 'a': + output_analysis = output_alarming; + break; case 'h': output_analysis = output_html; break; @@ -214,10 +236,10 @@ int main(int argc, char **argv) flip_ranges(ranges, tmp_ranges); } free(tmp_ranges); - output_analysis(); + ret_val = output_analysis(); clean_up(); - return (EXIT_SUCCESS); + return (ret_val); } /* Global allocations, counter resets etc */ diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index bd4d34f..c9559d1 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -102,6 +102,8 @@ struct configuration_t { int reverse_order; char *output_file; int output_limit[2]; + double warning; + double critical; }; struct shared_network_t { char *name; @@ -177,6 +179,7 @@ void *safe_malloc(const size_t size) void *safe_realloc(void *__restrict ptr, const size_t size); char *safe_strdup(const char *__restrict str) __attribute__ ((nonnull(1))); int xstrstr(char *__restrict a, char *__restrict b, int len); +double strtod_or_err(const char *__restrict str, const char *__restrict errmesg); int close_stream(FILE * stream); void close_stdout(void); void print_version(void) __attribute__ ((noreturn)); @@ -207,6 +210,7 @@ int output_txt(void); int output_html(void); int output_xml(void); int output_csv(void); +int output_alarming(void); /* Memory release, file closing etc */ void clean_up(void); /* Hash functions */ diff --git a/src/other.c b/src/other.c index f71c55f..5551ce3 100644 --- a/src/other.c +++ b/src/other.c @@ -136,6 +136,28 @@ char *safe_strdup(const char *restrict str) return ret; } +/* Return percentage value */ +double strtod_or_err(const char *str, const char *errmesg) +{ + double num; + char *end = NULL; + + if (str == NULL || *str == '\0') + goto err; + errno = 0; + num = strtod(str, &end); + + if (errno || str == end || (end && *end)) + goto err; + + return num; + err: + if (errno) + err(EXIT_FAILURE, "%s: '%s'", errmesg, str); + + errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); +} + void flip_ranges(struct range_t *restrict ranges, struct range_t *restrict tmp_ranges) { unsigned int i = num_ranges - 1, j; @@ -237,6 +259,9 @@ This is ISC dhcpd pools usage analyzer.\n\ -o, --output=FILE output into a file\n\ -L, --limit=NR output limit mask 77 - 00\n"); fprintf(out, "\ + --warning=PERC set warning alarming limit\n\ + --critical=PERC set critical alarming limit\n"); + fprintf(out, "\ -v, --version version information\n\ -h, --help this screen\n\ \n\ diff --git a/src/output.c b/src/output.c index 7e03bf5..9a4f312 100644 --- a/src/output.c +++ b/src/output.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -788,3 +789,87 @@ int output_csv(void) } return 0; } + +int output_alarming(void) +{ + FILE *outfile; + struct range_t *range_p; + struct shared_network_t *shared_p; + int i; + float perc; + int rw = 0, rc = 0, ro = 0, sw = 0, sc = 0, so = 0; + int ret_val, ret; + + range_p = ranges; + shared_p = shared_networks; + + if (config.output_file[0]) { + outfile = fopen(config.output_file, "w+"); + if (outfile == NULL) { + err(EXIT_FAILURE, "output_alarming: %s", + config.output_file); + } + } else { + outfile = stdout; + } + + if (config.output_limit[1] & output_limit_bit_1) { + for (i = 0; i < num_ranges; i++) { + perc = (float)(100 * range_p->count) / + (range_p->last_ip - range_p->first_ip - 1); + if (config.critical < perc) + rc++; + else if (config.warning < perc) + rw++; + else + ro++; + range_p++; + } + } + if (config.output_limit[1] & output_limit_bit_2) { + for (i = 0; i < num_shared_networks; i++) { + perc = (float)(100 * shared_p->used) / + shared_p->available; + if (config.critical < perc) + sc++; + else if (config.warning < perc) + sw++; + else + so++; + shared_p++; + } + } + if (0 < rc || 0 < sc) { + ret_val = 2; + fprintf(outfile, "CRITICAL: %s: ", + program_invocation_short_name); + } else if (0 < rw || 0 < sw) { + ret_val = 1; + fprintf(outfile, "WARNING: %s: ", + program_invocation_short_name); + } else { + ret_val = 0; + fprintf(outfile, "OK: "); + } + if (config.output_limit[0] & output_limit_bit_1) { + fprintf(outfile, "Ranges; crit: %d warn: %d ok: %d ", rc, rw, + ro); + } + if (config.output_limit[0] & output_limit_bit_2) { + fprintf(outfile, "Shared nets; crit: %d warn: %d ok: %d", sc, + sw, so); + } + fprintf(outfile, "\n"); + if (outfile == stdout) { + ret = fflush(stdout); + if (ret) { + warn("output_alarming: fflush"); + } + } else { + ret = close_stream(outfile); + if (ret) { + warn("output_alarming: fclose"); + } + } + return ret_val; +}