2 * The dhcpd-pools has BSD 2-clause license which also known as "Simplified
3 * BSD License" or "FreeBSD License".
5 * Copyright 2006- Sami Kerola. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
19 * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 * THE POSSIBILITY OF SUCH DAMAGE.
31 * The views and conclusions contained in the software and documentation are
32 * those of the authors and should not be interpreted as representing
33 * official policies, either expressed or implied, of Sami Kerola.
40 #include <arpa/inet.h>
42 #include <netinet/in.h>
46 #include "dhcpd-pools.h"
51 struct in_addr first, last;
52 struct range_t *range_p;
53 struct shared_network_t *shared_p;
57 if (config.output_file[0]) {
58 outfile = fopen(config.output_file, "w+");
59 if (outfile == NULL) {
60 err(EXIT_FAILURE, "output_txt: %s",
68 shared_p = shared_networks;
70 if (config.output_limit[0] & output_limit_bit_1) {
71 fprintf(outfile, "Ranges:\n");
74 "shared net name first ip last ip max cur percent touch t+c t+c perc");
75 if (0 < num_backups) {
76 fprintf(outfile, " bu bu perc");
78 fprintf(outfile, "\n");
80 if (config.output_limit[1] & output_limit_bit_1) {
81 for (i = 0; i < num_ranges; i++) {
82 first.s_addr = ntohl(range_p->first_ip + 1);
83 last.s_addr = ntohl(range_p->last_ip - 1);
85 if (range_p->shared_net) {
86 fprintf(outfile, "%-20s",
87 range_p->shared_net->name);
89 fprintf(outfile, "not_defined ");
91 fprintf(outfile, "%-16s", inet_ntoa(first));
93 " - %-16s %5lu %5lu %10.3f %5lu %5lu %9.3f",
95 range_p->last_ip - range_p->first_ip - 1,
97 (float) (100 * range_p->count) /
98 (range_p->last_ip - range_p->first_ip - 1),
100 range_p->touched + range_p->count,
104 (range_p->last_ip - range_p->first_ip -
106 if (0 < num_backups) {
107 fprintf(outfile, "%7lu %8.3f",
109 (float) (100 * range_p->backups) /
111 range_p->first_ip - 1));
113 fprintf(outfile, "\n");
117 if (config.output_limit[1] & output_limit_bit_1
118 && config.output_limit[0] & output_limit_bit_2) {
119 fprintf(outfile, "\n");
121 if (config.output_limit[0] & output_limit_bit_2) {
122 fprintf(outfile, "Shared networks:\n");
124 "name max cur percent touch t+c t+c perc");
125 if (0 < num_backups) {
126 fprintf(outfile, " bu bu perc");
128 fprintf(outfile, "\n");
130 if (config.output_limit[1] & output_limit_bit_2) {
131 for (i = 0; i < num_shared_networks; i++) {
134 "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
135 shared_p->name, shared_p->available,
137 (float) (100 * shared_p->used) /
138 shared_p->available, shared_p->touched,
139 shared_p->touched + shared_p->used,
143 shared_p->available);
144 if (0 < num_backups) {
145 fprintf(outfile, "%7lu %8.3f",
147 (float) (100 * shared_p->backups) /
148 shared_p->available);
151 fprintf(outfile, "\n");
154 if (config.output_limit[1] & output_limit_bit_2
155 && config.output_limit[0] & output_limit_bit_3) {
156 fprintf(outfile, "\n");
158 if (config.output_limit[0] & output_limit_bit_3) {
159 fprintf(outfile, "Sum of all ranges:\n");
161 "name max cur percent touch t+c t+c perc");
163 if (0 < num_backups) {
164 fprintf(outfile, " bu bu perc");
166 fprintf(outfile, "\n");
168 if (config.output_limit[1] & output_limit_bit_3) {
169 fprintf(outfile, "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
170 shared_networks->name,
171 shared_networks->available,
172 shared_networks->used,
173 (float) (100 * shared_networks->used) /
174 shared_networks->available,
175 shared_networks->touched,
176 shared_networks->touched + shared_networks->used,
178 (shared_networks->touched +
179 shared_networks->used)) /
180 shared_networks->available);
182 if (0 < num_backups) {
183 fprintf(outfile, "%7lu %8.3f",
184 shared_networks->backups,
185 (float) (100 * shared_networks->backups) /
186 shared_networks->available);
188 fprintf(outfile, "\n");
190 if (outfile == stdout) {
191 ret = fflush(stdout);
193 warn("output_txt: fflush");
196 ret = fclose(outfile);
198 warn("output_txt: fclose");
208 struct in_addr first, last;
209 struct range_t *range_p;
210 struct shared_network_t *shared_p;
211 struct macaddr_t *macaddr_p;
215 if (config.output_file[0]) {
216 outfile = fopen(config.output_file, "w+");
217 if (outfile == NULL) {
218 err(EXIT_FAILURE, "output_xml: %s",
226 shared_p = shared_networks;
228 fprintf(outfile, "<dhcpstatus>\n");
230 if (macaddr != NULL) {
231 for (macaddr_p = macaddr; macaddr_p->next != NULL;
232 macaddr_p = macaddr_p->next) {
234 "<active_lease>\n\t<ip>%s</ip>\n\t<macaddress>%s</macaddress>\n</active_lease>\n",
235 macaddr_p->ip, macaddr_p->ethernet);
239 if (config.output_limit[1] & output_limit_bit_1) {
240 for (i = 0; i < num_ranges; i++) {
241 first.s_addr = ntohl(range_p->first_ip + 1);
242 last.s_addr = ntohl(range_p->last_ip - 1);
243 fprintf(outfile, "<subnet>\n");
244 if (range_p->shared_net) {
246 "\t<location>%s</location>\n",
247 range_p->shared_net->name);
250 "\t<location></location>\n");
253 fprintf(outfile, "\t<network></network>\n");
254 fprintf(outfile, "\t<netmask></netmask>\n");
255 fprintf(outfile, "\t<range>%s ", inet_ntoa(first));
256 fprintf(outfile, "- %s</range>\n",
258 fprintf(outfile, "\t<gateway></gateway>\n");
259 fprintf(outfile, "\t<defined>%lu</defined>\n",
260 range_p->last_ip - range_p->first_ip - 1);
261 fprintf(outfile, "\t<used>%lu</used>\n",
263 fprintf(outfile, "\t<free>%lu</free>\n",
264 range_p->last_ip - range_p->first_ip - 1 -
267 fprintf(outfile, "</subnet>\n");
271 if (config.output_limit[1] & output_limit_bit_2) {
272 for (i = 0; i < num_shared_networks; i++) {
274 fprintf(outfile, "<shared-network>\n");
275 fprintf(outfile, "\t<location>%s</location>\n",
277 fprintf(outfile, "\t<defined>%lu</defined>\n",
278 shared_p->available);
279 fprintf(outfile, "\t<used>%lu</used>\n",
281 fprintf(outfile, "\t<free>%lu</free>\n",
282 shared_p->available - shared_p->used);
283 fprintf(outfile, "</shared-network>\n");
287 if (config.output_limit[0] & output_limit_bit_3) {
288 fprintf(outfile, "<summary>\n");
289 fprintf(outfile, "\t<location>%s</location>\n",
290 shared_networks->name);
291 fprintf(outfile, "\t<defined>%lu</defined>\n",
292 shared_networks->available);
293 fprintf(outfile, "\t<used>%lu</used>\n",
294 shared_networks->used);
295 fprintf(outfile, "\t<free>%lu</free>\n",
296 shared_networks->available -
297 shared_networks->used);
298 fprintf(outfile, "</summary>\n");
301 fprintf(outfile, "</dhcpstatus>\n");
302 if (outfile == stdout) {
303 ret = fflush(stdout);
305 warn("output_xml: fflush");
308 ret = fclose(outfile);
310 warn("output_xml: fclose");
317 void html_header(FILE * f)
320 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \n");
321 fprintf(f, " \"http://www.w3.org/TR/html4/strict.dtd\">\n");
322 fprintf(f, "<html>\n");
323 fprintf(f, "<head>\n");
324 fprintf(f, "<meta http-equiv=\"Content-Type\" ");
325 fprintf(f, "content=\"text/html; charset=iso-8859-1\">\n");
326 fprintf(f, " <title>ISC dhcpd stats</title>\n");
327 fprintf(f, " <style TYPE=\"text/css\">\n");
328 fprintf(f, " <!--\n");
329 fprintf(f, " table.dhcpd-pools {\n");
330 fprintf(f, " color: black;\n");
331 fprintf(f, " vertical-align: middle;\n");
332 fprintf(f, " text-align: center;\n");
334 fprintf(f, " table.dhcpd-pools th.section {\n");
335 fprintf(f, " color: black;\n");
336 fprintf(f, " font-size: large;\n");
337 fprintf(f, " vertical-align: middle;\n");
338 fprintf(f, " text-align: left;\n");
340 fprintf(f, " table.dhcpd-pools th.calign {\n");
341 fprintf(f, " color: black;\n");
342 fprintf(f, " vertical-align: middle;\n");
343 fprintf(f, " text-align: center;\n");
344 fprintf(f, " text-decoration: underline;\n");
346 fprintf(f, " table.dhcpd-pools th.ralign {\n");
347 fprintf(f, " color: black;\n");
348 fprintf(f, " vertical-align: middle;\n");
349 fprintf(f, " text-align: right;\n");
350 fprintf(f, " text-decoration: underline;\n");
352 fprintf(f, " table.dhcpd-pools td.calign {\n");
353 fprintf(f, " color: black;\n");
354 fprintf(f, " vertical-align: middle;\n");
355 fprintf(f, " text-align: center;\n");
357 fprintf(f, " table.dhcpd-pools td.ralign {\n");
358 fprintf(f, " color: black;\n");
359 fprintf(f, " vertical-align: middle;\n");
360 fprintf(f, " text-align: right;\n");
362 fprintf(f, " p.created {\n");
363 fprintf(f, " font-size: small;\n");
364 fprintf(f, " color: grey;\n");
366 fprintf(f, " p.updated {\n");
367 fprintf(f, " font-size: small;\n");
368 fprintf(f, " color: grey;\n");
369 fprintf(f, " font-style: italic;\n");
371 fprintf(f, " -->\n");
372 fprintf(f, " </style>\n");
373 fprintf(f, "</head>\n");
374 fprintf(f, "<body>\n");
377 void html_footer(FILE * f)
379 fprintf(f, "<p><br></p>\n");
380 fprintf(f, "<hr>\n");
381 fprintf(f, "<p class=created>\nData generated by ");
382 fprintf(f, "<a href=\"%s\">", PACKAGE_URL);
383 fprintf(f, "dhcpd-pools</a>.\n</p>\n");
384 fprintf(f, "<p class=updated>\n");
385 fprintf(f, "<script type=\"text/javascript\">\n");
386 fprintf(f, " document.write(\"Last Updated On \" + ");
387 fprintf(f, "document.lastModified + \".\")\n");
388 fprintf(f, "</script>\n<br>\n</p>\n");
389 fprintf(f, "</body>\n");
390 fprintf(f, "</html>\n");
393 void newrow(FILE * f)
395 fprintf(f, "<tr>\n");
398 void endrow(FILE * f)
400 fprintf(f, "</tr>\n\n");
403 void output_line(FILE * f, char *type, char *class, char *text)
405 fprintf(f, " <%s class=%s>%s</%s>\n", type, class, text, type);
408 void output_long(FILE * f, char *type, unsigned long unlong)
410 fprintf(f, " <%s class=ralign>%lu</%s>\n", type, unlong, type);
413 void output_float(FILE * f, char *type, float fl)
415 fprintf(f, " <%s class=ralign>%.3f</%s>\n", type, fl, type);
418 void table_start(FILE * f)
420 fprintf(f, "<table width=\"75%%\" ");
421 fprintf(f, "class=\"dhcpd-pools\" ");
422 fprintf(f, "summary=\"ISC dhcpd pool usage report\">\n");
425 void table_end(FILE * f)
427 fprintf(f, "</table>\n");
430 void newsection(FILE * f, char *title)
433 output_line(f, "td", "calign", " ");
436 output_line(f, "th", "section", title);
440 int output_html(void)
443 struct in_addr first, last;
444 struct range_t *range_p;
445 struct shared_network_t *shared_p;
448 if (config.output_file[0]) {
449 outfile = fopen(config.output_file, "w+");
450 if (outfile == NULL) {
451 err(EXIT_FAILURE, "output_html: %s",
459 shared_p = shared_networks;
461 html_header(outfile);
463 table_start(outfile);
464 if (config.output_limit[0] & output_limit_bit_1) {
465 newsection(outfile, "Ranges:");
467 output_line(outfile, "th", "calign", "shared net name");
468 output_line(outfile, "th", "calign", "first ip");
469 output_line(outfile, "th", "calign", "last ip");
470 output_line(outfile, "th", "ralign", "max");
471 output_line(outfile, "th", "ralign", "cur");
472 output_line(outfile, "th", "ralign", "percent");
473 output_line(outfile, "th", "ralign", "touch");
474 output_line(outfile, "th", "ralign", "t+c");
475 output_line(outfile, "th", "ralign", "t+c perc");
476 if (0 < num_backups) {
477 output_line(outfile, "th", "ralign", "bu");
478 output_line(outfile, "th", "ralign", "bu perc");
482 if (config.output_limit[1] & output_limit_bit_1) {
483 for (i = 0; i < num_ranges; i++) {
484 first.s_addr = ntohl(range_p->first_ip + 1);
485 last.s_addr = ntohl(range_p->last_ip - 1);
487 if (range_p->shared_net) {
488 output_line(outfile, "td", "calign",
489 range_p->shared_net->name);
491 output_line(outfile, "td", "calign",
494 output_line(outfile, "td", "calign",
496 output_line(outfile, "td", "calign",
498 output_long(outfile, "td",
499 range_p->last_ip - range_p->first_ip -
501 output_long(outfile, "td", range_p->count);
502 output_float(outfile, "td",
503 (float) (100 * range_p->count) /
505 range_p->first_ip - 1));
506 output_long(outfile, "td", range_p->touched);
507 output_long(outfile, "td",
508 range_p->touched + range_p->count);
509 output_float(outfile, "td",
514 range_p->first_ip - 1));
515 if (0 < num_backups) {
516 output_long(outfile, "td",
518 output_float(outfile, "td",
522 range_p->first_ip - 1));
529 table_start(outfile);
530 if (config.output_limit[0] & output_limit_bit_2) {
531 newsection(outfile, "Shared networks:");
533 output_line(outfile, "th", "calign", "name");
534 output_line(outfile, "th", "ralign", "max");
535 output_line(outfile, "th", "ralign", "cur");
536 output_line(outfile, "th", "ralign", "percent");
537 output_line(outfile, "th", "ralign", "touch");
538 output_line(outfile, "th", "ralign", "t+c");
539 output_line(outfile, "th", "ralign", "t+c perc");
540 if (0 < num_backups) {
541 output_line(outfile, "th", "ralign", "bu");
542 output_line(outfile, "th", "ralign", "bu perc");
546 if (config.output_limit[1] & output_limit_bit_2) {
547 for (i = 0; i < num_shared_networks; i++) {
550 output_line(outfile, "td", "calign",
552 output_long(outfile, "td", shared_p->available);
553 output_long(outfile, "td", shared_p->used);
554 output_float(outfile, "td",
555 (float) (100 * shared_p->used) /
556 shared_p->available);
557 output_long(outfile, "td", shared_p->touched);
558 output_long(outfile, "td",
559 shared_p->touched + shared_p->used);
560 output_float(outfile, "td",
564 shared_p->available);
565 if (0 < num_backups) {
566 output_long(outfile, "td",
568 output_float(outfile, "td",
571 shared_p->available);
577 if (config.output_limit[0] & output_limit_bit_3) {
578 newsection(outfile, "Sum of all ranges:");
580 output_line(outfile, "th", "calign", "name");
581 output_line(outfile, "th", "ralign", "max");
582 output_line(outfile, "th", "ralign", "cur");
583 output_line(outfile, "th", "ralign", "percent");
584 output_line(outfile, "th", "ralign", "touch");
585 output_line(outfile, "th", "ralign", "t+c");
586 output_line(outfile, "th", "ralign", "t+c perc");
587 if (0 < num_backups) {
588 output_line(outfile, "th", "ralign", "bu");
589 output_line(outfile, "th", "ralign", "bu perc");
594 if (config.output_limit[1] & output_limit_bit_3) {
596 output_line(outfile, "td", "calign",
597 shared_networks->name);
598 output_long(outfile, "td", shared_networks->available);
599 output_long(outfile, "td", shared_networks->used);
600 output_float(outfile, "td",
601 (float) (100 * shared_networks->used) /
602 shared_networks->available);
603 output_long(outfile, "td", shared_networks->touched);
604 output_long(outfile, "td",
605 shared_networks->touched +
606 shared_networks->used);
607 output_float(outfile, "td",
609 (shared_networks->touched +
610 shared_networks->used)) /
611 shared_networks->available);
612 if (0 < num_backups) {
613 output_long(outfile, "td",
614 shared_networks->backups);
615 output_float(outfile, "td",
617 shared_networks->backups) /
618 shared_networks->available);
624 html_footer(outfile);
626 if (outfile == stdout) {
627 ret = fflush(stdout);
629 warn("output_html: fflush");
632 ret = fclose(outfile);
634 warn("output_html: fclose");
643 struct in_addr first, last;
644 struct range_t *range_p;
645 struct shared_network_t *shared_p;
648 if (config.output_file[0]) {
649 outfile = fopen(config.output_file, "w+");
650 if (outfile == NULL) {
651 err(EXIT_FAILURE, "output_csv: %s",
659 shared_p = shared_networks;
660 if (config.output_limit[0] & output_limit_bit_1) {
661 fprintf(outfile, "\"Ranges:\"\n");
664 "\"shared net name\",\"first ip\",\"last ip\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
665 if (0 < num_backups) {
666 fprintf(outfile, ",\"bu\",\"bu perc\"");
668 fprintf(outfile, "\n");
670 if (config.output_limit[1] & output_limit_bit_1) {
671 for (i = 0; i < num_ranges; i++) {
672 first.s_addr = ntohl(range_p->first_ip + 1);
673 last.s_addr = ntohl(range_p->last_ip - 1);
674 if (range_p->shared_net) {
675 fprintf(outfile, "\"%s\",",
676 range_p->shared_net->name);
678 fprintf(outfile, "\"not_defined\",");
680 fprintf(outfile, "\"%s\",", inet_ntoa(first));
682 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
684 range_p->last_ip - range_p->first_ip - 1,
686 (float) (100 * range_p->count) /
687 (range_p->last_ip - range_p->first_ip - 1),
689 range_p->touched + range_p->count,
693 (range_p->last_ip - range_p->first_ip -
695 if (0 < num_backups) {
696 fprintf(outfile, ",\"%lu\",\"%.3f\"",
698 (float) (100 * range_p->backups) /
700 range_p->first_ip - 1));
703 fprintf(outfile, "\n");
706 fprintf(outfile, "\n");
708 if (config.output_limit[0] & output_limit_bit_2) {
709 fprintf(outfile, "\"Shared networks:\"\n");
711 "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
712 if (0 < num_backups) {
713 fprintf(outfile, ",\"bu\",\"bu perc\"");
715 fprintf(outfile, "\n");
717 if (config.output_limit[1] & output_limit_bit_2) {
719 for (i = 0; i < num_shared_networks; i++) {
722 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
723 shared_p->name, shared_p->available,
725 (float) (100 * shared_p->used) /
726 shared_p->available, shared_p->touched,
727 shared_p->touched + shared_p->used,
731 shared_p->available);
732 if (0 < num_backups) {
733 fprintf(outfile, ",\"%lu\",\"%.3f\"",
735 (float) (100 * shared_p->backups) /
736 shared_p->available);
739 fprintf(outfile, "\n");
741 fprintf(outfile, "\n");
743 if (config.output_limit[0] & output_limit_bit_3) {
744 fprintf(outfile, "\"Sum of all ranges:\"\n");
746 "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
747 if (0 < num_backups) {
748 fprintf(outfile, ",\"bu\",\"bu perc\"");
750 fprintf(outfile, "\n");
752 if (config.output_limit[1] & output_limit_bit_3) {
755 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
756 shared_networks->name, shared_networks->available,
757 shared_networks->used,
758 (float) (100 * shared_networks->used) /
759 shared_networks->available,
760 shared_networks->touched,
761 shared_networks->touched + shared_networks->used,
763 (shared_networks->touched +
764 shared_networks->used)) /
765 shared_networks->available);
766 if (0 < num_backups) {
767 fprintf(outfile, "%7lu %8.3f",
768 shared_networks->backups,
769 (float) (100 * shared_networks->backups) /
770 shared_networks->available);
772 fprintf(outfile, "\n");
774 if (outfile == stdout) {
775 ret = fflush(stdout);
777 warn("output_cvs: fflush");
781 ret = fclose(outfile);
783 warn("output_cvs: fclose");