/* * The dhcpd-pools has BSD 2-clause license which also known as "Simplified * BSD License" or "FreeBSD License". * * Copyright 2006- Sami Kerola. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of Sami Kerola. */ /*! \file output.c * \brief All about output formats. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "close-stream.h" #include "error.h" #include "progname.h" #include "strftime.h" #include "dhcpd-pools.h" /*! \brief Text output format, which is the default. */ int output_txt(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; int max_ipaddr_length = config.ip_version == IPv6 ? 39 : 16; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_txt: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.header_limit & R_BIT) { fprintf(outfile, "Ranges:\n"); fprintf (outfile, "%-20s%-*s %-*s %5s %5s %10s %5s %5s %9s", "shared net name", max_ipaddr_length, "first ip", max_ipaddr_length, "last ip", "max", "cur", "percent", "touch", "t+c", "t+c perc"); if (config.backups_found == 1) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.number_limit & R_BIT) { for (i = 0; i < num_ranges; i++) { if (range_p->shared_net) { fprintf(outfile, "%-20s", range_p->shared_net->name); } else { fprintf(outfile, "not_defined "); } /* Outputting of first_ip and last_ip need to be * separate since ntop_ipaddr always returns the * same buffer */ fprintf(outfile, "%-*s", max_ipaddr_length, ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, " - %-*s %5g %5g %10.3f %5g %5g %9.3f", max_ipaddr_length, ntop_ipaddr(&range_p->last_ip), range_size, range_p->count, (float)(100 * range_p->count) / range_size, range_p->touched, range_p->touched + range_p->count, (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == 1) { fprintf(outfile, "%7g %8.3f", range_p->backups, (float)(100 * range_p->backups) / range_size); } fprintf(outfile, "\n"); range_p++; range_size = get_range_size(range_p); } } if (config.number_limit & R_BIT && config.header_limit & S_BIT) { fprintf(outfile, "\n"); } if (config.header_limit & S_BIT) { fprintf(outfile, "Shared networks:\n"); fprintf(outfile, "name max cur percent touch t+c t+c perc"); if (config.backups_found == 1) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.number_limit & S_BIT) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "%-20s %5g %5g %10.3f %7g %6g %9.3f", shared_p->name, shared_p->available, shared_p->used, shared_p->available == 0 ? NAN : (float)(100 * shared_p->used) / shared_p->available, shared_p->touched, shared_p->touched + shared_p->used, shared_p->available == 0 ? NAN : ((float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available)); if (config.backups_found == 1) { fprintf(outfile, "%7g %8.3f", shared_p->backups, (float)(100 * shared_p->backups) / shared_p->available); } fprintf(outfile, "\n"); } } if (config.number_limit & S_BIT && config.header_limit & A_BIT) { fprintf(outfile, "\n"); } if (config.header_limit & A_BIT) { fprintf(outfile, "Sum of all ranges:\n"); fprintf(outfile, "name max cur percent touch t+c t+c perc"); if (config.backups_found == 1) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.number_limit & A_BIT) { fprintf(outfile, "%-20s %5g %5g %10.3f %7g %6g %9.3f", shared_networks->name, shared_networks->available, shared_networks->used, shared_networks->available == 0 ? NAN : (float)(100 * shared_networks->used) / shared_networks->available, shared_networks->touched, shared_networks->touched + shared_networks->used, shared_networks->available == 0 ? NAN : (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == 1) { fprintf(outfile, "%7g %8.3f", shared_networks->available == 0 ? NAN : shared_networks->backups, (float)(100 * shared_networks->backups) / shared_networks->available); } fprintf(outfile, "\n"); } if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_txt: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_txt: fclose"); } } return 0; } /*! \brief The xml output formats. */ int output_xml(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_xml: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; fprintf(outfile, "\n"); if (config.print_mac_addreses == 1) { struct leases_t *l; for (l = leases; l != NULL; l = l->hh.next) { if (l->type == ACTIVE) { fputs("\n\t", outfile); fputs(ntop_ipaddr(&l->ip), outfile); fputs("\n\t", outfile); if (l->ethernet != NULL) { fputs(l->ethernet, outfile); } fputs("\n\n", outfile); } } } if (config.number_limit & R_BIT) { for (i = 0; i < num_ranges; i++) { fprintf(outfile, "\n"); if (range_p->shared_net) { fprintf(outfile, "\t%s\n", range_p->shared_net->name); } else { fprintf(outfile, "\t\n"); } fprintf(outfile, "\t%s ", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, "- %s\n", ntop_ipaddr(&range_p->last_ip)); fprintf(outfile, "\t%g\n", range_size); fprintf(outfile, "\t%g\n", range_p->count); fprintf(outfile, "\t%g\n", range_p->touched); fprintf(outfile, "\t%g\n", range_size - range_p->count); range_p++; range_size = get_range_size(range_p); fprintf(outfile, "\n"); } } if (config.number_limit & S_BIT) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "\n"); fprintf(outfile, "\t%s\n", shared_p->name); fprintf(outfile, "\t%g\n", shared_p->available); fprintf(outfile, "\t%g\n", shared_p->used); fprintf(outfile, "\t%g\n", shared_p->touched); fprintf(outfile, "\t%g\n", shared_p->available - shared_p->used); fprintf(outfile, "\n"); } } if (config.header_limit & A_BIT) { fprintf(outfile, "\n"); fprintf(outfile, "\t%s\n", shared_networks->name); fprintf(outfile, "\t%g\n", shared_networks->available); fprintf(outfile, "\t%g\n", shared_networks->used); fprintf(outfile, "\t%g\n", shared_networks->touched); fprintf(outfile, "\t%g\n", shared_networks->available - shared_networks->used); fprintf(outfile, "\n"); } fprintf(outfile, "\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_xml: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_xml: fclose"); } } return 0; } /*! \brief The json output formats. */ int output_json(void) { unsigned int i = 0; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; unsigned int sep; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_json: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; sep = 0; fprintf(outfile, "{\n"); if (config.print_mac_addreses == 1) { struct leases_t *l; fprintf(outfile, " \"active_leases\": ["); for (l = leases; l != NULL; l = l->hh.next) { if (l->type == ACTIVE) { if (i == 0) { i = 1; } else { fputc(',', outfile); } fputs("\n { \"ip\":\"", outfile); fputs(ntop_ipaddr(&l->ip), outfile); fputs("\", \"macaddress\":\"", outfile); if (l->ethernet != NULL) { fputs(l->ethernet, outfile); } fputs("\" }", outfile); } } fprintf(outfile, "\n ]"); /* end of active_leases */ sep++; } if (config.number_limit & R_BIT) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"subnets\": [\n"); for (i = 0; i < num_ranges; i++) { fprintf(outfile, " "); fprintf(outfile, "{ "); if (range_p->shared_net) { fprintf(outfile, "\"location\":\"%s\", ", range_p->shared_net->name); } else { fprintf(outfile, "\"location\":\"\", "); } fprintf(outfile, "\"range\":\"%s", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, " - %s\", ", ntop_ipaddr(&range_p->last_ip)); fprintf(outfile, "\"defined\":%g, ", range_size); fprintf(outfile, "\"used\":%g, ", range_p->count); fprintf(outfile, "\"touched\":%g, ", range_p->touched); fprintf(outfile, "\"free\":%g ", range_size - range_p->count); range_p++; range_size = get_range_size(range_p); if (i + 1 < num_ranges) fprintf(outfile, "},\n"); else fprintf(outfile, "}\n"); } fprintf(outfile, " ]"); /* end of subnets */ sep++; } if (config.number_limit & S_BIT) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"shared-networks\": [\n"); for (i = 0; i < num_shared_networks; i++) { fprintf(outfile, " "); shared_p++; fprintf(outfile, "{ "); fprintf(outfile, "\"location\":\"%s\", ", shared_p->name); fprintf(outfile, "\"defined\":%g, ", shared_p->available); fprintf(outfile, "\"used\":%g, ", shared_p->used); fprintf(outfile, "\"touched\":%g, ", shared_p->touched); fprintf(outfile, "\"free\":%g ", shared_p->available - shared_p->used); if (i + 1 < num_shared_networks) fprintf(outfile, "},\n"); else fprintf(outfile, "}\n"); } fprintf(outfile, " ]"); /* end of shared-networks */ sep++; } if (config.header_limit & A_BIT) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"summary\": {\n"); fprintf(outfile, " \"location\":\"%s\",\n", shared_networks->name); fprintf(outfile, " \"defined\":%g,\n", shared_networks->available); fprintf(outfile, " \"used\":%g,\n", shared_networks->used); fprintf(outfile, " \"touched\":%g,\n", shared_networks->touched); fprintf(outfile, " \"free\":%g\n", shared_networks->available - shared_networks->used); fprintf(outfile, " }"); /* end of summary */ } fprintf(outfile, "\n}\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_json: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_json: fclose"); } } return 0; } /*! \brief Header for full html output format. * * \param f Output file descriptor. */ static void html_header(FILE *restrict f) { char outstr[200]; struct tm *tmp, result; struct stat statbuf; stat(config.dhcpdlease_file, &statbuf); tmp = localtime_r(&statbuf.st_mtime, &result); if (tmp == NULL) { error(EXIT_FAILURE, errno, "html_header: localtime"); } setlocale(LC_CTYPE, ""); setlocale(LC_NUMERIC, ""); if (strftime(outstr, sizeof(outstr), nl_langinfo(D_T_FMT), &result) == 0) { error(EXIT_FAILURE, 0, "html_header: strftime returned 0"); } fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "ISC dhcpd dhcpd-pools output\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, ""); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "
\n"); fprintf(f, "

ISC DHCPD status

\n"); fprintf(f, "File %s was last modified at %s
\n", config.dhcpdlease_file, outstr); } /*! \brief Footer for full html output format. * * \param f Output file descriptor. */ static void html_footer(FILE *restrict f) { fprintf(f, "
\n"); fprintf(f, "Generated using %s
\n", PACKAGE_STRING); fprintf(f, "More info at %s\n", PACKAGE_URL, PACKAGE_URL); fprintf(f, "
\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); } /*! \brief Start a html tag. * * \param f Output file descriptor. * \param tag The html tag. */ static void start_tag(FILE *restrict f, char const *restrict tag) { fprintf(f, "<%s>\n", tag); } /*! \brief End a html tag. * * \param f Output file descriptor. * \param tag The html tag. */ static void end_tag(FILE *restrict f, char const *restrict tag) { fprintf(f, "\n", tag); } /*! \brief Line with text in html output format. * * \param f Output file descriptor. * \param type HTML tag name. * \param class How the data is aligned. * \param text Actual payload of the printout. */ static void output_line(FILE *restrict f, char const *restrict type, char const *restrict text) { fprintf(f, "<%s>%s\n", type, text, type); } /*! \brief Line with digit in html output format. * * \param f Output file descriptor. * \param type HMTL tag name. * \param d Actual payload of the printout. */ static void output_double(FILE *restrict f, char const *restrict type, double d) { fprintf(f, "<%s>%g\n", type, d, type); } /*! \brief Line with float in html output format. * * \param f Output file descriptor. * \param type HTML tag name. * \param fl Actual payload of the printout. */ static void output_float(FILE *restrict f, char const *restrict type, float fl) { fprintf(f, "<%s>%.3f\n", type, fl, type); } /*! \brief Begin table in html output format. * * \param f Output file descriptor. */ static void table_start(FILE *restrict f, char const *restrict id, char const *restrict summary) { fprintf(f, "\n", id, summary); } /*! \brief End table in html output format. * * \param f Output file descriptor. */ static void table_end(FILE *restrict f) { fprintf(f, "
\n"); } /*! \brief New section in html output format. * * \param f Output file descriptor. * \param title Table title. */ static void newsection(FILE *restrict f, char const *restrict title) { output_line(f, "h3", title); } /*! \brief Output html format. */ int output_html(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_html: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; html_header(outfile); newsection(outfile, "Sum of all"); table_start(outfile, "a", "all"); if (config.header_limit & A_BIT) { start_tag(outfile, "thead"); start_tag(outfile, "tr"); output_line(outfile, "th", "name"); output_line(outfile, "th", "max"); output_line(outfile, "th", "cur"); output_line(outfile, "th", "percent"); output_line(outfile, "th", "touch"); output_line(outfile, "th", "t+c"); output_line(outfile, "th", "t+c perc"); if (config.backups_found == 1) { output_line(outfile, "th", "bu"); output_line(outfile, "th", "bu perc"); } end_tag(outfile, "tr"); end_tag(outfile, "thead"); } if (config.number_limit & A_BIT) { start_tag(outfile, "tbody"); start_tag(outfile, "tr"); output_line(outfile, "td", shared_networks->name); output_double(outfile, "td", shared_networks->available); output_double(outfile, "td", shared_networks->used); output_float(outfile, "td", shared_networks->available == 0 ? NAN : (float)(100 * shared_networks->used) / shared_networks->available); output_double(outfile, "td", shared_networks->touched); output_double(outfile, "td", shared_networks->touched + shared_networks->used); output_float(outfile, "td", shared_networks->available == 0 ? NAN : (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == 1) { output_double(outfile, "td", shared_networks->backups); output_float(outfile, "td", shared_networks->available == 0 ? NAN : (float)(100 * shared_networks->backups) / shared_networks->available); } end_tag(outfile, "tr"); end_tag(outfile, "tbody"); } table_end(outfile); newsection(outfile, "Shared networks"); table_start(outfile, "s", "snet"); if (config.header_limit & S_BIT) { start_tag(outfile, "thead"); start_tag(outfile, "tr"); output_line(outfile, "th", "name"); output_line(outfile, "th", "max"); output_line(outfile, "th", "cur"); output_line(outfile, "th", "percent"); output_line(outfile, "th", "touch"); output_line(outfile, "th", "t+c"); output_line(outfile, "th", "t+c perc"); if (config.backups_found == 1) { output_line(outfile, "th", "bu"); output_line(outfile, "th", "bu perc"); } end_tag(outfile, "tr"); end_tag(outfile, "thead"); } if (config.number_limit & S_BIT) { start_tag(outfile, "tbody"); for (i = 0; i < num_shared_networks; i++) { shared_p++; start_tag(outfile, "tr"); output_line(outfile, "td", shared_p->name); output_double(outfile, "td", shared_p->available); output_double(outfile, "td", shared_p->used); output_float(outfile, "td", shared_p->available == 0 ? NAN : (float)(100 * shared_p->used) / shared_p->available); output_double(outfile, "td", shared_p->touched); output_double(outfile, "td", shared_p->touched + shared_p->used); output_float(outfile, "td", shared_p->available == 0 ? NAN : (float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available); if (config.backups_found == 1) { output_double(outfile, "td", shared_p->backups); output_float(outfile, "td", shared_p->available == 0 ? NAN : (float)(100 * shared_p->backups) / shared_p->available); } end_tag(outfile, "tr"); } end_tag(outfile, "tbody"); } table_end(outfile); newsection(outfile, "Ranges"); table_start(outfile, "r", "ranges"); if (config.header_limit & R_BIT) { start_tag(outfile, "thead"); start_tag(outfile, "tr"); output_line(outfile, "th", "shared net name"); output_line(outfile, "th", "first ip"); output_line(outfile, "th", "last ip"); output_line(outfile, "th", "max"); output_line(outfile, "th", "cur"); output_line(outfile, "th", "percent"); output_line(outfile, "th", "touch"); output_line(outfile, "th", "t+c"); output_line(outfile, "th", "t+c perc"); if (config.backups_found == 1) { output_line(outfile, "th", "bu"); output_line(outfile, "th", "bu perc"); } end_tag(outfile, "tr"); end_tag(outfile, "thead"); } if (config.number_limit & R_BIT) { start_tag(outfile, "tbody"); for (i = 0; i < num_ranges; i++) { start_tag(outfile, "tr"); if (range_p->shared_net) { output_line(outfile, "td", range_p->shared_net->name); } else { output_line(outfile, "td", "not_defined"); } output_line(outfile, "td", ntop_ipaddr(&range_p->first_ip)); output_line(outfile, "td", ntop_ipaddr(&range_p->last_ip)); output_double(outfile, "td", range_size); output_double(outfile, "td", range_p->count); output_float(outfile, "td", (float)(100 * range_p->count) / range_size); output_double(outfile, "td", range_p->touched); output_double(outfile, "td", range_p->touched + range_p->count); output_float(outfile, "td", (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == 1) { output_double(outfile, "td", range_p->backups); output_float(outfile, "td", (float)(100 * range_p->backups) / range_size); } end_tag(outfile, "tr"); range_p++; range_size = get_range_size(range_p); } end_tag(outfile, "tbody"); } table_end(outfile); html_footer(outfile); if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_html: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_html: fclose"); } } return 0; } /*! \brief Output cvs format. */ int output_csv(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; FILE *outfile; int ret; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_csv: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.header_limit & R_BIT) { fprintf(outfile, "\"Ranges:\"\n"); fprintf (outfile, "\"shared net name\",\"first ip\",\"last ip\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == 1) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.number_limit & R_BIT) { for (i = 0; i < num_ranges; i++) { if (range_p->shared_net) { fprintf(outfile, "\"%s\",", range_p->shared_net->name); } else { fprintf(outfile, "\"not_defined\","); } fprintf(outfile, "\"%s\",", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", ntop_ipaddr(&range_p->last_ip), range_size, range_p->count, (float)(100 * range_p->count) / range_size, range_p->touched, range_p->touched + range_p->count, (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == 1) { fprintf(outfile, ",\"%g\",\"%.3f\"", range_p->backups, (float)(100 * range_p->backups) / range_size); } fprintf(outfile, "\n"); range_p++; range_size = get_range_size(range_p); } fprintf(outfile, "\n"); } if (config.header_limit & S_BIT) { fprintf(outfile, "\"Shared networks:\"\n"); fprintf(outfile, "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == 1) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.number_limit & S_BIT) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", shared_p->name, shared_p->available, shared_p->used, shared_p->available == 0 ? NAN : (float)(100 * shared_p->used) / shared_p->available, shared_p->touched, shared_p->touched + shared_p->used, shared_p->available == 0 ? NAN : (float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available); if (config.backups_found == 1) { fprintf(outfile, ",\"%g\",\"%.3f\"", shared_p->backups, shared_p->available == 0 ? NAN : (float)(100 * shared_p->backups) / shared_p->available); } fprintf(outfile, "\n"); } fprintf(outfile, "\n"); } if (config.header_limit & A_BIT) { fprintf(outfile, "\"Sum of all ranges:\"\n"); fprintf(outfile, "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == 1) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.number_limit & A_BIT) { fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", shared_networks->name, shared_networks->available, shared_networks->used, shared_networks->available == 0 ? NAN : (float)(100 * shared_networks->used) / shared_networks->available, shared_networks->touched, shared_networks->touched + shared_networks->used, shared_networks->available == 0 ? NAN : (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == 1) { fprintf(outfile, "%7g %8.3f", shared_networks->backups, shared_networks->available == 0 ? NAN : (float)(100 * shared_networks->backups) / shared_networks->available); } fprintf(outfile, "\n"); } if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_cvs: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_cvs: fclose"); } } return 0; } /*! \brief Output alarm text, and return program exit value. */ int output_alarming(void) { FILE *outfile; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; unsigned int i; float perc; int rw = 0, rc = 0, ro = 0, ri = 0, sw = 0, sc = 0, so = 0, si = 0; int ret_val, ret; range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { error(EXIT_FAILURE, errno, "output_alarming: %s", config.output_file); } } else { outfile = stdout; } if (config.number_limit & R_BIT) { for (i = 0; i < num_ranges; i++) { if (config.snet_alarms && range_p->shared_net != shared_networks) { continue; } if (config.minsize < range_size) { perc = (float)(100 * range_p->count) / range_size; if (config.critical < perc && (range_size - range_p->count) < config.crit_count) rc++; else if (config.warning < perc && (range_size - range_p->count) < config.warn_count) rw++; else ro++; } else { ri++; } range_p++; range_size = get_range_size(range_p); } } if (config.number_limit & S_BIT) { for (i = 0; i < num_shared_networks; i++) { shared_p++; if (config.minsize < shared_p->available) { perc = shared_p->available == 0 ? 100 : (float)(100 * shared_p->used) / shared_p->available; if (config.critical < perc && shared_p->used < config.crit_count) sc++; else if (config.warning < perc && shared_p->used < config.warn_count) sw++; else so++; } else { si++; } } } if (sc || rc) ret_val = STATE_CRITICAL; else if (sw || rw) ret_val = STATE_WARNING; else ret_val = STATE_OK; if ((0 < rc && config.number_limit & R_BIT) || (0 < sc && config.number_limit & S_BIT)) { fprintf(outfile, "CRITICAL: %s:", program_name); } else if ((0 < rw && config.number_limit & R_BIT) || (0 < sw && config.number_limit & S_BIT)) { fprintf(outfile, "WARNING: %s:", program_name); } else { if (config.number_limit & A_BIT) fprintf(outfile, "OK:"); else { if (close_stream(outfile)) { error(EXIT_FAILURE, errno, "output_alarming: fclose"); } return ret_val; } } if (config.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, "; | range_crit=%d range_warn=%d range_ok=%d", rc, rw, ro); if (ri != 0) { fprintf(outfile, " range_ignored=%d", ri); } if (config.perfdata == 1 && config.number_limit & R_BIT) { for (i = 0; i < num_ranges; i++) { range_p--; range_size = get_range_size(range_p); if (config.minsize < range_size) { fprintf(outfile, " %s_r=", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, "%g;%g;%g;0;%g", range_p->count, (range_size * config.warning / 100), (range_size * config.critical / 100), range_size); fprintf(outfile, " %s_rt=%g", ntop_ipaddr(&range_p->first_ip), range_p->touched); if (config.backups_found == 1) { fprintf(outfile, " %s_rbu=%g", ntop_ipaddr(&range_p->first_ip), range_p->backups); } } } } fprintf(outfile, "\n"); } else { fprintf(outfile, " "); } if (config.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, "; | snet_crit=%d snet_warn=%d snet_ok=%d", sc, sw, so); if (si != 0) { fprintf(outfile, " snet_ignored=%d", si); } if (config.perfdata == 1 && config.header_limit & R_BIT) { for (i = 0; i < num_shared_networks; i++) { if (config.minsize < shared_p->available) { fprintf(outfile, " '%s_s'=%g;%g;%g;0;%g", shared_p->name, shared_p->used, (shared_p->available * config.warning / 100), (shared_p->available * config.critical / 100), shared_p->available); fprintf(outfile, " '%s_st'=%g", shared_p->name, shared_p->touched); if (config.backups_found == 1) { fprintf(outfile, " '%s_sbu'=%g", shared_p->name, shared_p->backups); } } shared_p--; } fprintf(outfile, "\n"); } } fprintf(outfile, "\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { error(EXIT_FAILURE, errno, "output_alarming: fflush"); } } else { ret = close_stream(outfile); if (ret) { error(EXIT_FAILURE, errno, "output_alarming: fclose"); } } return ret_val; }