1 /* http://dhcpd-pools.sourceforge.net/
2 ** Copyright 2006- Sami Kerola <kerolasa@iki.fi>
4 ** This program is free software: you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation, either version 3 of the License, or
7 ** (at your option) any later version.
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU General Public License for more details.
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
28 #include "dhcpd-pools.h"
33 struct in_addr first, last;
34 struct range_t *range_p;
35 struct shared_network_t *shared_p;
39 if (config.output_file[0]) {
40 outfile = fopen(config.output_file, "w+");
41 if (outfile == NULL) {
42 err(EXIT_FAILURE, "output_txt: %s",
50 shared_p = shared_networks;
52 if (config.output_limit[0] & output_limit_bit_1) {
53 fprintf(outfile, "Ranges:\n");
56 "shared net name first ip last ip max cur percent touch t+c t+c perc");
57 if (0 < num_backups) {
58 fprintf(outfile, " bu bu perc");
60 fprintf(outfile, "\n");
62 if (config.output_limit[1] & output_limit_bit_1) {
63 for (i = 0; i < num_ranges; i++) {
64 first.s_addr = ntohl(range_p->first_ip + 1);
65 last.s_addr = ntohl(range_p->last_ip - 1);
67 if (range_p->shared_net) {
68 fprintf(outfile, "%-20s",
69 range_p->shared_net->name);
71 fprintf(outfile, "not_defined ");
73 fprintf(outfile, "%-16s", inet_ntoa(first));
75 " - %-16s %5lu %5lu %10.3f %5lu %5lu %9.3f",
77 range_p->last_ip - range_p->first_ip - 1,
79 (float) (100 * range_p->count) /
80 (range_p->last_ip - range_p->first_ip - 1),
82 range_p->touched + range_p->count,
86 (range_p->last_ip - range_p->first_ip -
88 if (0 < num_backups) {
89 fprintf(outfile, "%7lu %8.3f",
91 (float) (100 * range_p->backups) /
93 range_p->first_ip - 1));
95 fprintf(outfile, "\n");
99 if (config.output_limit[1] & output_limit_bit_1
100 && config.output_limit[0] & output_limit_bit_2) {
101 fprintf(outfile, "\n");
103 if (config.output_limit[0] & output_limit_bit_2) {
104 fprintf(outfile, "Shared networks:\n");
106 "name max cur percent touch t+c t+c perc");
107 if (0 < num_backups) {
108 fprintf(outfile, " bu bu perc");
110 fprintf(outfile, "\n");
112 if (config.output_limit[1] & output_limit_bit_2) {
113 for (i = 0; i < num_shared_networks; i++) {
116 "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
117 shared_p->name, shared_p->available,
119 (float) (100 * shared_p->used) /
120 shared_p->available, shared_p->touched,
121 shared_p->touched + shared_p->used,
125 shared_p->available);
126 if (0 < num_backups) {
127 fprintf(outfile, "%7lu %8.3f",
129 (float) (100 * shared_p->backups) /
130 shared_p->available);
133 fprintf(outfile, "\n");
136 if (config.output_limit[1] & output_limit_bit_2
137 && config.output_limit[0] & output_limit_bit_3) {
138 fprintf(outfile, "\n");
140 if (config.output_limit[0] & output_limit_bit_3) {
141 fprintf(outfile, "Sum of all ranges:\n");
143 "name max cur percent touch t+c t+c perc");
145 if (0 < num_backups) {
146 fprintf(outfile, " bu bu perc");
148 fprintf(outfile, "\n");
150 if (config.output_limit[1] & output_limit_bit_3) {
151 fprintf(outfile, "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
152 shared_networks->name,
153 shared_networks->available,
154 shared_networks->used,
155 (float) (100 * shared_networks->used) /
156 shared_networks->available,
157 shared_networks->touched,
158 shared_networks->touched + shared_networks->used,
160 (shared_networks->touched +
161 shared_networks->used)) /
162 shared_networks->available);
164 if (0 < num_backups) {
165 fprintf(outfile, "%7lu %8.3f",
166 shared_networks->backups,
167 (float) (100 * shared_networks->backups) /
168 shared_networks->available);
170 fprintf(outfile, "\n");
172 if (outfile == stdout) {
173 ret = fflush(stdout);
175 warn("output_txt: fflush");
178 ret = fclose(outfile);
180 warn("output_txt: fclose");
190 struct in_addr first, last;
191 struct range_t *range_p;
192 struct shared_network_t *shared_p;
193 struct macaddr_t *macaddr_p;
197 if (config.output_file[0]) {
198 outfile = fopen(config.output_file, "w+");
199 if (outfile == NULL) {
200 err(EXIT_FAILURE, "output_xml: %s",
208 shared_p = shared_networks;
210 fprintf(outfile, "<dhcpstatus>\n");
212 if (macaddr != NULL) {
213 for (macaddr_p = macaddr; macaddr_p->next != NULL;
214 macaddr_p = macaddr_p->next) {
216 "<active_lease>\n\t<ip>%s</ip>\n\t<macaddress>%s</macaddress>\n</active_lease>\n",
217 macaddr_p->ip, macaddr_p->ethernet);
221 if (config.output_limit[1] & output_limit_bit_1) {
222 for (i = 0; i < num_ranges; i++) {
223 first.s_addr = ntohl(range_p->first_ip + 1);
224 last.s_addr = ntohl(range_p->last_ip - 1);
225 fprintf(outfile, "<subnet>\n");
226 if (range_p->shared_net) {
228 "\t<location>%s</location>\n",
229 range_p->shared_net->name);
232 "\t<location></location>\n");
235 fprintf(outfile, "\t<network></network>\n");
236 fprintf(outfile, "\t<netmask></netmask>\n");
237 fprintf(outfile, "\t<range>%s ", inet_ntoa(first));
238 fprintf(outfile, "- %s</range>\n",
240 fprintf(outfile, "\t<gateway></gateway>\n");
241 fprintf(outfile, "\t<defined>%lu</defined>\n",
242 range_p->last_ip - range_p->first_ip - 1);
243 fprintf(outfile, "\t<used>%lu</used>\n",
245 fprintf(outfile, "\t<free>%lu</free>\n",
246 range_p->last_ip - range_p->first_ip - 1 -
249 fprintf(outfile, "</subnet>\n");
253 if (config.output_limit[1] & output_limit_bit_2) {
254 for (i = 0; i < num_shared_networks; i++) {
256 fprintf(outfile, "<shared-network>\n");
257 fprintf(outfile, "\t<location>%s</location>\n",
259 fprintf(outfile, "\t<defined>%lu</defined>\n",
260 shared_p->available);
261 fprintf(outfile, "\t<used>%lu</used>\n",
263 fprintf(outfile, "\t<free>%lu</free>\n",
264 shared_p->available - shared_p->used);
265 fprintf(outfile, "</shared-network>\n");
269 if (config.output_limit[0] & output_limit_bit_3) {
270 fprintf(outfile, "<summary>\n");
271 fprintf(outfile, "\t<location>%s</location>\n",
272 shared_networks->name);
273 fprintf(outfile, "\t<defined>%lu</defined>\n",
274 shared_networks->available);
275 fprintf(outfile, "\t<used>%lu</used>\n",
276 shared_networks->used);
277 fprintf(outfile, "\t<free>%lu</free>\n",
278 shared_networks->available -
279 shared_networks->used);
280 fprintf(outfile, "</summary>\n");
283 fprintf(outfile, "</dhcpstatus>\n");
284 if (outfile == stdout) {
285 ret = fflush(stdout);
287 warn("output_xml: fflush");
290 ret = fclose(outfile);
292 warn("output_xml: fclose");
299 void html_header(FILE * f)
302 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \n");
303 fprintf(f, " \"http://www.w3.org/TR/html4/strict.dtd\">\n");
304 fprintf(f, "<html>\n");
305 fprintf(f, "<head>\n");
306 fprintf(f, "<meta http-equiv=\"Content-Type\" ");
307 fprintf(f, "content=\"text/html; charset=iso-8859-1\">\n");
308 fprintf(f, " <title>ISC dhcpd stats</title>\n");
309 fprintf(f, " <style TYPE=\"text/css\">\n");
310 fprintf(f, " <!--\n");
311 fprintf(f, " table.dhcpd-pools {\n");
312 fprintf(f, " color: black;\n");
313 fprintf(f, " vertical-align: middle;\n");
314 fprintf(f, " text-align: center;\n");
316 fprintf(f, " table.dhcpd-pools th.section {\n");
317 fprintf(f, " color: black;\n");
318 fprintf(f, " font-size: large;\n");
319 fprintf(f, " vertical-align: middle;\n");
320 fprintf(f, " text-align: left;\n");
322 fprintf(f, " table.dhcpd-pools th.calign {\n");
323 fprintf(f, " color: black;\n");
324 fprintf(f, " vertical-align: middle;\n");
325 fprintf(f, " text-align: center;\n");
326 fprintf(f, " text-decoration: underline;\n");
328 fprintf(f, " table.dhcpd-pools th.ralign {\n");
329 fprintf(f, " color: black;\n");
330 fprintf(f, " vertical-align: middle;\n");
331 fprintf(f, " text-align: right;\n");
332 fprintf(f, " text-decoration: underline;\n");
334 fprintf(f, " table.dhcpd-pools td.calign {\n");
335 fprintf(f, " color: black;\n");
336 fprintf(f, " vertical-align: middle;\n");
337 fprintf(f, " text-align: center;\n");
339 fprintf(f, " table.dhcpd-pools td.ralign {\n");
340 fprintf(f, " color: black;\n");
341 fprintf(f, " vertical-align: middle;\n");
342 fprintf(f, " text-align: right;\n");
344 fprintf(f, " p.created {\n");
345 fprintf(f, " font-size: small;\n");
346 fprintf(f, " color: grey;\n");
348 fprintf(f, " p.updated {\n");
349 fprintf(f, " font-size: small;\n");
350 fprintf(f, " color: grey;\n");
351 fprintf(f, " font-style: italic;\n");
353 fprintf(f, " -->\n");
354 fprintf(f, " </style>\n");
355 fprintf(f, "</head>\n");
356 fprintf(f, "<body>\n");
359 void html_footer(FILE * f)
361 fprintf(f, "<p><br></p>\n");
362 fprintf(f, "<hr>\n");
363 fprintf(f, "<p class=created>\nData generated by ");
364 fprintf(f, "<a href=\"%s\">", PACKAGE_URL);
365 fprintf(f, "dhcpd-pools</a>.\n</p>\n");
366 fprintf(f, "<p class=updated>\n");
367 fprintf(f, "<script type=\"text/javascript\">\n");
368 fprintf(f, " document.write(\"Last Updated On \" + ");
369 fprintf(f, "document.lastModified + \".\")\n");
370 fprintf(f, "</script>\n<br>\n</p>\n");
371 fprintf(f, "</body>\n");
372 fprintf(f, "</html>\n");
375 void newrow(FILE * f)
377 fprintf(f, "<tr>\n");
380 void endrow(FILE * f)
382 fprintf(f, "</tr>\n\n");
385 void output_line(FILE * f, char *type, char *class, char *text)
387 fprintf(f, " <%s class=%s>%s</%s>\n", type, class, text, type);
390 void output_long(FILE * f, char *type, unsigned long unlong)
392 fprintf(f, " <%s class=ralign>%lu</%s>\n", type, unlong, type);
395 void output_float(FILE * f, char *type, float fl)
397 fprintf(f, " <%s class=ralign>%.3f</%s>\n", type, fl, type);
400 void table_start(FILE * f)
402 fprintf(f, "<table width=\"75%%\" ");
403 fprintf(f, "class=\"dhcpd-pools\" ");
404 fprintf(f, "summary=\"ISC dhcpd pool usage report\">\n");
407 void table_end(FILE * f)
409 fprintf(f, "</table>\n");
412 void newsection(FILE * f, char *title)
415 output_line(f, "td", "calign", " ");
418 output_line(f, "th", "section", title);
422 int output_html(void)
425 struct in_addr first, last;
426 struct range_t *range_p;
427 struct shared_network_t *shared_p;
430 if (config.output_file[0]) {
431 outfile = fopen(config.output_file, "w+");
432 if (outfile == NULL) {
433 err(EXIT_FAILURE, "output_html: %s",
441 shared_p = shared_networks;
443 html_header(outfile);
445 table_start(outfile);
446 if (config.output_limit[0] & output_limit_bit_1) {
447 newsection(outfile, "Ranges:");
449 output_line(outfile, "th", "calign", "shared net name");
450 output_line(outfile, "th", "calign", "first ip");
451 output_line(outfile, "th", "calign", "last ip");
452 output_line(outfile, "th", "ralign", "max");
453 output_line(outfile, "th", "ralign", "cur");
454 output_line(outfile, "th", "ralign", "percent");
455 output_line(outfile, "th", "ralign", "touch");
456 output_line(outfile, "th", "ralign", "t+c");
457 output_line(outfile, "th", "ralign", "t+c perc");
458 if (0 < num_backups) {
459 output_line(outfile, "th", "ralign", "bu");
460 output_line(outfile, "th", "ralign", "bu perc");
464 if (config.output_limit[1] & output_limit_bit_1) {
465 for (i = 0; i < num_ranges; i++) {
466 first.s_addr = ntohl(range_p->first_ip + 1);
467 last.s_addr = ntohl(range_p->last_ip - 1);
469 if (range_p->shared_net) {
470 output_line(outfile, "td", "calign",
471 range_p->shared_net->name);
473 output_line(outfile, "td", "calign",
476 output_line(outfile, "td", "calign",
478 output_line(outfile, "td", "calign",
480 output_long(outfile, "td",
481 range_p->last_ip - range_p->first_ip -
483 output_long(outfile, "td", range_p->count);
484 output_float(outfile, "td",
485 (float) (100 * range_p->count) /
487 range_p->first_ip - 1));
488 output_long(outfile, "td", range_p->touched);
489 output_long(outfile, "td",
490 range_p->touched + range_p->count);
491 output_float(outfile, "td",
496 range_p->first_ip - 1));
497 if (0 < num_backups) {
498 output_long(outfile, "td",
500 output_float(outfile, "td",
504 range_p->first_ip - 1));
511 table_start(outfile);
512 if (config.output_limit[0] & output_limit_bit_2) {
513 newsection(outfile, "Shared networks:");
515 output_line(outfile, "th", "calign", "name");
516 output_line(outfile, "th", "ralign", "max");
517 output_line(outfile, "th", "ralign", "cur");
518 output_line(outfile, "th", "ralign", "percent");
519 output_line(outfile, "th", "ralign", "touch");
520 output_line(outfile, "th", "ralign", "t+c");
521 output_line(outfile, "th", "ralign", "t+c perc");
522 if (0 < num_backups) {
523 output_line(outfile, "th", "ralign", "bu");
524 output_line(outfile, "th", "ralign", "bu perc");
528 if (config.output_limit[1] & output_limit_bit_2) {
529 for (i = 0; i < num_shared_networks; i++) {
532 output_line(outfile, "td", "calign",
534 output_long(outfile, "td", shared_p->available);
535 output_long(outfile, "td", shared_p->used);
536 output_float(outfile, "td",
537 (float) (100 * shared_p->used) /
538 shared_p->available);
539 output_long(outfile, "td", shared_p->touched);
540 output_long(outfile, "td",
541 shared_p->touched + shared_p->used);
542 output_float(outfile, "td",
546 shared_p->available);
547 if (0 < num_backups) {
548 output_long(outfile, "td",
550 output_float(outfile, "td",
553 shared_p->available);
559 if (config.output_limit[0] & output_limit_bit_3) {
560 newsection(outfile, "Sum of all ranges:");
562 output_line(outfile, "th", "calign", "name");
563 output_line(outfile, "th", "ralign", "max");
564 output_line(outfile, "th", "ralign", "cur");
565 output_line(outfile, "th", "ralign", "percent");
566 output_line(outfile, "th", "ralign", "touch");
567 output_line(outfile, "th", "ralign", "t+c");
568 output_line(outfile, "th", "ralign", "t+c perc");
569 if (0 < num_backups) {
570 output_line(outfile, "th", "ralign", "bu");
571 output_line(outfile, "th", "ralign", "bu perc");
576 if (config.output_limit[1] & output_limit_bit_3) {
578 output_line(outfile, "td", "calign",
579 shared_networks->name);
580 output_long(outfile, "td", shared_networks->available);
581 output_long(outfile, "td", shared_networks->used);
582 output_float(outfile, "td",
583 (float) (100 * shared_networks->used) /
584 shared_networks->available);
585 output_long(outfile, "td", shared_networks->touched);
586 output_long(outfile, "td",
587 shared_networks->touched +
588 shared_networks->used);
589 output_float(outfile, "td",
591 (shared_networks->touched +
592 shared_networks->used)) /
593 shared_networks->available);
594 if (0 < num_backups) {
595 output_long(outfile, "td",
596 shared_networks->backups);
597 output_float(outfile, "td",
599 shared_networks->backups) /
600 shared_networks->available);
606 html_footer(outfile);
608 if (outfile == stdout) {
609 ret = fflush(stdout);
611 warn("output_html: fflush");
614 ret = fclose(outfile);
616 warn("output_html: fclose");
625 struct in_addr first, last;
626 struct range_t *range_p;
627 struct shared_network_t *shared_p;
630 if (config.output_file[0]) {
631 outfile = fopen(config.output_file, "w+");
632 if (outfile == NULL) {
633 err(EXIT_FAILURE, "output_csv: %s",
641 shared_p = shared_networks;
642 if (config.output_limit[0] & output_limit_bit_1) {
643 fprintf(outfile, "\"Ranges:\"\n");
646 "\"shared net name\",\"first ip\",\"last ip\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
647 if (0 < num_backups) {
648 fprintf(outfile, ",\"bu\",\"bu perc\"");
650 fprintf(outfile, "\n");
652 if (config.output_limit[1] & output_limit_bit_1) {
653 for (i = 0; i < num_ranges; i++) {
654 first.s_addr = ntohl(range_p->first_ip + 1);
655 last.s_addr = ntohl(range_p->last_ip - 1);
656 if (range_p->shared_net) {
657 fprintf(outfile, "\"%s\",",
658 range_p->shared_net->name);
660 fprintf(outfile, "\"not_defined\",");
662 fprintf(outfile, "\"%s\",", inet_ntoa(first));
664 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
666 range_p->last_ip - range_p->first_ip - 1,
668 (float) (100 * range_p->count) /
669 (range_p->last_ip - range_p->first_ip - 1),
671 range_p->touched + range_p->count,
675 (range_p->last_ip - range_p->first_ip -
677 if (0 < num_backups) {
678 fprintf(outfile, ",\"%lu\",\"%.3f\"",
680 (float) (100 * range_p->backups) /
682 range_p->first_ip - 1));
685 fprintf(outfile, "\n");
688 fprintf(outfile, "\n");
690 if (config.output_limit[0] & output_limit_bit_2) {
691 fprintf(outfile, "\"Shared networks:\"\n");
693 "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
694 if (0 < num_backups) {
695 fprintf(outfile, ",\"bu\",\"bu perc\"");
697 fprintf(outfile, "\n");
699 if (config.output_limit[1] & output_limit_bit_2) {
701 for (i = 0; i < num_shared_networks; i++) {
704 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
705 shared_p->name, shared_p->available,
707 (float) (100 * shared_p->used) /
708 shared_p->available, shared_p->touched,
709 shared_p->touched + shared_p->used,
713 shared_p->available);
714 if (0 < num_backups) {
715 fprintf(outfile, ",\"%lu\",\"%.3f\"",
717 (float) (100 * shared_p->backups) /
718 shared_p->available);
721 fprintf(outfile, "\n");
723 fprintf(outfile, "\n");
725 if (config.output_limit[0] & output_limit_bit_3) {
726 fprintf(outfile, "\"Sum of all ranges:\"\n");
728 "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
729 if (0 < num_backups) {
730 fprintf(outfile, ",\"bu\",\"bu perc\"");
732 fprintf(outfile, "\n");
734 if (config.output_limit[1] & output_limit_bit_3) {
737 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
738 shared_networks->name, shared_networks->available,
739 shared_networks->used,
740 (float) (100 * shared_networks->used) /
741 shared_networks->available,
742 shared_networks->touched,
743 shared_networks->touched + shared_networks->used,
745 (shared_networks->touched +
746 shared_networks->used)) /
747 shared_networks->available);
748 if (0 < num_backups) {
749 fprintf(outfile, "%7lu %8.3f",
750 shared_networks->backups,
751 (float) (100 * shared_networks->backups) /
752 shared_networks->available);
754 fprintf(outfile, "\n");
756 if (outfile == stdout) {
757 ret = fflush(stdout);
759 warn("output_cvs: fflush");
763 ret = fclose(outfile);
765 warn("output_cvs: fclose");