diff --git a/samples/mustach.template b/samples/mustach.template index 3c0db39..669910d 100644 --- a/samples/mustach.template +++ b/samples/mustach.template @@ -65,3 +65,9 @@ lease_file_epoch_mtime: {{lease_file_epoch_mtime}} template_file_path: {{template_file_path}} template_file_local_mtime: {{template_file_local_mtime}} template_file_epoch_mtime: {{template_file_epoch_mtime}} + +number_of_ranges_warning: {{number_of_ranges_warning}} +number_of_ranges_critical: {{number_of_ranges_critical}} +number_of_shared_networks: {{number_of_shared_networks}} +number_of_shared_networks_warning: {{number_of_shared_networks_warning}} +number_of_shared_networks_critical: {{number_of_shared_networks_critical}} diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index 2bb365c..36ec255 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -155,6 +155,16 @@ struct output_helper_t { uint32_t pad; }; +/*! \struct status_counts_t + * \brief Range and shared network alarming status counts. + */ +struct status_counts_t { + unsigned int warning; + unsigned int critical; + unsigned int ok; + unsigned int ignored; +}; + /*! \enum ltype * \brief Lease state types. These are the possible values in struct leases_t. */ @@ -320,6 +330,8 @@ extern int range_output_helper(struct conf_t *state, struct output_helper_t *oh, extern int shnet_output_helper(struct conf_t *state, struct output_helper_t *oh, struct shared_network_t *shared_p); extern int output_analysis(struct conf_t *state); +extern void range_alarms(struct conf_t *state, struct status_counts_t *rangstat); +extern void shared_net_alarms(struct conf_t *state, struct status_counts_t *sharstat); /* sort.c */ extern void mergesort_ranges(struct conf_t *state, diff --git a/src/mustach-dhcpd-pools.c b/src/mustach-dhcpd-pools.c index 00e1b8b..4e25346 100644 --- a/src/mustach-dhcpd-pools.c +++ b/src/mustach-dhcpd-pools.c @@ -82,21 +82,45 @@ static int must_put_base(void *closure, const char *name, int escape fprintf(file, "%u", e->state->num_ranges); return 0; } + if (!strcmp(name, "number_of_ranges_warning")) { + struct status_counts_t stat = { 0 }; + + range_alarms(e->state, &stat); + fprintf(file, "%u", stat.warning); + return 0; + } + if (!strcmp(name, "number_of_ranges_critical")) { + struct status_counts_t stat = { 0 }; + + range_alarms(e->state, &stat); + fprintf(file, "%u", stat.critical); + return 0; + } if (!strcmp(name, "number_of_shared_networks")) { - static uint32_t num = 0xffffffff; + uint32_t num = 0; + struct shared_network_t *shared_p; - if (num == 0xffffffff) { - /* Use of static num ensures this is done only once. */ - struct shared_network_t *shared_p; - - num = 0; - for (shared_p = e->state->shared_net_root->next; shared_p; - shared_p = shared_p->next) - num++; + for (shared_p = e->state->shared_net_root->next; shared_p; + shared_p = shared_p->next) { + num++; } fprintf(file, "%u", num); return 0; } + if (!strcmp(name, "number_of_shared_networks_warning")) { + struct status_counts_t stat = { 0 }; + + shared_net_alarms(e->state, &stat); + fprintf(file, "%u", stat.warning); + return 0; + } + if (!strcmp(name, "number_of_shared_networks_critical")) { + struct status_counts_t stat = { 0 }; + + shared_net_alarms(e->state, &stat); + fprintf(file, "%u", stat.critical); + return 0; + } if (!strcmp(name, "version")) { fprintf(file, "%s", PACKAGE_VERSION); return 0; diff --git a/src/output.c b/src/output.c index 275e431..bc20d18 100644 --- a/src/output.c +++ b/src/output.c @@ -1024,19 +1024,11 @@ static int output_csv(struct conf_t *state) return 0; } -/*! \brief Output alarm text, and return program exit value. */ -static int output_alarming(struct conf_t *state) +void range_alarms(struct conf_t *state, struct status_counts_t *rangstat) { - FILE *outfile; - struct range_t *range_p; - struct shared_network_t *shared_p; struct output_helper_t oh; + struct range_t *range_p = state->ranges; unsigned int i; - int rw = 0, rc = 0, ro = 0, ri = 0, sw = 0, sc = 0, so = 0, si = 0; - int ret_val; - - outfile = open_outfile(state); - range_p = state->ranges; if (state->number_limit & R_BIT) { for (i = 0; i < state->num_ranges; i++) { @@ -1045,16 +1037,16 @@ static int output_alarming(struct conf_t *state) case STATUS_SUPPRESSED: break; case STATUS_IGNORED: - ri++; + rangstat->ignored++; break; case STATUS_CRIT: - rc++; + rangstat->critical++; break; case STATUS_WARN: - rw++; + rangstat->warning++; break; case STATUS_OK: - ro++; + rangstat->ok++; break; default: abort(); @@ -1062,6 +1054,13 @@ static int output_alarming(struct conf_t *state) range_p++; } } +} + +void shared_net_alarms(struct conf_t *state, struct status_counts_t *sharstat) +{ + struct output_helper_t oh; + struct shared_network_t *shared_p; + if (state->number_limit & S_BIT) { for (shared_p = state->shared_net_root->next; shared_p; shared_p = shared_p->next) { shnet_output_helper(state, &oh, shared_p); @@ -1069,35 +1068,51 @@ static int output_alarming(struct conf_t *state) case STATUS_SUPPRESSED: break; case STATUS_IGNORED: - si++; + sharstat->ignored++; break; case STATUS_CRIT: - sc++; + sharstat->critical++; break; case STATUS_WARN: - sw++; + sharstat->warning++; break; case STATUS_OK: - so++; + sharstat->ok++; break; default: abort(); } } } +} - if (sc || rc) + +/*! \brief Output alarm text, and return program exit value. */ +static int output_alarming(struct conf_t *state) +{ + FILE *outfile; + unsigned int i; + int ret_val; + struct status_counts_t rangstat = { 0 }; + struct status_counts_t sharstat = { 0 }; + + outfile = open_outfile(state); + + range_alarms(state, &rangstat); + shared_net_alarms(state, &sharstat); + + if (rangstat.critical || sharstat.critical) ret_val = STATE_CRITICAL; - else if (sw || rw) + else if (rangstat.warning || sharstat.warning) ret_val = STATE_WARNING; else ret_val = STATE_OK; - if ((0 < rc && state->number_limit & R_BIT) - || (0 < sc && state->number_limit & S_BIT)) { + if ((0 < rangstat.critical && state->number_limit & R_BIT) + || (0 < sharstat.critical && state->number_limit & S_BIT)) { fprintf(outfile, "CRITICAL: %s:", program_name); - } else if ((0 < rw && state->number_limit & R_BIT) - || (0 < sw && state->number_limit & S_BIT)) { + } else if ((0 < rangstat.warning && state->number_limit & R_BIT) + || (0 < sharstat.warning && state->number_limit & S_BIT)) { fprintf(outfile, "WARNING: %s:", program_name); } else { if (state->number_limit & A_BIT) @@ -1110,17 +1125,21 @@ static int output_alarming(struct conf_t *state) } } if (state->header_limit & R_BIT) { - fprintf(outfile, " Ranges - crit: %d warn: %d ok: %d", rc, rw, ro); - if (ri != 0) { - fprintf(outfile, " ignored: %d", ri); + fprintf(outfile, " Ranges - crit: %d warn: %d ok: %d", rangstat.critical, rangstat.warning, rangstat.ok); + if (rangstat.ignored != 0) { + fprintf(outfile, " ignored: %d", rangstat.ignored); } - fprintf(outfile, "; | range_crit=%d range_warn=%d range_ok=%d", rc, rw, ro); - if (ri != 0) { - fprintf(outfile, " range_ignored=%d", ri); + fprintf(outfile, "; | range_crit=%d range_warn=%d range_ok=%d", rangstat.critical, rangstat.warning, rangstat.ok); + if (rangstat.ignored != 0) { + fprintf(outfile, " range_ignored=%d", rangstat.ignored); } if (state->perfdata == 1 && state->number_limit & R_BIT) { - for (i = 0; i < state->num_ranges; i++) { - range_p--; + /* last to first order. too late to fix this after so many years */ + struct range_t *range_p = state->ranges + state->num_ranges - 1; + + for (i = state->num_ranges; i; i--) { + struct output_helper_t oh; + if (range_output_helper(state, &oh, range_p)) continue; if (state->minsize < oh.range_size) { @@ -1137,6 +1156,7 @@ static int output_alarming(struct conf_t *state) range_p->backups); } } + range_p--; } } fprintf(outfile, "\n"); @@ -1144,16 +1164,20 @@ static int output_alarming(struct conf_t *state) fprintf(outfile, " "); } if (state->header_limit & S_BIT) { - fprintf(outfile, "Shared nets - crit: %d warn: %d ok: %d", sc, sw, so); - if (si != 0) { - fprintf(outfile, " ignored: %d", si); + fprintf(outfile, "Shared nets - crit: %d warn: %d ok: %d", sharstat.critical, sharstat.warning, sharstat.ok); + if (sharstat.ignored != 0) { + fprintf(outfile, " ignored: %d", sharstat.ignored); } - fprintf(outfile, "; | snet_crit=%d snet_warn=%d snet_ok=%d", sc, sw, so); - if (si != 0) { - fprintf(outfile, " snet_ignored=%d", si); + fprintf(outfile, "; | snet_crit=%d snet_warn=%d snet_ok=%d", sharstat.critical, sharstat.warning, sharstat.ok); + if (sharstat.ignored != 0) { + fprintf(outfile, " snet_ignored=%d", sharstat.ignored); } if (state->perfdata == 1 && state->header_limit & R_BIT) { + struct shared_network_t *shared_p; + for (shared_p = state->shared_net_root->next; shared_p; shared_p = shared_p->next) { + struct output_helper_t oh; + if (shnet_output_helper(state, &oh, shared_p)) continue; if (state->minsize < shared_p->available) { diff --git a/tests/expected/mustach b/tests/expected/mustach index dddecb0..a8942c6 100644 --- a/tests/expected/mustach +++ b/tests/expected/mustach @@ -120,6 +120,12 @@ number_of_shared_networks: 2 + +number_of_ranges_warning: 0 +number_of_ranges_critical: 0 +number_of_shared_networks: 2 +number_of_shared_networks_warning: 0 +number_of_shared_networks_critical: 0 --- skip ok --- Subnets: location: example1 @@ -201,3 +207,9 @@ number_of_shared_networks: 2 + +number_of_ranges_warning: 3 +number_of_ranges_critical: 0 +number_of_shared_networks: 2 +number_of_shared_networks_warning: 1 +number_of_shared_networks_critical: 0