Compare commits

...

158 commits

Author SHA1 Message Date
Sami Kerola
1722d54103
chore: update web pages
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2025-04-28 15:32:04 +01:00
Sami Kerola
1c413b0653
release: 3.3
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2025-04-28 14:36:52 +01:00
Sami Kerola
d020e4d09f
output: update html javascripts
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2025-04-28 14:33:35 +01:00
Sami Kerola
f917d5b223
build-sys: update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2025-04-28 14:33:26 +01:00
Sami Kerola
5b7ab28314
build-sys: quote subshell execution in the autotools file
Ryan discovered a typo/issue while handling the man targets.  This change
fixes the issue.

Reported-by: Ryan Steinmetz <zi@freebsd.org>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2025-04-28 14:22:56 +01:00
Belkacem Daheb
dc649e27cd
getdata output: add start, end and hostname printing support for xml and json
Ensure strings are always null terminated.
2024-08-09 12:51:20 +01:00
luisδμ
7fc13c60e0
fix: avoid generation of unvalid JSON in summary
This can happen when there are no available shared networks.  A division by
zero throws 'nan', which is non JSON-valid unless it's surrounded by double
quotes.
2024-08-09 12:30:49 +01:00
Sami Kerola
5ed6e7688f
gnulib: update bootstrap and gitignore files
And it turns out mustach.c will not compile without config.h being
explicitly included before other headers, so let me do that.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2024-08-09 12:06:22 +01:00
M. van Brummelen
9c6336e5b6
docs: fix manual page groff warning
The only thing the change does is the way the manpage gets parsed, and fixes
follwing warning.

"W: dhcpd-pools: groff-message an.tmac:<standard input>:147: warning: tbl
preprocessor failed, or it or soelim was not run; table(s) likely not
rendered (TE macro called with TW register undefined)
[usr/share/man/man1/dhcpd-pools.1.gz:1]"

Reference: https://www.mail-archive.com/debian-devel@lists.debian.org/msg377263.html
Signed-off-by: M. van Brummelen <mvb@debian.org>
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
2024-08-09 11:00:02 +01:00
Sami Kerola
d94654e100
getdata: only emit warning when config include file cannot be read
Not being able to open primary config file will cause fatal error, where as
include files will only warn.  This is useful for setups that want to
publish some of the dhcp lease data, but not all.  Such setup obviously
required dhcpd server to have differnt account than dhcpd-pools, with
carefully managed read permissions.

Requested-by: Björn Lässig <b.laessig@pengutronix.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2024-01-28 16:07:56 +00:00
Sami Kerola
dc1f0b9b76
chore: update web links
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2023-09-02 11:55:16 +01:00
Belkacem Daheb
3d37ac0a2d
add start, end and hostname printing support for xml and json
In short it gets these parameters and prints them in json and xml formats.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2023-08-15 22:17:38 +01:00
Sami Kerola
102d017ed5
website: use https
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2023-03-26 11:15:36 +01:00
Sami Kerola
501bc15b43
update project web page
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2022-11-26 10:00:53 +00:00
Sami Kerola
0c5b8301dd
release: 3.2
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2022-06-04 12:42:00 +01:00
Sami Kerola
1d20604519
build-sys: routine update
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2022-06-04 12:40:39 +01:00
Sami Kerola
5126e63665
build-sys: autotools and gnulib related updates
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2021-09-05 15:52:07 +01:00
Sami Kerola
c7e0058994
config: remove unnecessary padding
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2021-09-05 15:51:29 +01:00
Sami Kerola
2ecfc86a06
build-sys: update .gitignore files
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2020-09-09 20:22:37 +01:00
Jean Benoit
0f19d44c1d
contrib: snmptest.pl SNMPwalk can't access to all variables/wrong sort
Large quantity of data will be missing when snmptest.pl is used.  The reason
is a sort in lexicographic order:

    $ snmpwalk -v2c -c public localhost .1.3.6.1.4.1.2021.250.255 |head
    iso.3.6.1.4.1.2021.250.255.2.1 = STRING:  "10.4.52.1"
    iso.3.6.1.4.1.2021.250.255.2.10 = STRING: "192.168.35.64"
    iso.3.6.1.4.1.2021.250.255.2.100 = STRING: "192.168.196.1"
    iso.3.6.1.4.1.2021.250.255.2.101 = STRING: "192.168.198.1"
    iso.3.6.1.4.1.2021.250.255.2.102 = STRING: "192.168.209.225"
    iso.3.6.1.4.1.2021.250.255.2.103 = STRING: "192.168.209.241"

SNMPGetNext after "root.2.1" should give "root.2.2".  Thus, lots of
variables are missing.

The function is now dependant on a CPAN module NetSNMP::OID, (debian/ubuntu
package is called libsnmp-perl).  This is probably not the most efficient
way to do it: walking the whole tree will be much slower.

Signed-off-by: Jean Benoit <jean@unistra.fr>
2020-09-04 19:38:17 +01:00
Sami Kerola
b005ce9a25
contrib: point out where one can find zabbix template
Thanks to Mathieu Morier for adding a Zabbix support.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2020-08-29 09:46:21 +01:00
Sami Kerola
45f7fc1514
release: 3.1
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2020-03-31 20:20:10 +01:00
Sami Kerola
ec613f762d
output: update javascripts
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2020-03-31 20:17:08 +01:00
Sami Kerola
e48768b041
build-sys: update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2020-03-31 20:14:34 +01:00
Sami Kerola
544e7ec0a5
output: add ethernet address priting support to --mustach
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-10-26 22:23:19 +01:00
Sami Kerola
b96c6c14d2
misc: fix spelling issues
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-09-12 22:29:44 +01:00
Sami Kerola
21194d2e4a
samples: make prometheus template less klunky
This should work nicer when displaying various statistics from prometheus
with grafana.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-07-27 22:53:42 +01:00
Sami Kerola
fb518b7a19
output: add warning and critical threshold counts to mustach
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-07-27 22:20:44 +01:00
Sami Kerola
707eafa670
build-sys: update .gitignore files
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-07-27 21:17:45 +01:00
Mark Sangster
07b4eaa480
output: fix warn and crit counts on shared networks
The crit/warn_count is tested against used rather than free.  It is only for
shared networks, the range correctly subtracts count from size to get its
free.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-04-15 19:34:28 +01:00
Sami Kerola
17d68b7e3e
various: tidy up variable scopes, and one name mismatch
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-03-26 21:26:51 +00:00
Sami Kerola
4f64902a9e
mustach: sync with most recent mustach upstream changes
Git: https://gitlab.com/jobol/mustach.git
Commit: 3a694bdc6cdd374358a30949206e315ed3428cf9
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-03-26 21:00:40 +00:00
Sami Kerola
008e9f17c1
other: use IP string lengths from netinet/in.h
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-03-23 22:19:13 +00:00
Sami Kerola
71714a0993
warnings: ensure optimal packing in structures
Add padding where needed and order structure when it makes alignment fall
naturally to better order, with a single padding at the end of structure.

Reference: http://www.catb.org/esr/structure-packing/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-02-17 11:43:02 +00:00
Sami Kerola
6f6369f517
various: fix few warnings
-Wmissing-variable-declarations -Wunreachable-code-break and -Wshadow.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-02-09 17:43:16 +00:00
Sami Kerola
8731c6a11f
fix typos
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-01-14 22:59:13 +00:00
Sami Kerola
d29b498cae
lib: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-01-04 22:44:11 +00:00
Sami Kerola
48e46e8698
other: use strftime() to generate date-time string
It is better to use library function to create date-time string than sprintf
various struct tm members.  In same go retire time() call that is obsoleted
by clock_gettime().

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2019-01-04 22:44:07 +00:00
Sami Kerola
4befdeeb47
getdata: remote dead code
These few lines has been part of code without any point in releases 2.17 to
3.0 and six and half years.  Oops.

Reference: ae7747db87
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-10-26 22:01:26 +01:00
Sami Kerola
9727bb28b9
drop images, java scripts, and such from web sitemap file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-08-26 09:32:15 +01:00
Sami Kerola
5027b50ade
sort: ensure NaN will not trip over comp_double()
In unlikely event of NaN being compared avoid exception.  If NaN appears in
input data it will be evaluated as equal with any value.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-07-23 21:41:59 +01:00
Sami Kerola
27c70a0efe
fix switch missing default case warnings
src/other.c:387:3: warning: switch missing default case [-Wswitch-default]

The one in do_counting() should be unreachable, so add abort() call to it.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-07-23 21:33:45 +01:00
Sami Kerola
7fe686b417
webpages: use html sample output
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-20 15:54:58 +01:00
Sami Kerola
3f85360c64
main: move output_format to state, and rename color_format
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-20 12:03:07 +01:00
Sami Kerola
e8e9d49ebb
main: move print_mac_addreses to state structure
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-20 11:47:30 +01:00
Sami Kerola
4e7ab66fd4
fix typo
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-15 21:31:52 +01:00
Sami Kerola
b568725e7d
main: simplify option parsing
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-15 21:16:38 +01:00
Sami Kerola
a192f51545
output: fix implicit conversion
src/output.c:731:38: warning: implicit conversion from ‘float’ to ‘double’
when passing argument to function [-Wdouble-promotion]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-05-04 22:22:02 +01:00
Sami Kerola
679d63dd9f
add .mailmap
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-02-24 11:48:02 +00:00
Sami Kerola
0fe89808ee
docs: fix peoples name in THANKS file to have correct characters
Unicode fixes.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2018-01-14 18:35:15 +00:00
Sami Kerola
447241e6c3
tests: improve coverage
Add error condition checks.  Add lease file binding states.  Check all
output formats.  Check leases file that is in mad order, cse all sorting
methods when checking this.  Use json output to check status classfications.
Add cidr range checks.  Add conf include and comment parsing input checks.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-26 15:14:49 +00:00
Sami Kerola
2849dde21b
build-sys: add coverage files to .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-26 13:59:17 +00:00
Sami Kerola
813e320b68
webpage: add instructions how to get output you need
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-15 20:09:52 +00:00
Sami Kerola
e6e90b4d62
release: 3.0
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-15 13:29:46 +00:00
Sami Kerola
a1d2bd2cf7
usage: --skip=ignored is actually 'suppressed'
When making --skip to take arguments ignored was for moment a work name for
'suppressed' state, and that was accidentally left to usage() output.

Reference: 3369278fc0
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 22:30:07 +00:00
Sami Kerola
46ec42182b
output: add some trivia data to json output
These are software version, dhcpd conf and leases paths and mtime epoch
timestamps.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 20:24:15 +00:00
Sami Kerola
444815f964
orther: fix xstrstr_init() memcmp() return value usage
This is a bug.  The xstrstr_init initialized wrong IP version functions when
this function was the first to run and set function pointers.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 18:58:11 +00:00
Sami Kerola
6d737a7607
output: unify time stamp creations
Use iso time stamp in both mustach and html outputs.  Effectively this is a
removal of libc langinfo D_T_FMT format, that pulled a lot of gnulib stuff
to project almost unnecessarily.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 11:08:46 +00:00
Sami Kerola
ff3d9523e6
output: add more items to mustach tags
Base level printing; localstime, number of ranges and shared networks,
project version, and file paths and time stamps.

Also print error and stop template processing when unknown tag is
encountered.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 10:48:52 +00:00
Sami Kerola
d24313d25a
output: remove unused variable attribute
The closure is used.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 00:17:56 +00:00
Sami Kerola
c687f38ed6
docs: improve doxygen documentation
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-14 00:11:46 +00:00
Sami Kerola
887845df2a
misc: move couple enums from global scope to file scope
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 21:55:14 +00:00
Sami Kerola
74b697321f
misc: move command line option parsing to separate function
Earlier main() had lots of temporary variables related to command line
parsing.  By moving these to separate function runtime can forget these
variables when moving on.  If nothing else this makes running gdb nicer when
debugging crashes, but as said stack memory should also be spared for better
purpose.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 21:52:03 +00:00
Sami Kerola
3369278fc0
output: make --skip to take arguments what will be skipped
Accidental typo in usage() caused realisation making skipping to fully
controllable is good idea.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 20:23:12 +00:00
Sami Kerola
e4f7259cf6
samples: add prometheus text file collector mustach template
Because prometheus needs timestamp information add that to mustach, and
update manual page what tags are available.

Reference: https://prometheus.io/docs/instrumenting/exposition_formats/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 14:18:05 +00:00
Sami Kerola
eabaa8adc2
thanks: add Troy D. Hanson to credits about uthash
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 11:53:21 +00:00
Sami Kerola
8fba5c5e6b
clean up: fix couple compiler warnings
src/sort.c:255:5: warning: no previous prototype for 'merge'
src/sort.c:290:2: warning: ISO C90 forbids mixed declarations and code
src/mustach-dhcpd-pools.c:67:5: warning: no previous prototype for 'must_put_err'
src/output.c:109:26: warning: comparing floating point with == or != is unsafe (x5)

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 11:37:18 +00:00
Sami Kerola
88a3f1eb53
hash: include stdlib.h to avoid implicit declarations
Reported-by: Frank Bulk <fbulk@mypremieronline.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 11:37:15 +00:00
Sami Kerola
8ae5fbf489
output: improve html table
Update DataTables and Bootstrap versions.  Add free IP counts to table.
Replace yellow as warning with magenta that is easier to read from white
background.  Use italic and bold to emphasis warning and critical.  Remove
strips.  Use ascent percent sort by default.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 10:16:34 +00:00
Sami Kerola
b2c764924b
output: shared net can be in suppressed state
Avoid calling abort() when this very unlikely situation happens.

Reference: 48962004b8
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-13 09:57:22 +00:00
Sami Kerola
242c58f45e
output: display more entries in html table by default
And add 'All' to 'Show number of entries' menu.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 23:14:23 +00:00
Sami Kerola
c029c7581a
output: make warning and critical colors work in html output
Users should combine this with --color=always to web pages to work
correctly.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 22:19:09 +00:00
Sami Kerola
a64630aa49
output: move shared net andn range status check to output_helper
Having same logic in many places is error prone if and when the logic needs
maintenance.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 17:43:42 +00:00
Sami Kerola
15f08bbf02
output: make --skip-ok to effect --perfdata
Reported-by: Frank Bulk <fbulk@mypremieronline.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 17:31:01 +00:00
Sami Kerola
ef5421ed05
analysis: shared networks to be linked list
This way memory is allocated only for items that are in use, and walking
through shared network items is also more straightforward.

As an unfortunate side effect in --perfdata output shared networks are no
longer printed in reverse order.  This should be a cosmetic issue.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 16:54:00 +00:00
Sami Kerola
a237c11d5a
output: improve mustach template parsing error
Following error did not inform clearly what is wrong.

$ ./dhcpd-pools -l samples/dhcpd.leases -c samples/dhcpd.conf -fm
./dhcpd-pools: must_read_template: open: (null): Bad address

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 15:22:46 +00:00
Sami Kerola
5a8c178924
other: add Jose Bollo to version output credits
Be also a little bit more verbose about licenses in version output.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 15:12:16 +00:00
Sami Kerola
d25e7afa1c
analyze: bug fix shared networks counts
This also fixes backup state counts that were added to shared networks
twice, making the numbers to be much greater than they really where.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 15:12:16 +00:00
Sami Kerola
7cd381ed83
all files: re-indent
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 15:12:16 +00:00
Sami Kerola
1875a13733
all files: replace global variables with runtime config state structure
Earlier variables magically appeared to scope of functions that took void as
argument.  One could figure out perhaps they were globals, but programs that
do that are unnessarily hard to follow.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-12 15:12:15 +00:00
Sami Kerola
adda925c1e
clean up: remove unused variable
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 23:59:13 +00:00
Sami Kerola
3dda0a77a5
output: deduplicate file closing code
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 23:09:33 +00:00
Sami Kerola
7575294c36
usage: add error message informing mustach support is not available
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 21:15:36 +00:00
Sami Kerola
39b2811aa7
build-sys: omit mustach compilation when it cannot work
For example mac does not have open_memstream(3), and strndupa(3) can also be
missing.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 16:13:14 +00:00
Sami Kerola
b96f8cd8ad
gnulib: use nstrftime instead of strftime
The strftime module is obsolete.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 15:37:07 +00:00
Sami Kerola
54cedc1001
output: include stdlib.h to avoid compilation error
The stdlib.h has EXIT_FAILURE and free(3).

Reported-by: Sebastián Cramatte <scramatte@nixus.es>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 14:29:00 +00:00
Sami Kerola
e4baff79bd
output: add must_put_err() utility function
This function deals situation when mustach put happens before enter, that is
a sign of an invalid input template.  Good side of adding this function is
that dhcpd-pools does not need to modify code provided by Jose.

Reference: 66183bc7c7
Proposed-by: José Bollo <jobol@nonadev.net>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 09:00:33 +00:00
Sami Kerola
4fc4bcd083
output: save and reuse output helper results
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 08:39:50 +00:00
Sami Kerola
d5ae2a80c0
output: do not skip over first range in mustach output
Off by one that is caused by must_next_range() advancing pointer, and moving
over the first range.  Fix by setting indexes one step backwards, that is
not excellent but better than copying skip_ok stuff to must_enter().

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 08:20:10 +00:00
Sami Kerola
50fc4ebe9d
output: avoid mixing ntop_ipaddr() output buffers
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-11 08:19:56 +00:00
Sami Kerola
66183bc7c7
output: make mustach processing more robust
Fix issues found with afl-fuzz.  It is a pity I had to change mustach.c it
is no longer exactly the same as upstream.  Lets see if Jose will accept
these changes.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-09 19:49:37 +00:00
Sami Kerola
2ec953858b
tests: add mustach check
Use samples directory data as input to ensure they do not break.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-09 19:49:17 +00:00
Sami Kerola
39e6e65201
docs: add mustach sample files
Include samples to installation, and give a hint to user where it can be
found in manual page.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-09 19:49:17 +00:00
Sami Kerola
74fdf90980
output: add separate first_ip and last_ip to json and mustach outputs
This give greater liberty to people who are using these formats to do what
ever they need to.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-09 19:49:17 +00:00
Sami Kerola
7d9a5b5561
output: add mustach templating support
Based on José Bollo's mustache C implementation.  This adaptation uses
project specific data structures to avoid overhead with json parsing.

Reference: https://gitlab.com/jobol/mustach.git
Commit: d84608a69033d38c81b8fcff0cb272e225dd5428
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-09 19:49:13 +00:00
Sami Kerola
fe847bb9b1
output: use range_output_helper() value in output_xml()
Earlier commit started to use range_output_helper() in output_xml() so
remove the unnecessary calls to get_range_size().

Reference: c55c823753
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-08 23:04:28 +00:00
Sami Kerola
1182ec4cc9
include: use project specific header guard
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-07 13:45:17 +00:00
Sami Kerola
e9736f74e7
getdata: do not use 'else' after 'continue'
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-07 13:44:50 +00:00
Sami Kerola
e5cd46e4e9
other: do not use 'else' after 'return'
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-07 13:12:37 +00:00
Sami Kerola
eb7547c742
output: json nan values need quoting
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-07 10:41:53 +00:00
Sami Kerola
8fe7dc2c03
other: add --skip-ok to usage() output
Forgot in previous commit.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-06 22:34:06 +00:00
Sami Kerola
c55c823753
output: add --skip-ok option
Omit ranges and shared networks that do not exceed warning or critical
thresholds.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-06 22:11:47 +00:00
Sami Kerola
e079cc16e0
output: include earlier missing data to json output
This commit adds all the data that is in text output to json output.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-06 21:39:15 +00:00
Sami Kerola
344ed2900d
output: add color support to text output
When --warning or --critical thresholds are defined with text output lines
that exceed threshold will be either yellow (warning) or red (critical).

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-06 21:31:57 +00:00
Sami Kerola
48962004b8
output: add output helper functions
There is too much repetative confusing maths near printouts.  Move that
stuff to a function.

This change also fixes --snet-alarms option counting issue in range that
were not part of any shared network were ignored.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-05 16:21:20 +00:00
Sami Kerola
05f8208518
getdata: fix typo
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-05 10:01:07 +00:00
Sami Kerola
abf5d04736
output: make output_analysis() to be regular function
This commit makes it possible to define alarming thresholds at the same time
with other output formats.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-11-05 09:51:35 +00:00
Sami Kerola
9deeae8c36
update sitemap
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-23 09:18:35 +01:00
Sami Kerola
548ce63963
release: update web page meta data
This should have been done before tag.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-23 08:53:18 +01:00
Sami Kerola
58a31513fe
release: 2.29
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-23 08:17:38 +01:00
Sami Kerola
804aa3236d
docs: update maintainer gpg key
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 09:50:55 +01:00
Sami Kerola
af1ae94112
docs: add build instruction link to the project web page
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 09:17:15 +01:00
Sami Kerola
fefd8d26cf
docs: tell what needs to be done when releasing new version
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 09:00:25 +01:00
Sami Kerola
1d47eb9a1c
docs: update doxygen configuration file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 08:43:19 +01:00
Sami Kerola
0c32a67ff1
build-sys: update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 08:41:41 +01:00
Sami Kerola
bb0fa9adae
getdata: add cidr range support
This makes 'range6 123::/45' style cidr notation to be understood as address
range.  Earlier ranges that used cidr failed to parse completely.

Reported-by: Jeff Bailey <jeffrey.bailey@bt.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-17 00:03:06 +01:00
Sami Kerola
48d0629881
lib: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-09 10:29:04 +01:00
Sami Kerola
782f63c3ad
add --ip-version option to force either IPv4 or IPv6 analysis
Proposed-by: Jeff Balley <jeffrey.bailey@bt.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-09-09 10:28:27 +01:00
Boris Lytochkin
b9cff0d814
introduce -A arg: treat single subnets as shared-network with CIDR as their name
Current output makes some false-positives for situations when multiple
ranges are specified inside single network, for example:

subnet 10.0.0.0 netmask 255.255.254.0 {
	...
	range 10.0.0.1 10.0.0.254;
	range 10.0.1.1 10.0.1.253;
	...
}

An alert for range 10.0.0.1 - 10.0.0.254 will be raised even in situations
when range 10.0.1.1 - 10.0.1.253 is completely empty.  To cope with this
issue, an -A option is added to treat all single networks as shared-network.
This option changes output for both range and shared networks output if
specified.  Frankly saying, using network CIDR as network name is much more
sane for me than 'All Networks'.

Signed-off-by: Boris Lytochkin <lytboris@yandex-team.ru>
2017-07-15 17:26:15 +01:00
Sami Kerola
dff991666e
lib: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-05-21 17:30:24 +01:00
Sami Kerola
242ef3109b
variable: add const to print_mac_addreses_tmp
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-05-21 17:21:57 +01:00
Sami Kerola
1c8b799799
fix typo
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-05-06 16:44:19 +01:00
Sami Kerola
e93fc5dba4
lib: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-04-15 20:42:58 +01:00
Sami Kerola
c3c3fc6e40
getdata: fpos_t is not easy to print correctly
On some systems fpos_t may be a complex object, so printing it is not as
easy as ftell() position.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-04-15 20:42:07 +01:00
Sami Kerola
e9223a852c
contrib: Klaus Slott told about opensuse package
Add opensuse rpm as an example how to build one.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-04-10 13:12:34 +01:00
Sami Kerola
9a52619385
style: use same argument names in header and source file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-04-07 22:56:19 +01:00
Sami Kerola
2b75a0d78e
getdata: remove POSIX_FADV_NOREUSE
It is too difficult to know what users might want to do.  Maybe some run
this software all the time from a monitoring system, and in cases like that
it is best to have caches helping.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-02-04 23:11:43 +00:00
Sami Kerola
344e01c1f6
output: add include avoid referringt to undefined definition
Reference: c4a654a149
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-02-04 18:00:02 +00:00
Sami Kerola
c4a654a149
output: fix timestamp localization on html page
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-12 22:40:33 +00:00
Sami Kerola
a905b50943
getdata: report position in config file when parsing fails
It seems that one can reach the abort() with severely broken configuration
file, that is extremely unlikely to run without parser error when given to
ISC dhcpd.  So such files ought to be impossible, and it is good enough for
this software to report position where parsing cannot be continued.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-08 11:49:41 +00:00
Sami Kerola
ae2edb0fbc
man: remove old html table only option argument from manual
Incomplete html page, that was just a html table, was removed some time ago
but deprecated option arguments were unfortunately left to manual that are
now removed.

Reference: 1299737d76
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-07 11:01:22 +00:00
Sami Kerola
5eae1b41a7
man: improve synopsis and output limit
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-06 23:36:36 +00:00
Sami Kerola
ea7fd91876
remove const and pure function attributes
Most of these functions take pointers as input argument, so they cannot be
considered neiter const or pure.  In same go fix few issues noticed when
compiling with smatch.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-06 23:14:28 +00:00
Sami Kerola
11c0b23d77
portability: add gnulib modules earlier missing
Found with help if autoscan.  In same go update lib/.gitignore file.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-06 22:33:08 +00:00
Sami Kerola
aaad35a8c9
output: remove unnecessary increment
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2017-01-02 21:21:27 +00:00
Sami Kerola
a6b77ab785
docs: fix couple typos and improve a sentence in README
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-10-02 21:35:29 +01:00
Sami Kerola
7740927721
build-sys: always use restrict found by autoconf
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-08-16 13:25:23 +01:00
Sami Kerola
9bb30b29ca
build-sys: default to ./configure --enable-silent-rules
This makes compiler to options not to be shown when running make, and that
allows noticing warnings more easily.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-08-15 21:18:29 +01:00
Sami Kerola
1b35a16d95
analyze: use while() when for() is less fit to purpose
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-07-03 14:00:00 +01:00
Sami Kerola
d26c858c13
build-sys: update gnulib .gitignore file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-05-29 21:22:13 +01:00
Sami Kerola
840d2143e6
build-sys: update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-05-29 21:20:39 +01:00
Sami Kerola
a3ef3d617f
output: check alarming mode can output successfully
Fixes also a resource leak.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-24 12:29:50 +01:00
Sami Kerola
f6e256243d
fix doap file git repository and license section
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-23 22:55:21 +01:00
Sami Kerola
ccd5370d9c
add dhcpd-pools Description Of A Project file
Reference: https://github.com/edumbill/doap/wiki
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-23 22:33:08 +01:00
Sami Kerola
c4ebafb106
argument parsing: fix compiler warning
src/dhcpd-pools.c:193:18: warning: comparison of integers of different
signs: 'int' and 'unsigned long' [-Wsign-compare]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-23 16:35:38 +01:00
Sami Kerola
87c06a1b13
getdata: get rid of remaining stdbool usage
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-23 16:32:08 +01:00
Sami Kerola
8a8c28a17e
contrib: remove awk file duplicate
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-01 23:11:37 +01:00
Sami Kerola
5a33b619d1
contrib: remove unnecessary cgi script
The html format is done using Bootstrap and DataTables.  That deprecatated
need for having cgi to wrap dhcpd-pools.

Reference: 1299737d76
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-01 23:11:37 +01:00
Sami Kerola
e5f9a77511
contrib: add archlinux package build file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-04-01 23:11:36 +01:00
Manuel Hachtkemper
32e2d399a0
alarming: add additional performance data
Options -p or --perfdata (in alarming mode) now enable the output of
additional performance data, i.e.  used, touched and backup addresses per
subnet.

Signed-off-by: Manuel Hachtkemper <hacman@math.uni-bonn.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-03-31 22:34:27 +01:00
Sami Kerola
c305e2f82c
tests: add range definition flip test
This test ensure 10b06d88f0 will not get
regression in future.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-02-18 23:05:24 +00:00
Sami Kerola
10b06d88f0
getdata: flip ranges if they are in greater smaller order
Apparently ISC dhcpd allows marking ranges in order from greater IP to
smaller.  In these cases first and last IPs are fliped, so that the rest of
the processing can be done without alterations.

Reported-by: Ivanov Ivan <mgfnv9@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2016-02-18 22:35:56 +00:00
Sami Kerola
3d0c510475
webpages: compress sitemap.txt file
More than 90% is hefty pay-off.

$ gzip -v -d  sitemap.txt.gz
sitemap.txt.gz:  93.5% -- replaced with sitemap.txt

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-29 21:52:48 +00:00
Sami Kerola
46641751b4
webpages: make index page mobile device friendly
Use css max-width instead of width this permits narrow screen to wrap lines,
this makes the index page more usable when browsing with a mobile phone or
some other device with limited horizontal dimension.  Also get rid of <pre>
tag, and make the sample usage more realistic.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-29 21:29:32 +00:00
Sami Kerola
d717a043bf
use long options in .indent.pro file
Short options are impossible to understand without looking to manual page.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-10 22:42:54 +00:00
Sami Kerola
03b1edb188
add sitemap url to robots.txt file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-07 10:55:45 +00:00
Sami Kerola
1dcf762967
add dhcpd-pools website content to a subdirectory
Start using git to backup of the website content.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-07 10:32:02 +00:00
Sami Kerola
17f1fb7f5e
tell in README when ./bootstrap is needed
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-06 19:08:08 +00:00
109 changed files with 7657 additions and 2127 deletions

3
.gitignore vendored
View file

@ -1,5 +1,8 @@
# Wildcard + in any subdir.
*.o
*.gcno
*.gcda
*.[ch].gcov
# Exact filename in any subdir.
.deps

2
.mailmap Normal file
View file

@ -0,0 +1,2 @@
Sami Kerola <kerolasa@iki.fi>
Sami Kerola <kerolasa@iki.fi> <sami.kerola@tomtom.com>

View file

@ -1,7 +1,6 @@
## Makefile.am -- Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = gnu
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = \
.version \
@ -35,11 +34,12 @@ edit_cmd = sed \
-e 's|@SHELL[@]|$(SHELL)|g' \
-e 's|@VERSION[@]|$(VERSION)|g' \
-e 's|@bindir[@]|$(bindir)|g' \
-e 's|@docdir[@]|$(docdir)|g' \
-e 's|@top_srcdir[@]|$(top_srcdir)|g'
$(PATHFILES): Makefile
@ rm -f $@ $@.tmp
$(AM_V_at) test -d $(dir $@) || mkdir -p $(dir $@)
$(AM_V_at) mkdir -p $$(dirname $@)
$(AM_V_GEN) srcdir=''; \
test -f ./$@.in || srcdir=$(srcdir)/; \
$(edit_cmd) $${srcdir}$@.in >$@.tmp
@ -48,6 +48,7 @@ $(PATHFILES): Makefile
include contrib/Makemodule.am
include doc/Makemodule.am
include man/Makemodule.am
include samples/Makemodule.am
include src/Makemodule.am
include tests/Makemodule.am

189
NEWS
View file

@ -5,7 +5,194 @@ See the end for copying conditions.
Please send dhcpd-pools bug reports to kerolasa@iki.fi.
gpg: Signature is crated using RSA key ID FDE9B739.
gpg: Signature is crated using RSA key ID 8ED396E37E38D471A00530D3A9553245FDE9B739.
Version 3.3
Belkacem Daheb (2):
add start, end and hostname printing support for xml and json
getdata output: add start, end and hostname printing support for xml and json
M. van Brummelen (1):
docs: fix manual page groff warning
Sami Kerola (9):
update project web page
website: use https
chore: update web links
getdata: only emit warning when config include file cannot be read
gnulib: update bootstrap and gitignore files
build-sys: quote subshell execution in the autotools file
build-sys: update bootstrap from gnulib
output: update html javascripts
release: 3.3
luisδμ (1):
fix: avoid generation of unvalid JSON in summary
Version 3.2
Jean Benoit (1):
contrib: snmptest.pl SNMPwalk can't access to all variables/wrong sort
Sami Kerola (5):
contrib: point out where one can find zabbix template
build-sys: update .gitignore files
config: remove unnecessary padding
build-sys: autotools and gnulib related updates
build-sys: routine update
release: 3.2
Version 3.1
Mark Sangster (1):
output: fix warn and crit counts on shared networks
Sami Kerola (31):
webpage: add instructions how to get output you need
build-sys: add coverage files to .gitignore
tests: improve coverage
docs: fix peoples name in THANKS file to have correct characters
add .mailmap
output: fix implicit conversion
main: simplify option parsing
fix typo
main: move print_mac_addreses to state structure
main: move output_format to state, and rename color_format
webpages: use html sample output
fix switch missing default case warnings
sort: ensure NaN will not trip over comp_double()
drop images, java scripts, and such from web sitemap file
getdata: remote dead code
other: use strftime() to generate date-time string
lib: update .gitignore
fix typos
various: fix few warnings
warnings: ensure optimal packing in structures
other: use IP string lengths from netinet/in.h
mustach: sync with most recent mustach upstream changes
various: tidy up variable scopes, and one name mismatch
build-sys: update .gitignore files
output: add warning and critical threshold counts to mustach
samples: make prometheus template less klunky
misc: fix spelling issues
output: add ethernet address priting support to --mustach
build-sys: update bootstrap from gnulib
output: update javascripts
release: 3.1
Version 3.0
Sami Kerola (56):
release: update web page meta data
update sitemap
output: make output_analysis() to be regular function
getdata: fix typo
output: add output helper functions
output: add color support to text output
output: include earlier missing data to json output
output: add --skip-ok option
other: add --skip-ok to usage() output
output: json nan values need quoting
other: do not use 'else' after 'return'
getdata: do not use 'else' after 'continue'
include: use project specific header guard
output: use range_output_helper() value in output_xml()
output: add mustach templating support
output: add separate first_ip and last_ip to json and mustach outputs
docs: add mustach sample files
tests: add mustach check
output: make mustach processing more robust
output: avoid mixing ntop_ipaddr() output buffers
output: do not skip over first range in mustach output
output: save and reuse output helper results
output: add must_put_err() utility function
output: include stdlib.h to avoid compilation error
gnulib: use nstrftime instead of strftime
build-sys: omit mustach compilation when it cannot work
usage: add error message informing mustach support is not available
output: deduplicate file closing code
clean up: remove unused variable
all files: replace global variables with runtime config state structure
all files: re-indent
analyze: bug fix shared networks counts
other: add Jose Bollo to version output credits
output: improve mustach template parsing error
analysis: shared networks to be linked list
output: make --skip-ok to effect --perfdata
output: move shared net andn range status check to output_helper
output: make warning and critical colors work in html output
output: display more entries in html table by default
output: shared net can be in suppressed state
output: improve html table
hash: include stdlib.h to avoid implicit declarations
clean up: fix couple compiler warnings
thanks: add Troy D. Hanson to credits about uthash
samples: add prometheus text file collector mustach template
output: make --skip to take arguments what will be skipped
misc: move command line option parsing to separate function
misc: move couple enums from global scope to file scope
docs: improve doxygen documentation
output: remove unused variable attribute
output: add more items to mustach tags
output: unify time stamp creations
orther: fix xstrstr_init() memcmp() return value usage
output: add some trivia data to json output
usage: --skip=ignored is actually 'suppressed'
release: 3.0
Version 2.29
Boris Lytochkin (1):
introduce -A arg: treat single subnets as shared-network with CIDR as their name
Manuel Hachtkemper (1):
alarming: add additional performance data
Sami Kerola (47):
tell in README when ./bootstrap is needed
add dhcpd-pools website content to a subdirectory
add sitemap url to robots.txt file
use long options in .indent.pro file
webpages: make index page mobile device friendly
webpages: compress sitemap.txt file
getdata: flip ranges if they are in greater smaller order
tests: add range definition flip test
contrib: add archlinux package build file
contrib: remove unnecessary cgi script
contrib: remove awk file duplicate
getdata: get rid of remaining stdbool usage
argument parsing: fix compiler warning
add dhcpd-pools Description Of A Project file
fix doap file git repository and license section
output: check alarming mode can output successfully
build-sys: update bootstrap from gnulib
build-sys: update gnulib .gitignore file
analyze: use while() when for() is less fit to purpose
build-sys: default to ./configure --enable-silent-rules
build-sys: always use restrict found by autoconf
docs: fix couple typos and improve a sentence in README
output: remove unnecessary increment
portability: add gnulib modules earlier missing
remove const and pure function attributes
man: improve synopsis and output limit
man: remove old html table only option argument from manual
getdata: report position in config file when parsing fails
output: fix timestamp localization on html page
output: add include avoid referringt to undefined definition
getdata: remove POSIX_FADV_NOREUSE
style: use same argument names in header and source file
contrib: Klaus Slott told about opensuse package
getdata: fpos_t is not easy to print correctly
lib: update .gitignore
fix typo
variable: add const to print_mac_addreses_tmp
lib: update .gitignore
add --ip-version option to force either IPv4 or IPv6 analysis
lib: update .gitignore
getdata: add cidr range support
build-sys: update bootstrap from gnulib
docs: update doxygen configuration file
docs: tell what needs to be done when releasing new version
docs: add build instruction link to the project web page
docs: update maintainer gpg key
release: 2.29
Version 2.28
Sami Kerola (26):

8
README
View file

@ -11,7 +11,7 @@ Quick start.
Build the dhcpd-pools project.
cd /tmp/dhcpd-pools
./bootstrap
./bootstrap # only when building git clone
./configure --with-uthash=/tmp/uthash-master/include
make
make check
@ -22,13 +22,13 @@ Quick start.
./configure --help
Read the manual to see what options are available, and what they to.
Remember to read the friendly manual page.
man ./man/dhcpd-pools.1
Dependencies to other projects.
http://www.gnu.org/software/gnulib/
https://www.gnu.org/software/gnulib/
You can avoid repeated gnulib downloads by setting
GNULIB_SRCDIR environment variable. For example:
@ -39,7 +39,7 @@ Dependencies to other projects.
Assumign detached gnulib please remember to git pull the
latest updates before building dhcpd-pools.
http://uthash.sourceforge.net/
https://troydhanson.github.io/uthash/
See quick start.

29
THANKS
View file

@ -5,23 +5,24 @@ Project is maintained by Sami Kerola <kerolasa@iki.fi>
People who reported problems, give improvement suggestions or even
contributed code.
Otto J. Mäkelä
Otto J. Mäkelä
Mika Paananen
Frank Bulk
Roar Pettersen
Jeff Wieland
Rusty
Fredrik Vöcks
Fredrik Vöcks
Dan Thorson
Stian Øvrevåge
Stian Øvrevåge
Dominic Germain
Anders Låstad
Anders Låstad
Thor Eivind Brantzeg
Ahmed AL Dakhil
Adam Ciarcinski
Rezso Gajdóczy
Rezső Gajdóczy
Robert Viou
Enno Gröper
Enno Gröper
Troy D. Hanson
Ryan Malek
Cheer Xiao
Gilles Bouthenot
@ -29,7 +30,7 @@ Helmut Grohne
Joey D.
Ryan Steinmetz
Dan Pritts
Fredrik Lysén
Fredrik Lysén
Conor McCarthy
Wolfgang Steudel
Aaron Paetznick
@ -37,3 +38,17 @@ Tim Cantin
Martijn van Brummelen
Anton Tkachev
Derrick Lin
Ivanov Ivan
Manuel Hachtkemper
Klaus Slott
Boris Lytochkin
Jeff Bailey
José Bollo
Sebastián Cramatte
Mark Sangster
Brent Swingle
Mathieu Morier
Jean Benoit
Belkacem Daheb
Björn Lässig
Luisδμ

17
TODO
View file

@ -14,3 +14,20 @@ o When time stamps are part of lease situation evaluation (see
bug 1) add a --now switch which will one can use to change when
expiry happens.
o Add lease time histogram support.
### When releasing
o Update gnulib
o Update bootstrap
o Update DataTables, and bootstrap versions; see https://datatables.net/download/index
o Update NEWS, webpages/index.html dateModified & version
o Make annotated git tag
o ./configure --enable-doxygen && make distcheck
o BROWSER=cat man -H ./man/dhcpd-pools.1 | tee ./webpages/man.html
o gpg --armor --detach-sign dhcpd-pools*tar*
* Update sitemap
o Upload files to sourceforge
o mv doc/html webpages/doxygen
o sftp index.html man.html doxygen/* -> sourceforge web
remove old doxygen before uploading new
o Send email to dhcpd-pools-announce@lists.sourceforge.net subject: Version 3.n is released

2010
bootstrap

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
# Bootstrap configuration.
# Bootstrap configuration. -*- sh -*-
# Copyright (C) 2006-2012 Free Software Foundation, Inc.
# Copyright (C) 2006-2025 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
@ -13,7 +13,7 @@
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# gnulib modules used by this package.
@ -29,8 +29,8 @@ gnulib_modules="
getopt-gnu
inet_pton
isnan
langinfo
netinet_in
nstrftime
progname
quote
realloc-gnu
@ -40,8 +40,9 @@ gnulib_modules="
stdlib
stpncpy
strdup-posix
strftime
strstr
strtod
time_r
xalloc
"
@ -63,7 +64,7 @@ XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
gettext_external=0
grep '^[ ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null &&
gettext_external=1
grep '^[ ]*AM_GNU_GETTEXT(\[external\]' configure.ac > /dev/null &&
grep '^[ ]*AM_GNU_GETTEXT(\[external]' configure.ac > /dev/null &&
gettext_external=1
if test $gettext_external = 1; then

View file

@ -1,6 +1,7 @@
/ar-lib
/compile
/config.guess
/config.rpath
/config.sub
/depcomp
/install-sh

View file

@ -1,12 +1,12 @@
#!/bin/sh
# Print a version string.
scriptversion=2012-12-31.23; # UTC
scriptversion=2022-01-27.18; # UTC
# Copyright (C) 2007-2013 Free Software Foundation, Inc.
# Copyright (C) 2007-2022 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
@ -15,9 +15,9 @@ scriptversion=2012-12-31.23; # UTC
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
# This script is derived from GIT-VERSION-GEN from GIT: https://git-scm.com/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
@ -65,19 +65,21 @@ scriptversion=2012-12-31.23; # UTC
# EXTRA_DIST = $(top_srcdir)/.version
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# echo '$(VERSION)' > $@-t
# mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
# echo '$(VERSION)' > $(distdir)/.tarball-version
me=$0
year=`expr "$scriptversion" : '\([^-]*\)'`
version="git-version-gen $scriptversion
Copyright 2011 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING."
Copyright (C) ${year} Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law."
usage="\
Usage: $me [OPTION]... \$srcdir/.tarball-version [TAG-NORMALIZATION-SED-SCRIPT]
@ -85,8 +87,9 @@ Print a version string.
Options:
--prefix prefix of git tags (default 'v')
--fallback fallback version to use if \"git --version\" fails
--prefix PREFIX prefix of git tags (default 'v')
--fallback VERSION
fallback version to use if \"git --version\" fails
--help display this help and exit
--version output version information and exit
@ -100,8 +103,8 @@ while test $# -gt 0; do
case $1 in
--help) echo "$usage"; exit 0;;
--version) echo "$version"; exit 0;;
--prefix) shift; prefix="$1";;
--fallback) shift; fallback="$1";;
--prefix) shift; prefix=${1?};;
--fallback) shift; fallback=${1?};;
-*)
echo "$0: Unknown option '$1'." >&2
echo "$0: Try '--help' for more information." >&2
@ -140,11 +143,9 @@ then
v=`cat $tarball_version_file` || v=
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test "x$v" = x \
&& echo "$0: WARNING: $tarball_version_file is missing or damaged" 1>&2
&& echo "$0: WARNING: $tarball_version_file is damaged" 1>&2
fi
if test "x$v" != x
@ -166,9 +167,10 @@ then
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
vprefix=`expr "X$v" : 'X\(.*\)-g[^-]*$'` || vprefix=$v
case $vprefix in
*-*) : git describe is probably okay three part flavor ;;
*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
@ -183,9 +185,9 @@ then
;;
esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
# Change the penultimate "-" to ".", for version-comparing tools.
# Remove the "g" to save a byte.
v=`echo "$v" | sed 's/-\([^-]*\)-g\([^-]*\)$/.\1-\2/'`;
v_from_git=1
elif test "x$fallback" = x || git --version >/dev/null 2>&1; then
v=UNKNOWN
@ -199,7 +201,7 @@ v=`echo "$v" |sed "s/^$prefix//"`
# string we're using came from git. I.e., skip the test if it's "UNKNOWN"
# or if it came from .tarball-version.
if test "x$v_from_git" != x; then
# Don't declare a version "dirty" merely because a time stamp has changed.
# Don't declare a version "dirty" merely because a timestamp has changed.
git update-index --refresh > /dev/null 2>&1
dirty=`exec 2>/dev/null;git diff-index --name-only HEAD` || dirty=
@ -214,12 +216,12 @@ if test "x$v_from_git" != x; then
fi
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
echo "$v" | tr -d "$nl"
printf %s "$v"
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -2,11 +2,11 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_MACRO_DIRS([m4])
AC_INIT([dhcpd-pools],
[m4_esyscmd([build-aux/git-version-gen .tarball-version])],
[kerolasa@iki.fi],[],
[http://dhcpd-pools.sourceforge.net/])
[https://dhcpd-pools.sourceforge.net/])
PACKAGE_MAINTAINER="Sami Kerola"
AC_SUBST([PACKAGE_MAINTAINER])
AC_CONFIG_AUX_DIR([build-aux])
@ -24,6 +24,9 @@ AM_INIT_AUTOMAKE([
AC_CONFIG_SRCDIR([src/dhcpd-pools.h])
AC_CONFIG_HEADERS([config.h])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
# Checks for programs
AC_USE_SYSTEM_EXTENSIONS
AC_C_RESTRICT
@ -66,8 +69,24 @@ AC_TYPE_UINT32_T
AC_FUNC_ERROR_AT_LINE
AC_CHECK_FUNCS([\
__fpending \
open_memstream \
posix_fadvise \
])
AC_CHECK_DECL([strndupa])
AC_CHECK_FUNCS([fpclassify], [],
[AC_CHECK_LIB([m], [fpclassify], [MATH_LIBS="-lm"])]
[AC_CHECK_LIB([m], [__fpclassify], [MATH_LIBS="-lm"])]
)
AC_SUBST([MATH_LIBS])
AS_IF([test "x$ac_cv_func_open_memstream" = "xyes" && test "x$ac_cv_have_decl_strndupa" == "xyes"], [
build_mustach=yes
AC_DEFINE([BUILD_MUSTACH], [1], [build mustach support])
], [
build_mustach=no
])
AM_CONDITIONAL([ENABLE_MUSTACH], [test "x$build_mustach" = xyes])
AC_MSG_CHECKING([if the compiler supports __builtin_expect])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[

1
contrib/.gitignore vendored
View file

@ -1,2 +1 @@
/dhcpd-pools.cgi
/nagios.conf

View file

@ -1,5 +1,5 @@
contribdir = $(datadir)/dhcpd-pools/
PATHFILES += contrib/dhcpd-pools.cgi contrib/nagios.conf
dist_contrib_SCRIPTS = contrib/dhcpd-pools.cgi contrib/snmptest.pl
PATHFILES += contrib/nagios.conf
dist_contrib_SCRIPTS = contrib/snmptest.pl
dist_contrib_DATA = contrib/nagios.conf
EXTRA_DIST += contrib/munin_plugins

36
contrib/PKGBUILD Normal file
View file

@ -0,0 +1,36 @@
# Archlinux package file. Just download this file, and
# makepkg PKGBUILD
# pacman -U ./dhcpd-pools*.pkg.tar.xz
pkgname=dhcpd-pools
pkgver=0
pkgrel=1
pkgdesc="ISC dhcpd lease status utility"
arch=('i686' 'x86_64')
url=https://dhcpd-pools.sourceforge.net/
license=('BSD')
depends=('pacman')
makedepends=('uthash' 'git')
source=("$pkgname"::'git://git.code.sf.net/p/dhcpd-pools/code')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/$pkgname"
# Use the tag of the last commit
git describe --long | sed -E 's/([^-]*-g)/r\1/;s/-/./g'
}
build() {
cd "$srcdir/$pkgname"
./bootstrap
./configure \
--prefix=/usr \
--bindir=/usr/bin
make
}
package() {
cd "$srcdir/$pkgname"
make PREFIX=/ DESTDIR="$pkgdir" install
install -D -m644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/COPYING"
}

View file

@ -1,34 +0,0 @@
#!@SHELL@
#
# Simple CGI for dhcpd-pools.
echo Content-type: text/html
echo
# To make lease table more fancy use CSS definition something
# like this in your style.css file.
#
# TABLE.dhcpd-pools {
# border-style : groove;
# margin-left : 2px;
# foo : bar;
# }
#
# http://www.w3.org/TR/REC-CSS2/tables.html
#
# And uncomment this line.
#
#echo <link type="text/css" rel="stylesheet" href="/style.css" />
echo "<html>"
echo "<body>"
echo "<p>This was situation at "
date
echo "</p>"
@bindir@/dhcpd-pools --format html
echo "</body>"
echo "</html>"
# EOF

View file

@ -1,5 +1,4 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
mQINBFLH/jcBEADNgkgZAr7b/qvHzNkme8eSplDA8UHhcCFQmBnQ8HYFEYBi1Y5a
GhICcuisRSuZIPLtqRF8ntoOXsOHOUxnn5hVR62HxMLgOC1PQMw8TzREobbkAxMp
@ -12,41 +11,101 @@ v8Bj+uLXc4JT9kTB5E8DT2ZR+61E4eT/zk4rpZ5j6tTktLNaSG58VYc+oQlPkPsB
ntraDsORpa5cK9uPUbHIHN1qd4gi35O4UDSqS023XnStQqsUD4vlzICedPDypn28
h9q2nlNQHSDjIRnZFD+z9IHfVoBNTfm5/UH7NKBAvSS6rP5zsgi2fittt5AFdbmQ
VBOtpYp5vbcdSt8gNdJRy8FRaiQ/2n74xF1Zso/PGni1xRmseS+qBGI95QARAQAB
tDtTYW1pIEtlcm9sYSAoaHR0cDovL3d3dy5pa2kuZmkva2Vyb2xhc2EvKSA8a2Vy
b2xhc2FAaWtpLmZpPokCPwQTAQIAKQUCUsf+NwIbAwUJCWYBgAcLCQgHAwIBBhUI
AgkKCwQWAgMBAh4BAheAAAoJEKlVMkX96bc5aBwP/3XE1ZW3pp6B337vW5VfPY8v
+8h2JMdL/PfCLqDHbQm6fYgtT+EFbVE3JotXcocSqvl3xjA2LERROoN9a+jdaS9O
+WDWdIxVjnpMheb502ZnTbwFuh1OVasvqT7x4e9Tmq31S/0VFjTFLm8M+anuoUsn
9lfy5jeGnULMT0G737uySmm8M7hP5lSXHhFaiQi2R95wo8titvZ9ckGFJH3/u5qV
8aU34yzIw3MnKG52FeieYjSVfEaso9FrO8thMFIJclHSGzd5fw9CbPggFzMR0zHc
wJl+AEshAIG13+P88wcJ4sqfZGltdjm0vSgcmWgkmrZyDhvyA4Hnb2Rc3faqh3VC
/qU7p82yhoJ9M12xz4PIXQbodPDu/q8Ckzt8zh6h8ROUkqqZ90M2Yc3QoX82qOzR
tMokbhhwtYcgyAZHw0CLvJuJvAME41zjH1Wq9wY+gXHewTppi9Yqbd8E1LJaCvr7
pMhKr9f08lBoUD5G/M54HGMKW+1R0yvxR9C2lR8P5JfVfTmD9E/g8WbmzZuy1dm1
sL3fzjmnc3yNNt9MgfJgHQu2W15myNAzK/sEXGjuXJSqn/dpCoxiqQooEc2qokN/
wQp5g70We305+BZB1fQcjE7wBmF4OEtEcI3p4lSrffyxcsqFFds0ikDU024lA46D
V1nSGsKLk7fme3itszWmuQINBFLH/jcBEADGsDuJyhEGExcInkb4Zy8HlSNaT0nF
xpQK+tI5RlqyC11TnxdUDCQwPPRh/hdNs7RDQ6lHhmXydD04+Sjjn0nkQCxd8TlB
TwOU6BV4vPF7BonskTMHb6mXxOo+6f7+J5q4beQ7XzRSoFqLZ0kiump7B4m6L4WS
qZmcfi8f6EOQZHK1HsTB2jE+cwaPm7vNeNaKXYM6hHojZ7XnDavv4vMxfLRGGx5e
6wNcZexD4t4pkMwmA+A576t5CnIm8JVB2HLj2YZN6DfIfYQ9EcMYSYVLg/EuivPa
MZIoIa9ki5TbeQDANluJqAG+i+CSoIfJX1V1p0WoeSEKJnGBhVFmajU+nek1lCqe
M/VXQF4dWbFCQm8/eKl1M9PY77dwT90xRZDeigM6o6CoB+6rfePAnwsmtA21LyQ9
WMTCH9qii9SvlWkfCvLK3HnC/2d1ctwsF8yoc6KF+Qwj7RV23/iHYqjxB8OcOAyH
uv+k0sD9o0MLlzAExOftLPkwyWS8ePs7rJVLSA42N3diUYx5TO3NzmU8ifn4hGxb
F9J/sIYQUfCxH9V+DBe2vhVSZ/bQKpVUZTE8KxINL32JvTR3HbEwHKIe0xIFnDOM
GrWP7icPEsaSKj/0vEq/Is/R2nJWfD0Vzs7vil9zYU16vHQtZrv/5SzavzDRFGxL
m7/jDfrzMuNRdQARAQABiQIlBBgBAgAPBQJSx/43AhsMBQkJZgGAAAoJEKlVMkX9
6bc5cYEQAI8xVRdoza/MY9KFJCRiobii4GjxAJqIXXvbY8mM7rvmiLnzfr5msLzS
op7Epse6tkI8QvYXbY+EjXke27J8rM/zqXyqdKJfcqKVzq6fIQyVVsz9o0hwvuSj
kcSgCV2b8XHKbNygSnNh2VJ5YY/zL2x5tsySa3tLukh46ydKWRQqOSMIxMT0TnCO
iTMr5INwGnX68rB0kEuCSUdkzDuyulW2T0oN7Yx4ASgrJixwSu/UNMO/fXvkG0NY
IWeXQcnn0C8zQv/PAfzJ9O+24Md4m6tzVuDpblSRB6E8xQhusysRc4BEHB/G3Ege
3JR/tumT6solJD7pfFDYkC9rAKhTKK9h1b2VpEGxN9o8qwwjtNljLakEYXuWNpCm
ZxKAR4Agg3UY8CGmgsTKyjsfB9iO2+LXCS9uQMAtIHbnr++mPASBEKD6rP8QIyf1
2fbI9JRNGWcXQVZBGXWmu4UaKOrXBTVzooj2yG7kZmKO0FoIaCqqTUs2/KhnFj2E
Fvym2j1OMrYxOM/pT6w3cv3CwGb1ILOX0qrTQiEpOExSMa21Mi4678jXt6F6NPWG
/lwlgE1WM9i9jIcua+NU5ZJiqQ/rjuSRMB/WFrQy66/jb9wWNp/G6DXrANgdgoC9
Dq5oviB+dqSXlU5b0atG4ru506mXCHKmOC+wu0oRlGQ/X6iuuDfS
=U+eW
tB1TYW1pIEtlcm9sYSA8a2Vyb2xhc2FAaWtpLmZpPokCcwQTAQgAXQIbAwULCQgH
AgYVCAkKCwIEFgIDAQIeAQIXgAIZARsYaHR0cDovL2h0dHAta2V5cy5nbnVwZy5u
ZXQWIQSO05bjfjjUcaAFMNOpVTJF/em3OQUCWb42mgUJGcI7YwAKCRCpVTJF/em3
OWNBD/4/N0OO6cA3bmEAum5qmHdcJVcUor9ClY3oY2QWdTyDCmSJLcTZUNsTrYYA
hY5vQsDxG6ZaKiITvhwp9y4PdJmnqqzRfnqnXusSVEsqG3vGHIVlpQj8Vgurr68d
1x2buHGRvRrjBMWR/Ro1TUeNOmM4HStcvjXRTWlHk9VXi9nk+uMQY9n1lXYNChda
0usj7q5QXXFXbOukKrvEZzt4I1tGbSEv7bBIghr5fMAJg8ZqAMDwfqsUKSM38HF4
leCUgMZS7XuXuEb35ImjR1VYYCb+L2Q/PFqDOEGQpUwyLOzXcU9TaIDjMhNQY19y
DTUjW1YdQtf+3XmQFa4X1Od0jP1PiVJhw1LNCQLOENs+SRqT9s0W8+nP3qjso/LR
T3vR3FcGSw6KrESMFvmwY7EEYGvOpEgaIv8sIJl7un4BoWHYq/2D6jDHK/YmbpgG
J2FIvZZ4vVYixqgrqCh54USpwTaKd4KQpdm4zZMJ2yIznR6+gXxTi2TyUwKFV67y
RY6o5n3jusWuRejB1BI2eXRbFSeZn6IxAG8QLlLHu1R/XBB1dYDkbtYZ5XuAJRTH
qjCL+s/4rjJIUj02dmmtiyObN3bs/48DTQsDqgCYbA2wmbBjT9lPmRWfncBSlqbx
XSRwyXnDql+UIi6wphBdESn5TNVJjWxYQ16ZRYoZlz4tV2bPl4kCHAQQAQoABgUC
WCOB1QAKCRCB/dUuZfDuelcKD/4iggO8sgYYmTf63y2LJhG7e2d3K/cbQ04Pn/iF
b6zBa5kCsLAWHJmWBPlPkQB3HjZ+j1OSs4sHvwuotuVde2cbtzEvuphQRamFSU83
lakXwXrk00IU7oVEz1Yo9c7IB6pOY0uDgQMIp/Vitm9pomZXAV3S1bYciYuvXdJC
6SaUbyrHzkVgxEV7TSK2XUgMFGnBCIUhqxNA+chkGg6KS715XH8MJyb1Izinsjux
Q07+tquoiYqRhSntTc+bJ83OpSB8bPlqP1FZdc+ypZjq8OEpFIZK8QtK+849vzYw
vORq19mwFAY9y6XZip7YZzSGzn7Q4v3XfVJlIwGrkHSnUkqOmQXGdoSHAiwX3WhU
nPtpYFZQoFFQjm0SsgdPWbqJmmLj2MjHUFbKzl9PVa0INnwp6RxfzNZjU6OxphoI
ocw+2hmXv/lHzb+cwFf8Nae0WOJkCoGwxk9mYA0omhuKJ/WWVvauu+uaswBkeX6O
1Yf1jSrWgK5u+jbDcmZj0kFL0zdB/pBxshngxCA3efPd1e2dJGcPlaoqkwZAtEmG
hwWDj9Gk5IhSX1/Wpv+ke2wprUPzwv7Z5loXroLub2R29FWyHzymwlnts5hSg7kR
1PzxD3iOHFgmnWcBCchf8UWmAjrutZQJZWLTDkzlC6Vj8rkJcgdb0v14zvYVJTWs
Q/hMDYkCHAQSAQoABgUCWCN/ZwAKCRCRAl9JYWN/KLmND/9k8ydscqaMW86NswOC
drJDXuOTDvJJlnLYhgO1+jKQizbHQqnszIVk7KvXY2/K++TdTNdG/+/LosvtIRKb
2DEvV2hPZhc3UxZ2Gnx9ocqjSCfmd9er9EY34WGLtr57eQnu93CJGe10F3qg4rr3
8zsgQcLXomvKnB2J5oRWBla01DXZhum1uIbehrqDmBUz9YxAIz9adY0AjDyLNvAB
IghkjobLHWhouQaTV1IT6Koixdrj6eKekjRojWVZ7Po5dcUe525NlA1yBJhI9VDF
TLy6DHEwmJJuAQqDpyRILzSDsyQ0B+wBgpGks5reCDZlwAjogLy0O6nV2qYKfVXK
ziHeXPvzLPEfSmkA0ZutLXnJBLNfod4zELLJrPJA27dDdQO4yImoAjjTklyBpHXy
Fp3r5RlDq5yA9VpNkC58KJQZoiplkUNBaQTjYgcYX4LDaU4bEq++CUUEnisIyqPO
KqJPJAvmlm1d2vOMxhzcjxt3xBAvDZ8ibRIXlV296Y56SEBe5UZhyUqpAQBa0zsp
oQm9MdkqoC+IDBTRVnbGSxsw0GiQRpAJyNOlkTzP6z6ySmRIQ1hH1TqXx7TChPqP
tcLHLOnRTY9/v5Kt8APa+qgn/0UVgGcetkarqXNdtq+zD1x9C0DFNURBl0uH/E1E
Dtyx4xI6xCY3jzv0Cb1y9Afrc7Q7U2FtaSBLZXJvbGEgKGh0dHA6Ly93d3cuaWtp
LmZpL2tlcm9sYXNhLykgPGtlcm9sYXNhQGlraS5maT6JAlYEEwECAEACGwMHCwkI
BwMCAQYVCAIJCgsEFgIDAQIeAQIXgBYhBI7TluN+ONRxoAUw06lVMkX96bc5BQJZ
vjaaBQkZwjtjAAoJEKlVMkX96bc58KYP/jvpHWmoKKFzqClLdDkN8tBo30GgHGoh
WKHbgW859mi/ZcYzTxlx6Dm88QwV5DRulgqAHvLTippncR3LTpL3Ys86ZDoIskF9
BnWOm/bC+Czl9mDL6BNfFEWWnfeGFsCaMq/Jx8nj8i2o0ezhbTjCeGeng4quWK1D
T6G8Kvnk7Dc+i0n20LUQf2WRCLrtJEl/PMElc+11X/jLm9ypjE/jr24xiNsZck45
4rdMsdkZqgbSHWNIHyxS66mWmD1vbHp3kq0ic09ISCx/Xc7OQpv7V0hN+lxE+AvA
3Mjp2i7A3ntwUbPwmZkdiWUrBqU4CYee0S4fbgroUjNQ/JhGZmCku5YbcyAg4KrP
quXEftY0HP3qQMMElcwna5ljDQdC9NGuSWkH0OKZsuXlgtIz583wjNTKupzii+jo
AJcNnbdRR4i/U7cI+/ySluTp+Az/odmTNzssGnlsXOSGYWk4o6ruKvU4HzUauMEO
XPrTvI7IlH/GIHvwrOcXAyAU90M0qppC4YjXK8oCawzTnbQVQsbedwoNaEPaD4Bz
N4ka9PtvgKnBzODvOeDsTz1O6vTomttW2C6nficc/PXQvxDkZ3NeJw3eGiiAQxeA
w2Ps3+oIasyQZZVLlvu8dfE2BsPArggPLNgd6bLk3yk/gQGR0D+/TyHuCgPM1nZt
mBG3utrXfMz3iQIcBBABCgAGBQJYI4HVAAoJEIH91S5l8O56YhYQAIfxcRP31w+6
htYZO5dGS1zF1CReY8VO/AyBa59YJHAlFSbOhqHQY1SAYD+H1IZhv/JCvQScZhyT
giI3KPP1RAPUa1xGZrf4hwl7Yu8ZpFn1Y0Gxd4bj2i9HWJcd1A+ci4kc+dU4rPEB
ac2U06vcIyuyCSjuK2RdYCyd7pQRkoUtZxWen6sxi1khsw3Qucfbr5QZyh/roA4i
hTb3VlFFIiCRcZOAqSYml9a+kbDxpgswbdCE3EMHVYBWtFwWImZOhnsun148H7EA
+b+hAcbkoNpXJOfC8q/EM0qm6C1GhryXe1voLxfeMdKKjXM78dc0z3L/Vz0E+stD
qrT7CG1jLSk/rIjSvRhbnEX/ZTKa+19ytht0B2zxkokjevvzw6cXSM5JjG8Q9k7R
PcPOTS0t7MSwRqCEFvhvswH3JYy0SH0U2nKbPmkY1Awh6BZNyGpf3dxHV648RVZv
lrXUbXv1azD8U+llaMkVx0PTbej0RcRHQM6B5zJ0qu1MC64V/v2uUK3MNl38JdFa
wkB494uf024FRIfJlQ8+WYrsGlHbUBZZsWzsyrPaeaqL0Xcy+hOc7wu7cZPxkqL8
71O3jbq2dFkBWA4ANsiRdJTh14qoen4YVdc9gjq6HsuFyu0gauDktLaLUHVCX27e
kWThHNxeNoGkcKKHoQdHrN8sII8C1q6fiQIcBBIBCgAGBQJYI39nAAoJEJECX0lh
Y38oIbEP/165gMnaD+g7cfGsHCHQk9/ZrE+4iXfZSwxlhaJ4kK88Ad/tPvoiOxmS
NaUIfH/koGBQNeE/OjjIkPiGlsldg9//4mGmSglM4jLeQBG0QuTLo30aNCl9xU6q
rv9PV/ROfjRUF5NxCAiDdA24uBZ8CftdK5sglD6fazeINQyNk5Wm8e7Jk9PRzIuK
jnZRyaGJl3egx5smWnCZZ8QfjsYXDzbp1uDavmF7Qczp+xbzBhdh6VdSZ0VwvnPr
kN3CzGiR3AuG982R41UGZQ3a+3d38QnmX8cdT1yCqJLrSh4+AJbuGrndOqxBhTN0
VQBIGHteZ6ezxDHs4kVBwfSc3XOzNimJKFVxWCJDXZQojKawu7PaDPYGxU9OWAjs
OWtJFTGqeEiBDQbnLwncT5l/I1O1zv9MIFhQ4MgJeRbvG/QjuLrP6RoIMGZLkX6K
o35dZ6gO/XAdhJmOhfon6Q5/RPdB11e/UkM58xZMbQLGJ3Gm9vjz039vwMabMjXf
28UE3xKzdzDg8Fb3ykNtIQSFNr/cf5YBZ7KMtfJ6ugExmJQQdWxZLQpHoNNCmknt
OHOajlB628N3J0PKlwPjjt5KveBO2ur/yAly6SSv2Oi/astGscgrJtIyPFKMmKar
gPzEnPv4DfLbHnskHkyzVBrQE16Pmcfx4fAe2LeDIO8KJMqSxKOouQINBFLH/jcB
EADGsDuJyhEGExcInkb4Zy8HlSNaT0nFxpQK+tI5RlqyC11TnxdUDCQwPPRh/hdN
s7RDQ6lHhmXydD04+Sjjn0nkQCxd8TlBTwOU6BV4vPF7BonskTMHb6mXxOo+6f7+
J5q4beQ7XzRSoFqLZ0kiump7B4m6L4WSqZmcfi8f6EOQZHK1HsTB2jE+cwaPm7vN
eNaKXYM6hHojZ7XnDavv4vMxfLRGGx5e6wNcZexD4t4pkMwmA+A576t5CnIm8JVB
2HLj2YZN6DfIfYQ9EcMYSYVLg/EuivPaMZIoIa9ki5TbeQDANluJqAG+i+CSoIfJ
X1V1p0WoeSEKJnGBhVFmajU+nek1lCqeM/VXQF4dWbFCQm8/eKl1M9PY77dwT90x
RZDeigM6o6CoB+6rfePAnwsmtA21LyQ9WMTCH9qii9SvlWkfCvLK3HnC/2d1ctws
F8yoc6KF+Qwj7RV23/iHYqjxB8OcOAyHuv+k0sD9o0MLlzAExOftLPkwyWS8ePs7
rJVLSA42N3diUYx5TO3NzmU8ifn4hGxbF9J/sIYQUfCxH9V+DBe2vhVSZ/bQKpVU
ZTE8KxINL32JvTR3HbEwHKIe0xIFnDOMGrWP7icPEsaSKj/0vEq/Is/R2nJWfD0V
zs7vil9zYU16vHQtZrv/5SzavzDRFGxLm7/jDfrzMuNRdQARAQABiQIlBBgBAgAP
BQJSx/43AhsMBQkJZgGAAAoJEKlVMkX96bc5cYEQAI8xVRdoza/MY9KFJCRiobii
4GjxAJqIXXvbY8mM7rvmiLnzfr5msLzSop7Epse6tkI8QvYXbY+EjXke27J8rM/z
qXyqdKJfcqKVzq6fIQyVVsz9o0hwvuSjkcSgCV2b8XHKbNygSnNh2VJ5YY/zL2x5
tsySa3tLukh46ydKWRQqOSMIxMT0TnCOiTMr5INwGnX68rB0kEuCSUdkzDuyulW2
T0oN7Yx4ASgrJixwSu/UNMO/fXvkG0NYIWeXQcnn0C8zQv/PAfzJ9O+24Md4m6tz
VuDpblSRB6E8xQhusysRc4BEHB/G3Ege3JR/tumT6solJD7pfFDYkC9rAKhTKK9h
1b2VpEGxN9o8qwwjtNljLakEYXuWNpCmZxKAR4Agg3UY8CGmgsTKyjsfB9iO2+LX
CS9uQMAtIHbnr++mPASBEKD6rP8QIyf12fbI9JRNGWcXQVZBGXWmu4UaKOrXBTVz
ooj2yG7kZmKO0FoIaCqqTUs2/KhnFj2EFvym2j1OMrYxOM/pT6w3cv3CwGb1ILOX
0qrTQiEpOExSMa21Mi4678jXt6F6NPWG/lwlgE1WM9i9jIcua+NU5ZJiqQ/rjuSR
MB/WFrQy66/jb9wWNp/G6DXrANgdgoC9Dq5oviB+dqSXlU5b0atG4ru506mXCHKm
OC+wu0oRlGQ/X6iuuDfS
=fVwo
-----END PGP PUBLIC KEY BLOCK-----

4
contrib/rpm.spec Normal file
View file

@ -0,0 +1,4 @@
Klaus Slott made a package that works for opensuse, and is
a good starting point for whom ever happens to need an rpm.
https://build.opensuse.org/package/show/home:Mr_Manor/dhcpd-pools

View file

@ -23,9 +23,10 @@
# you set $dbg to 1 then output will be generated in /tmp.
use strict;
use NetSNMP::OID;
# Version info:
my $SNMPver = "snmp1.0";
my $SNMPver = "snmp1.1";
my $DHCPver = "dhcp1.0";
my $VERSION = "$SNMPver/$DHCPver";
#
@ -193,7 +194,7 @@ sub ParseDataFile () {
}
close IN;
if ($dbg) {
foreach (sort @validoidlist) { print DBG "ValidOID: $_\n"; }
foreach (sort Oidcmp @validoidlist) { print DBG "ValidOID: $_\n"; }
}
if ($dbg) {
@ -370,7 +371,7 @@ sub GetData ($) {
@userquery = split (/\./, $userqueryoid);
my $found = 0;
foreach (sort @validoidlist) {
foreach (sort Oidcmp @validoidlist) {
$next = $_;
print DBG "Comparing $userqueryoid vs. $_\n" if $dbg;
@validoid = split (/\./, $_);
@ -432,6 +433,12 @@ sub Pong {
$line = 0;
}
sub Oidcmp {
my $oida = new NetSNMP::OID($a);
my $oidb = new NetSNMP::OID($b);
snmp_oid_compare($oida, $oidb);
}
################################## START ##################################
#
# Main

4
contrib/zabbix.txt Normal file
View file

@ -0,0 +1,4 @@
Zabbix 5 template, and instructions how to use it, can be found from
Mathieu's repository.
https://github.com/mmorier86/dhcpd-pools-zabbix-template

View file

@ -1,4 +1,4 @@
# Doxyfile 1.8.10
# Doxyfile 1.8.13
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@ -51,7 +51,7 @@ PROJECT_BRIEF = "ISC dhcpd lease usage analyser"
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
@ -118,7 +118,7 @@ REPEAT_BRIEF = YES
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
@ -161,7 +161,7 @@ STRIP_FROM_PATH = src
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@ -228,13 +228,13 @@ TAB_SIZE = 4
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
ALIASES =
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@ -242,7 +242,7 @@ TCL_SUBST =
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_FOR_C = YES
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
@ -281,7 +281,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
EXTENSION_MAPPING =
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
@ -293,6 +293,15 @@ EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings.
# Minimum value: 0, maximum value: 99, default value: 0.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
TOC_INCLUDE_HEADINGS = 0
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
@ -512,7 +521,7 @@ CASE_SENSE_NAMES = YES
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
HIDE_SCOPE_NAMES = YES
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
@ -629,7 +638,7 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS =
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@ -671,7 +680,7 @@ SHOW_NAMESPACES = YES
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
@ -684,7 +693,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@ -694,7 +703,7 @@ LAYOUT_FILE =
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@ -739,6 +748,12 @@ WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
@ -753,7 +768,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard
# error (stderr).
WARN_LOGFILE =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@ -787,8 +802,8 @@ INPUT_ENCODING = UTF-8
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
# *.vhdl, *.ucf, *.qsf, *.as and *.js.
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.c \
*.h \
@ -824,7 +839,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@ -835,20 +850,20 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
@ -861,7 +876,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@ -877,8 +892,12 @@ IMAGE_PATH =
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
@ -886,8 +905,12 @@ INPUT_FILTER =
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS =
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
@ -910,7 +933,7 @@ FILTER_SOURCE_PATTERNS = *.c \
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
@ -1022,7 +1045,7 @@ COLS_IN_ALPHA_INDEX = 5
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
@ -1066,7 +1089,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@ -1076,7 +1099,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@ -1088,7 +1111,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
@ -1101,7 +1124,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@ -1111,7 +1134,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@ -1240,7 +1263,7 @@ GENERATE_HTMLHELP = NO
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
@ -1248,7 +1271,7 @@ CHM_FILE =
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
@ -1261,7 +1284,7 @@ GENERATE_CHI = NO
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
@ -1292,7 +1315,7 @@ GENERATE_QHP = NO
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
@ -1317,7 +1340,7 @@ QHP_VIRTUAL_FOLDER = doc
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
@ -1325,21 +1348,21 @@ QHP_CUST_FILTER_NAME =
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
@ -1472,7 +1495,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
@ -1480,7 +1503,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
@ -1540,7 +1563,7 @@ EXTERNAL_SEARCH = NO
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
@ -1556,7 +1579,7 @@ SEARCHDATA_FILE = searchdata.xml
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
@ -1566,7 +1589,7 @@ EXTERNAL_SEARCH_ID =
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
@ -1630,7 +1653,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@ -1646,7 +1669,7 @@ EXTRA_PACKAGES =
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
@ -1657,7 +1680,7 @@ LATEX_HEADER =
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
@ -1668,7 +1691,7 @@ LATEX_FOOTER =
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
@ -1676,7 +1699,7 @@ LATEX_EXTRA_STYLESHEET =
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@ -1729,6 +1752,14 @@ LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
@ -1776,14 +1807,14 @@ RTF_HYPERLINKS = NO
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
@ -1828,7 +1859,7 @@ MAN_EXTENSION = .3
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
@ -1941,7 +1972,7 @@ PERLMOD_PRETTY = YES
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
@ -1982,7 +2013,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@ -1990,7 +2021,7 @@ INCLUDE_PATH =
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
@ -2000,7 +2031,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@ -2009,7 +2040,7 @@ PREDEFINED =
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
@ -2038,13 +2069,13 @@ SKIP_FUNCTION_MACROS = YES
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
@ -2084,7 +2115,7 @@ PERL_PATH = /usr/bin/perl
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
CLASS_DIAGRAMS = NO
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see:
@ -2093,14 +2124,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
@ -2149,7 +2180,7 @@ DOT_FONTSIZE = 10
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
@ -2293,26 +2324,26 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
@ -2320,12 +2351,17 @@ DIAFILE_DIRS =
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
PLANTUML_JAR_PATH =
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
# configuration file for plantuml.
PLANTUML_CFG_FILE =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes

204
lib/.gitignore vendored
View file

@ -1,49 +1,51 @@
/*.lo
/*.o
/.deps/
/.gitignore~
/.libs/
/Makefile
/Makefile.am
/Makefile.in
/_Exit.c
/alloca.h
/alloca.in.h
/arg-nonnull.h
/arpa/
/arpa_inet.c
/arpa_inet.in.h
/atexit.c
/c++defs.h
/assert.in.h
/attribute.h
/basename-lgpl.c
/basename-lgpl.h
/c32is-impl.h
/c32isprint.c
/calloc.c
/c-ctype.c
/c-ctype.h
/c-strcase.h
/c-strcasecmp.c
/c-strcaseeq.h
/c-strncasecmp.c
/calloc.c
/charset.alias
/close-stream.c
/close-stream.h
/c++defs.h
/cdefs.h
/cloexec.c
/cloexec.h
/close.c
/closeout.c
/closeout.h
/config.charset
/configmake.h
/dosname.h
/close-stream.c
/close-stream.h
/c-strcasecmp.c
/c-strcaseeq.h
/c-strcase.h
/c-strncasecmp.c
/dup2.c
/errno.in.h
/error.c
/error.h
/error.in.h
/exitfail.c
/exitfail.h
/fclose.c
/fcntl.c
/fcntl.h
/fcntl.in.h
/fd-hook.c
/fd-hook.h
/fdopen.c
/fflush.c
/float+.h
/filename.h
/flexmember.h
/float.c
/float+.h
/float.h
/float.in.h
/fopen.c
/fpending.c
@ -57,112 +59,204 @@
/fstat.c
/ftell.c
/ftello.c
/getopt.c
/getopt.in.h
/getdtablesize.c
/getlocalename_l-unsafe.c
/getlocalename_l-unsafe.h
/getopt1.c
/getopt.c
/getopt-cdefs.in.h
/getopt-core.h
/getopt-ext.h
/getopt.in.h
/getopt_int.h
/getopt-pfx-core.h
/getopt-pfx-ext.h
/getprogname.c
/getprogname.h
/gettext.h
/gettimeofday.c
/hard-locale.c
/hard-locale.h
/ialloc.c
/ialloc.h
/idx.h
/inet_pton.c
/intprops.h
/intprops-internal.h
/inttypes.h
/inttypes.in.h
/isnan.c
/isnand.c
/isnanf.c
/isnanl.c
/itold.c
/langinfo.h
/langinfo.in.h
/lc-charset-dispatch.c
/lc-charset-dispatch.h
/libc-config.h
/libdhcpd_pools.la
/libdhcpd_pools_la-arpa_inet.lo
/libdhcpd_pools_la-basename-lgpl.lo
/libdhcpd_pools_la-c32isprint.lo
/libdhcpd_pools_la-c-ctype.lo
/libdhcpd_pools_la-cloexec.lo
/libdhcpd_pools_la-closeout.lo
/libdhcpd_pools_la-close-stream.lo
/libdhcpd_pools_la-c-strcasecmp.lo
/libdhcpd_pools_la-exitfail.lo
/libdhcpd_pools_la-fclose.lo
/libdhcpd_pools_la-fcntl.lo
/libdhcpd_pools_la-fd-hook.lo
/libdhcpd_pools_la-fflush.lo
/libdhcpd_pools_la-float.lo
/libdhcpd_pools_la-fopen.lo
/libdhcpd_pools_la-fpurge.lo
/libdhcpd_pools_la-freading.lo
/libdhcpd_pools_la-fseek.lo
/libdhcpd_pools_la-fseeko.lo
/libdhcpd_pools_la-getprogname.lo
/libdhcpd_pools_la-hard-locale.lo
/libdhcpd_pools_la-ialloc.lo
/libdhcpd_pools_la-localcharset.lo
/libdhcpd_pools_la-malloca.lo
/libdhcpd_pools_la-math.lo
/libdhcpd_pools_la-mbrtoc32.lo
/libdhcpd_pools_la-mbrtowc.lo
/libdhcpd_pools_la-mbszero.lo
/libdhcpd_pools_la-mktime.lo
/libdhcpd_pools_la-nstrftime.lo
/libdhcpd_pools_la-progname.lo
/libdhcpd_pools_la-quotearg.lo
/libdhcpd_pools_la-reallocarray.lo
/libdhcpd_pools_la-realloc.lo
/libdhcpd_pools_la-setlocale_null.lo
/libdhcpd_pools_la-setlocale_null-unlocked.lo
/libdhcpd_pools_la-stat-time.lo
/libdhcpd_pools_la-stdlib.lo
/libdhcpd_pools_la-sys_socket.lo
/libdhcpd_pools_la-timegm.lo
/libdhcpd_pools_la-time_rz.lo
/libdhcpd_pools_la-unistd.lo
/libdhcpd_pools_la-wctype-h.lo
/libdhcpd_pools_la-xalloc-die.lo
/libdhcpd_pools_la-xmalloc.lo
/.libs/
/limits.h
/limits.in.h
/localcharset.c
/localcharset.h
/locale.h
/locale.in.h
/localename.h
/localename-unsafe.c
/lseek.c
/malloc.c
/Makefile.am
/malloca.c
/malloca.h
/malloca.valgrind
/malloc.c
/math.c
/math.h
/math.in.h
/mbrtoc32.c
/mbrtowc.c
/mbrtowc-impl.h
/mbrtowc-impl-utf8.h
/mbsinit.c
/mbszero.c
/mbtowc-lock.c
/mbtowc-lock.h
/memchr.c
/memchr.valgrind
/memcpy.c
/mktime-internal.h
/minmax.h
/mktime.c
/mktime-internal.h
/msvc-inval.c
/msvc-inval.h
/msvc-nothrow.c
/msvc-nothrow.h
/netinet_in.in.h
/_Noreturn.h
/nstrftime.c
/open.c
/pathmax.h
/progname.c
/progname.h
/quote.h
/quotearg.c
/quotearg.h
/quote.h
/reallocarray.c
/realloc.c
/ref-add.sed
/ref-add.sin
/ref-del.sed
/ref-del.sin
/setenv.c
/setlocale-lock.c
/setlocale_null.c
/setlocale_null.h
/setlocale_null-unlocked.c
/stat.c
/stdalign.h
/stdalign.in.h
/stdarg.in.h
/stdbool.in.h
/stat-time.c
/stat-time.h
/stat-w32.c
/stat-w32.h
/stdckdint.h
/stdckdint.in.h
/stddef.h
/stddef.in.h
/stdint.in.h
/stdio-impl.h
/stdio.c
/stdio.h
/stdio-impl.h
/stdio.in.h
/stdio-read.c
/stdio-write.c
/stdlib.c
/stdlib.h
/stdlib.in.h
/stpncpy.c
/str-two-way.h
/strdup.c
/streq.h
/strerror.c
/strerror-override.c
/strerror-override.h
/strerror.c
/strftime.c
/strftime.h
/string.h
/string.in.h
/strstr.c
/strtod.c
/str-two-way.h
/sys/
/sys_socket.c
/sys_socket.in.h
/sys_stat.in.h
/sys_time.in.h
/sys_types.in.h
/sys_uio.in.h
/time-internal.h
/timegm.c
/time.h
/time.in.h
/time-internal.h
/time_r.c
/time_rz.c
/timegm.c
/tzset.c
/uchar.h
/uchar.in.h
/unictype/
/unictype/bitmap.h
/unictype/ctype_print.c
/unictype/ctype_print.h
/unictype/.gitignore
/unictype.h
/unictype.in.h
/unistd.c
/unistd.h
/unistd.in.h
/unitypes.h
/unitypes.in.h
/unsetenv.c
/unused-parameter.h
/verify.h
/warn-on-use.h
/wchar.h
/wchar.in.h
/wctype-h.c
/wctype.h
/wctype-h.c
/wctype.in.h
/windows-initguard.h
/xalloc-die.c
/xalloc-oversized.h
/xalloc.h
/xalloc-oversized.h
/xmalloc.c
/xprintf.c
/xprintf.h
/xstrtod.c
/xstrtod.h

View file

@ -1,9 +1,28 @@
.TH DHCPD-POOLS "1" "2015-09-04" "@VERSION@" "User Commands"
'\" t
.TH DHCPD-POOLS "1" "2024-08-09" "@VERSION@" "User Commands"
.SH NAME
dhcpd-pools \- ISC dhcpd pools usage analysis
.SH SYNOPSIS
.B dhcpd-pools
[options]
.SY dhcpd-pools
.OP \-\-config file
.OP \-\-leases file
.OP \-\-sort nimcptTe
.OP \-\-reverse
.OP \-\-format tHcxXjJ
.OP \-\-mustach template
.OP \-\-output file
.OP \-\-limit nr
.OP \-\-color when
.OP \-\-warning percent
.OP \-\-critical percent
.OP \-\-warn\-count number
.OP \-\-crit\-count number
.OP \-\-snet\-alarms
.OP \-\-minsize size
.OP \-\-perfdata
.OP \-\-version
.OP \-\-help
.YS
.SH DESCRIPTION
The program analyses ISC dhcpd shared network and pool usage and outputs the
results in a format selected by user.
@ -64,14 +83,14 @@ field is default sort key.
\fB\-r\fR, \fB\-\-reverse\fR
Sort results in reverse order.
.TP
\fB\-f\fR, \fB\-\-format\fR=\fI[thHcxXjJ]\fR
\fB\-f\fR, \fB\-\-format\fR=\fI[tHcxXjJ]\fR
Output format.
Text
.RI ( t ).
Full-html
.RI ( H )
page output.
The
page output. In html page critical and warning thresholds can be visualized
with \-\-color=always option. The
.RI ( c )
stands for comma-separated values. Output format xml
.RI ( x )
@ -86,6 +105,18 @@ to include ethernet address.
The default format is
.IR @OUTPUT_FORMAT@ .
.TP
\fB\-\-mustach\fR=\fITEMPLATE\fR
Output using mustach
.I template
file. This is useful when the native output formats controlled with
.B \-\-format
option do not provide what you need. See below example mustach template
that is using all available {{tags}} to demonstrate what can be displayed
and how.
.IP
@bindir@/dhcpd-pools --config @docdir@/dhcpd.conf --leases
@docdir@/dhcpd.leases --mustach @docdir@/mustach.template
.TP
\fB\-o\fR, \fB\-\-output\fR=\fIFILE\fR
.I File
where output is written. Default is stdout.
@ -104,29 +135,17 @@ determines which numeric analysis tables to include in the output. The
following values are "OR'd" together to create the desired output. The
default is
.IR @OUTPUT_LIMIT@ .
.PP
.RS
.PD 0
.TP
.B 01
Print ranges
.TP
.B 02
Print shared networks
.TP
.B 04
Print total summary
.TP
.B 10
Print range header
.TP
.B 20
Print shared network header
.TP
.B 40
Print total summary header
.PD
.RE
.IP
.TS
tab(:);
ll.
0\fI1\fR:Print ranges
0\fI2\fR:Print shared networks
0\fI4\fR:Print total summary
\fI1\fR0:Print range header
\fI2\fR0:Print shared network header
\fI4\fR0:Print total summary header
.TE
.IP
The output limit for total summary has special meaning in
.B \-\-warning
@ -136,6 +155,37 @@ alarming context. When the alarming is in use, and total is not wanted
to be seen then in the case of alarming returning success nothing is
printed.
.TP
\fB\-\-color\fR=\fIwhen\fR
Use yellow for warning, red for critical, green for suppressed by \-\-minsize
and blue when \-\-snet\-alarms is the cause of suppression or shared network
does not have any ranges. The
.I when
string can be
.BR always ,
.BR never ,
or
.BR auto .
Default is auto, that uses colors when command is running in interactive
terminal. With use of
.B \-\-warning
or
.B \-\-critical
coloring thresholds can be changed, but one must also use
.B \-\-format=text
to avoid turning on alarting mode.
.TP
\fB\-\-skip\fR=\fIwhen\fR
The
.I when
can be one of the following:
.IR ok ,
.IR warning ,
.IR critical ,
.IR minsize ,
or
.IR suppressed .
The skipping criteria is exact match with colors in \-\-color option.
.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
@ -168,7 +218,7 @@ and count
.I number
are required to be exceeded in order to alarm criteria being fulfilled.
.IP
This option is intented to be used in setup where very large and small
This option is intended to be used in setup where very large and small
shared-networks and ranges co-exists. In such environments percent based
alarming can lead to either flood of alarms about small ranges, or way too
great overhead of free addresses in large shared-networks. Suggested usage
@ -189,9 +239,25 @@ configurations that has lots of small ranges in big shared-networks.
\fB\-\-minsize\fR=\fIsize\fR
Ignore ranges and shared networks that are smaller or equal to the
defined size. This option is meaningful only in context of alarming, and
will intented to supress for example single host ranges. By default this
will intended to suppress for example single host ranges. By default this
option is not in use.
.TP
\fB\-p\fR, \fB\-\-perfdata\fR
Print additional performance data, like lease count, touched leases and
backup leases. This option is meaningful only in context of alarming and
will print lots of data, if there are many networks. By default this option
is not in use.
.TP
\fB\-A\fR, \fB\-\-all\-as\-shared\fR
Treat all stand-alone subnets as shared-network with named formed from it's
CIDR. By default this option is not in use for backwards compatibility.
.TP
\fB\-\-ip\-version\fR=\fI4|6\fR
Force command to read configuration and leases files in IPv4 or IPv6 mode.
Notice that when inputs do not match with what is forced analysis output is
garbage. This option should not be necessary to use, and exists only to
allow debugging.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print version information to standard output and exit successfully.
.TP
@ -220,7 +286,7 @@ $ dhcpd-pools \-c dhcpd.conf \-l dhcpd.leases \-L 22 \-\-critical 70 \-\-warning
.br
[no-output]
.br
Supress printing OK, and make alarm only to go off if shared networks
Suppress printing OK, and make alarm only to go off if shared networks
exceed critial or warning levels.
.SH FILES
.TP
@ -229,14 +295,23 @@ ISC dhcpd configuration file.
.TP
@DHCPDLEASE_FILE@
ISC dhcpd lease file.
.TP
@docdir@/prometheus.template
Prometheus text file collector mustach template.
.SH AUTHORS
Original design by Sami Kerola.
.br
uthash by Troy D. Hanson.
.br
XML support by Dominic Germain, Sogetel inc.
.br
IPv6 support by Cheer Xiao.
.PP
The software has FreeBSD License.
.br
Mustache templating support by José Bollo.
.SH LICENSE
The dhcpd-pools uses FreeBSD License, uthash uses BSD license, the mustache
uses Apache License, and the gnulib modules are mostly, but not entirely,
GPL.
.SH "REPORTING BUGS"
Report bugs to
.MT @PACKAGE_BUGREPORT@
@ -249,4 +324,6 @@ Home page
.SH "SEE ALSO"
.BR dhcpd.leases (5),
.BR dhcpd.conf (5),
.BR chmod (1)
.BR chmod (1),
.UR https://mustache.github.io/
.UE

38
project.doap Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xml:lang="en" xmlns="http://usefulinc.com/ns/doap#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/">
<Project rdf:about="https://dhcpd-pools.sourceforge.net/">
<name>dhcpd-pools</name>
<homepage rdf:resource="https://dhcpd-pools.sourceforge.net/" />
<shortdesc>This is dhcpd-pools ISC dhcp shared network and pool
range usage analysis tool.</shortdesc>
<description>Purpose of command is to count usage ratio of each
IP range and shared network pool which ISC dhcpd is in control
of. Program is written C. Design goal is to get analysis done
quickly where there is lots of data. On cheap laptop the speed
of analysis is more than 100k leases per second. Number of
ranges, or shared networks, does not make any significant
difference in getting analysis done.</description>
<mailing-list rdf:resource="https://lists.sourceforge.net/lists/listinfo/dhcpd-pools-announce" />
<download-page rdf:resource="https://sourceforge.net/projects/dhcpd-pools/files/" />
<programming-language>C</programming-language>
<repository>
<GitRepository>
<location rdf:resource="git://git.code.sf.net/p/dhcpd-pools/code" />
<browse rdf:resource="https://sourceforge.net/p/dhcpd-pools/code/ci/master/tree/" />
</GitRepository>
</repository>
<License>
<rdfs:label>BSD 2-Clause license</rdfs:label>
<rdfs:seeAlso rdf:resource="https://sourceforge.net/p/dhcpd-pools/code/ci/master/tree/COPYING?format=raw" />
</License>
<maintainer>
<foaf:Person>
<foaf:name>Sami Kerola</foaf:name>
<foaf:mbox rdf:resource="mailto:kerolasa@iki.fi" />
</foaf:Person>
</maintainer>
</Project>
</rdf:RDF>

5
samples/Makemodule.am Normal file
View file

@ -0,0 +1,5 @@
dist_doc_DATA = \
samples/dhcpd.conf \
samples/dhcpd.leases \
samples/mustach.template \
samples/prometheus.template

31
samples/dhcpd.conf Normal file
View file

@ -0,0 +1,31 @@
shared-network example1 {
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range 10.0.0.1 10.0.0.20;
}
}
subnet 10.1.0.0 netmask 255.255.255.0 {
pool {
range 10.1.0.1 10.1.0.20;
}
}
}
shared-network example2 {
subnet 10.2.0.0 netmask 255.255.255.0 {
pool {
range 10.2.0.1 10.2.0.20;
}
}
subnet 10.3.0.0 netmask 255.255.255.0 {
pool {
range 10.3.0.1 10.3.0.20;
}
}
}
subnet 10.4.0.0 netmask 255.255.255.0 {
pool {
range 10.4.0.1 10.4.0.20;
}
}

210
samples/dhcpd.leases Normal file
View file

@ -0,0 +1,210 @@
lease 10.0.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.0.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.3 {
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.0.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.0.0.5 {
binding state active;
hardware ethernet 00:00:00:00:00:05;
}
lease 10.0.0.6 {
binding state active;
hardware ethernet 00:00:00:00:00:06;
}
lease 10.0.0.7 {
binding state active;
hardware ethernet 00:00:00:00:00:07;
}
lease 10.0.0.8 {
binding state active;
hardware ethernet 00:00:00:00:00:08;
}
lease 10.0.0.9 {
binding state active;
hardware ethernet 00:00:00:00:00:09;
}
lease 10.0.0.10 {
binding state active;
hardware ethernet 00:00:00:00:00:10;
}
lease 10.0.0.11 {
binding state active;
hardware ethernet 00:00:00:00:00:11;
}
lease 10.0.0.12 {
binding state backup;
hardware ethernet 00:00:00:00:00:12;
}
lease 10.1.0.0 {
binding state active;
hardware ethernet 00:00:00:00:01:00;
}
lease 10.1.0.1 {
binding state active;
hardware ethernet 00:00:00:00:01:01;
}
lease 10.1.0.2 {
binding state active;
hardware ethernet 00:00:00:00:01:02;
}
lease 10.1.0.3 {
binding state active;
hardware ethernet 00:00:00:00:01:03;
}
lease 10.1.0.4 {
binding state active;
hardware ethernet 00:00:00:00:01:04;
}
lease 10.1.0.5 {
binding state active;
hardware ethernet 00:00:00:00:01:05;
}
lease 10.1.0.6 {
binding state active;
hardware ethernet 00:00:00:00:01:06;
}
lease 10.1.0.7 {
binding state active;
hardware ethernet 00:00:00:00:01:07;
}
lease 10.1.0.8 {
binding state active;
hardware ethernet 00:00:00:00:01:08;
}
lease 10.1.0.9 {
binding state active;
hardware ethernet 00:00:00:00:01:09;
}
lease 10.1.0.10 {
binding state active;
hardware ethernet 00:00:00:00:01:10;
}
lease 10.2.0.0 {
binding state active;
hardware ethernet 00:00:00:00:02:00;
}
lease 10.2.0.1 {
binding state active;
hardware ethernet 00:00:00:00:02:01;
}
lease 10.2.0.2 {
binding state active;
hardware ethernet 00:00:00:00:02:02;
}
lease 10.2.0.3 {
binding state active;
hardware ethernet 00:00:00:00:02:03;
}
lease 10.2.0.4 {
binding state active;
hardware ethernet 00:00:00:00:02:04;
}
lease 10.2.0.5 {
binding state active;
hardware ethernet 00:00:00:00:02:05;
}
lease 10.2.0.6 {
binding state active;
hardware ethernet 00:00:00:00:02:06;
}
lease 10.2.0.7 {
binding state active;
hardware ethernet 00:00:00:00:02:07;
}
lease 10.2.0.8 {
binding state active;
hardware ethernet 00:00:00:00:02:08;
}
lease 10.3.0.0 {
binding state active;
hardware ethernet 00:00:00:00:03:00;
}
lease 10.3.0.1 {
binding state active;
hardware ethernet 00:00:00:00:03:01;
}
lease 10.3.0.2 {
binding state active;
hardware ethernet 00:00:00:00:03:02;
}
lease 10.3.0.3 {
binding state active;
hardware ethernet 00:00:00:00:03:03;
}
lease 10.3.0.4 {
binding state active;
hardware ethernet 00:00:00:00:03:04;
}
lease 10.3.0.5 {
binding state active;
hardware ethernet 00:00:00:00:03:05;
}
lease 10.3.0.6 {
binding state active;
hardware ethernet 00:00:00:00:03:06;
}
lease 10.3.0.7 {
binding state active;
hardware ethernet 00:00:00:00:03:07;
}
lease 10.3.0.8 {
binding state active;
hardware ethernet 00:00:00:00:03:08;
}
lease 10.3.0.9 {
binding state active;
hardware ethernet 00:00:00:00:03:09;
}
lease 10.3.0.9 {
binding state active;
hardware ethernet 00:00:00:00:03:09;
}
lease 10.4.0.0 {
binding state active;
hardware ethernet 00:00:00:00:04:00;
}
lease 10.4.0.1 {
binding state active;
hardware ethernet 00:00:00:00:04:01;
}
lease 10.4.0.2 {
binding state active;
hardware ethernet 00:00:00:00:04:02;
}
lease 10.4.0.3 {
binding state active;
hardware ethernet 00:00:00:00:04:03;
}
lease 10.4.0.4 {
binding state active;
hardware ethernet 00:00:00:00:04:04;
}
lease 10.4.0.5 {
binding state active;
hardware ethernet 00:00:00:00:04:05;
}
lease 10.4.0.6 {
binding state backup;
hardware ethernet 00:00:00:00:04:06;
}

76
samples/mustach.template Normal file
View file

@ -0,0 +1,76 @@
Ethernets:{{#active_lease}}
macaddress: {{macaddress}} ip: {{ip}}{{/active_lease}}
Subnets:{{#subnets}}
location: {{location}}
range: {{range}}
first_ip: {{first_ip}}
last_ip: {{last_ip}}
used: {{used}}
touched: {{touched}}
defined: {{defined}}
free: {{free}}
percent: {{percent}}
touch_count: {{touch_count}}
touch_percent: {{touch_percent}}
backup_count: {{backup_count}}
backup_percent: {{backup_percent}}
status: {{status}}
gettimeofday: {{gettimeofday}}
lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/subnets}}
Shared-networks:{{#shared-networks}}
location: {{location}}
defined: {{defined}}
used: {{used}}
touched: {{touched}}
free: {{free}}
percent: {{percent}}
touch_count: {{touch_count}}
touch_percent: {{touch_percent}}
backup_count: {{backup_count}}
backup_percent: {{backup_percent}}
status: {{status}}
gettimeofday: {{gettimeofday}}
lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/shared-networks}}
Summary:{{#summary}}
location: {{location}}
defined: {{defined}}
used: {{used}}
touched: {{touched}}
free: {{free}}
percent: {{percent}}
touch_count: {{touch_count}}
touch_percent: {{touch_percent}}
backup_count: {{backup_count}}
backup_percent: {{backup_percent}}
status: {{status}}
gettimeofday: {{gettimeofday}}
lease_file_epoch_mtime: {{lease_file_epoch_mtime}}
{{/summary}}
localtime: {{localtime}}
number_of_ranges: {{number_of_ranges}}
number_of_shared_networks: {{number_of_shared_networks}}
version: {{version}}
conf_file_path: {{conf_file_path}}
conf_file_local_mtime: {{conf_file_local_mtime}}
conf_file_epoch_mtime: {{conf_file_epoch_mtime}}
lease_file_path: {{lease_file_path}}
lease_file_local_mtime: {{lease_file_local_mtime}}
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}}

View file

@ -0,0 +1,11 @@
# This mustach template can be used as Prometheus text file.
# https://prometheus.io/
# HELP dhcpd_pools ISC dhcpd statistics
# TYPE dhcpd_pools gauge
{{#subnets}}dhcpd_pools{location="{{location}}",range="{{first_ip}}",used="1"} {{used}} {{gettimeofday}}000
dhcpd_pools{location="{{location}}",range="{{first_ip}}",touched="1"} {{touched}} {{gettimeofday}}000
dhcpd_pools{location="{{location}}",range="{{first_ip}}",defined="1"} {{defined}} {{gettimeofday}}000
dhcpd_pools{location="{{location}}",range="{{first_ip}}",free="1"} {{free}} {{gettimeofday}}000
dhcpd_pools{location="{{location}}",range="{{first_ip}}",touch_count="1"} {{touch_count}} {{gettimeofday}}000
dhcpd_pools{location="{{location}}",range="{{first_ip}}",status="1"} {{status}} {{gettimeofday}}000
{{/subnets}}

11
src/.indent.pro vendored
View file

@ -1,5 +1,6 @@
-linux
-TFILE
-Tconf_t
-Tipaddr_t
-Tleases_t
-Toff_t
@ -7,7 +8,9 @@
-Tsize_t
-Ttime_t
-Tuintmax_t
-l100
-ppi1
-bad
-sob
--blank-lines-after-declarations
--format-all-comments
--line-length100
--preprocessor-indentation1
--start-left-side-of-comments
--swallow-optional-blank-lines

View file

@ -4,11 +4,10 @@ bin_PROGRAMS = dhcpd-pools
AC_PROG_RANLIB = resolv
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_builddir)/lib
dhcpd_pools_LDADD = $(top_builddir)/lib/libdhcpd_pools.la
dhcpd_pools_LDADD = $(top_builddir)/lib/libdhcpd_pools.la $(MATH_LIBS)
dhcpd_pools_SOURCES = \
src/analyze.c \
src/defaults.h \
src/dhcpd-pools.c \
src/dhcpd-pools.h \
src/getdata.c \
@ -16,3 +15,10 @@ dhcpd_pools_SOURCES = \
src/other.c \
src/output.c \
src/sort.c
if ENABLE_MUSTACH
dhcpd_pools_SOURCES += \
src/mustach-dhcpd-pools.c \
src/mustach.c \
src/mustach.h
endif

View file

@ -47,30 +47,31 @@
/*! \brief Prepare data for analysis. The function will sort leases and
* ranges. */
void prepare_data(void)
void prepare_data(struct conf_t *state)
{
/* Sort leases */
HASH_SORT(leases, leasecomp);
HASH_SORT(state->leases, leasecomp);
/* Sort ranges */
qsort(ranges, (size_t)num_ranges, sizeof(struct range_t), &rangecomp);
qsort(state->ranges, state->num_ranges, sizeof(struct range_t), &rangecomp);
}
/*! \brief Perform counting. Join leases with ranges, and update counters. */
void do_counting(void)
/*!\brief Perform counting. Join leases with ranges, and update range and
* shared network counters. */
void do_counting(struct conf_t *state)
{
struct range_t *restrict range_p;
const struct leases_t *restrict l = leases;
unsigned long i, k, block_size;
struct range_t *restrict range_p = state->ranges;
const struct leases_t *restrict l = state->leases;
unsigned long i;
double block_size;
/* Walk through ranges */
range_p = ranges;
for (i = 0; i < num_ranges; i++) {
for (; l != NULL && ipcomp(&range_p->first_ip, &l->ip) < 0; l = l->hh.prev)
/* rewind */ ;
for (i = 0; i < state->num_ranges; i++, range_p++) {
while (l != NULL && ipcomp(&range_p->first_ip, &l->ip) < 0)
l = l->hh.prev; /* rewind */
if (l == NULL)
l = leases;
l = state->leases;
for (; l != NULL && ipcomp(&l->ip, &range_p->last_ip) <= 0; l = l->hh.next) {
if (ipcomp(&l->ip, &range_p->first_ip) < 0)
if (unlikely(ipcomp(&l->ip, &range_p->first_ip) < 0))
continue; /* cannot happen? */
/* IP in range */
switch (l->type) {
@ -83,39 +84,23 @@ void do_counting(void)
case BACKUP:
range_p->backups++;
break;
}
if (range_p->shared_net) {
switch (l->type) {
case FREE:
range_p->shared_net->touched++;
break;
case ACTIVE:
range_p->shared_net->used++;
break;
case BACKUP:
range_p->shared_net->backups++;
break;
}
default:
abort();
}
}
/* Size of range, shared net & all networks */
/* Size of range size. */
block_size = get_range_size(range_p);
if (range_p->shared_net)
range_p->shared_net->available += block_size;
range_p++;
}
/* FIXME: During count of other shared networks default network
* and all networks got mixed together semantically. The below
* fixes the problem, but is not elegant. */
shared_networks->available = 0;
shared_networks->used = 0;
shared_networks->touched = 0;
range_p = ranges;
for (k = 0; k < num_ranges; k++) {
shared_networks->available += get_range_size(range_p);
shared_networks->used += range_p->count;
shared_networks->touched += range_p->touched;
shared_networks->backups += range_p->backups;
range_p++;
/* Count together ranges within shared network block. */
range_p->shared_net->available += block_size;
range_p->shared_net->used += range_p->count;
range_p->shared_net->touched += range_p->touched;
range_p->shared_net->backups += range_p->backups;
/* When shared network is not 'all networks' add it as well. */
if (range_p->shared_net != state->shared_net_root) {
state->shared_net_root->available += block_size;
state->shared_net_root->used += range_p->count;
state->shared_net_root->touched += range_p->touched;
state->shared_net_root->backups += range_p->backups;
}
}
}

View file

@ -1,55 +0,0 @@
/*
* 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 defaults.h
* \brief Default settings which cannot be changed without recompiling
* the software.
*/
#ifndef DEFAULTS_H
# define DEFAULTS_H 1
# include "dhcpd-pools.h"
/*! \var MAXLEN
* \brief Maximum expected line length in dhcpd.conf and dhcpd.leases
* files. */
static const size_t MAXLEN = 1024;
/*! \var SHARED_NETWORKS
* \brief Maximum number of different shared networks in dhcpd.conf file. */
static const unsigned int SHARED_NETWORKS = 8192;
#endif /* DEFAULTS_H */

View file

@ -39,6 +39,7 @@
#include <config.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
@ -53,74 +54,111 @@
#include "xalloc.h"
#include "dhcpd-pools.h"
#include "defaults.h"
/* Global variables */
int prefix_length[2][NUM_OF_PREFIX];
struct configuration_t config;
struct shared_network_t *shared_networks;
unsigned int num_shared_networks;
struct range_t *ranges;
unsigned int num_ranges;
struct leases_t *leases;
unsigned int RANGES;
/* Function pointers */
int (*parse_ipaddr) (const char *restrict src, union ipaddr_t *restrict dst);
int (*parse_ipaddr) (struct conf_t *state, const char *restrict src, union ipaddr_t *restrict dst);
void (*copy_ipaddr) (union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
const char *(*ntop_ipaddr) (const union ipaddr_t *ip);
double (*get_range_size) (const struct range_t *r);
int (*xstrstr) (const char *__restrict str);
int (*xstrstr) (struct conf_t *state, const char *restrict str);
int (*ipcomp) (const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
int (*leasecomp) (const struct leases_t *restrict a, const struct leases_t *restrict b);
int (*output_analysis) (void);
void (*add_lease) (union ipaddr_t *ip, enum ltype type);
struct leases_t *(*find_lease) (union ipaddr_t *ip);
void (*add_lease) (struct conf_t *state, union ipaddr_t *ip, enum ltype type);
struct leases_t *(*find_lease) (struct conf_t *state, union ipaddr_t *ip);
/*! \brief An option argument parser to populate state header_limit and
* number_limit values.
*/
static int return_limit(const char c)
{
if ('0' <= c && c < '8')
return c - '0';
clean_up();
error(EXIT_FAILURE, 0, "return_limit: output mask %s is illegal", quote(optarg));
return 0;
}
/*! \brief Start of execution. Parse options, and call other other
* functions one after another. At the moment adding threading support
* would be difficult, but there does not seem to be valid reason to
* consider that. Overall the analysis already quick enough even without
* making it parallel.
*
* \return Return value indicates success or fail or analysis, unless
* either --warning or --critical options are in use, which makes the
* return value in some cases to match with Nagios expectations about
* alarming. */
int main(int argc, char **argv)
/*! \brief Run time initialization. Global allocations, counter
* initializations, etc are here. */
static void prepare_memory(struct conf_t *state)
{
state->ranges = xmalloc(sizeof(struct range_t) * state->ranges_size);
/* First shared network entry is all networks */
state->shared_net_root = xcalloc(sizeof(struct shared_network_t), 1);
state->shared_net_root->name = xstrdup("All networks");
state->shared_net_head = state->shared_net_root;
}
/*! \brief The --skip option argument parser. */
static void skip_arg_parse(struct conf_t *state, char *arg)
{
enum {
OPT_ARG_OK = 0,
OPT_ARG_WARNING,
OPT_ARG_CRITICAL,
OPT_ARG_MINSIZE,
OPT_ARG_SUPPRESSED
};
char *const tokens[] = {
[OPT_ARG_OK] = "ok",
[OPT_ARG_WARNING] = "warning",
[OPT_ARG_CRITICAL] = "critical",
[OPT_ARG_MINSIZE] = "minsize",
[OPT_ARG_SUPPRESSED] = "suppressed",
NULL
};
char *value;
while (*arg != '\0') {
switch (getsubopt(&arg, tokens, &value)) {
case OPT_ARG_OK:
state->skip_ok = 1;
break;
case OPT_ARG_WARNING:
state->skip_warning = 1;
break;
case OPT_ARG_CRITICAL:
state->skip_critical = 1;
break;
case OPT_ARG_MINSIZE:
state->skip_minsize = 1;
break;
case OPT_ARG_SUPPRESSED:
state->skip_suppressed = 1;
break;
default:
error(EXIT_FAILURE, 0, "unknown --skip specifier: %s", value);
}
}
}
/*! \brief Command line options parser. */
static void parse_command_line_opts(struct conf_t *state, int argc, char **argv)
{
int i;
int option_index = 0;
char const *tmp;
char *print_mac_addreses_tmp;
struct range_t *tmp_ranges;
enum {
OPT_SNET_ALARMS = CHAR_MAX + 1,
OPT_WARN,
OPT_CRIT,
OPT_MINSIZE,
OPT_WARN_COUNT,
OPT_CRIT_COUNT
OPT_CRIT_COUNT,
OPT_COLOR,
OPT_SKIP,
OPT_SET_IPV,
OPT_MUSTACH
};
int ret_val;
static struct option const long_options[] = {
{"config", required_argument, NULL, 'c'},
{"leases", required_argument, NULL, 'l'},
{"color", required_argument, NULL, OPT_COLOR},
{"skip", required_argument, NULL, OPT_SKIP},
{"format", required_argument, NULL, 'f'},
{"sort", required_argument, NULL, 's'},
{"reverse", no_argument, NULL, 'r'},
{"output", required_argument, NULL, 'o'},
{"limit", required_argument, NULL, 'L'},
{"mustach", required_argument, NULL, OPT_MUSTACH},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
{"snet-alarms", no_argument, NULL, OPT_SNET_ALARMS},
@ -129,111 +167,124 @@ int main(int argc, char **argv)
{"warn-count", required_argument, NULL, OPT_WARN_COUNT},
{"crit-count", required_argument, NULL, OPT_CRIT_COUNT},
{"minsize", required_argument, NULL, OPT_MINSIZE},
{"perfdata", no_argument, NULL, 'p'},
{"all-as-shared", no_argument, NULL, 'A'},
{"ip-version", required_argument, NULL, OPT_SET_IPV},
{NULL, 0, NULL, 0}
};
int alarming = 0;
atexit(close_stdout);
set_program_name(argv[0]);
/* FIXME: These allocations should be fully dynamic, e.g., grow
* if needed. */
config.dhcpdconf_file = xmalloc(sizeof(char) * MAXLEN);
config.dhcpdlease_file = xmalloc(sizeof(char) * MAXLEN);
config.output_file = xmalloc(sizeof(char) * MAXLEN);
/* Make sure string has zero length if there is no
* command line option */
config.output_file[0] = '\0';
/* Alarming defaults. */
config.snet_alarms = false;
config.warning = ALARM_WARN;
config.critical = ALARM_CRIT;
config.warn_count = 0x100000000; /* == 2^32 that is the entire IPv4 space */
config.crit_count = 0x100000000; /* basically turns off the count criteria */
/* File location defaults */
strncpy(config.dhcpdconf_file, DHCPDCONF_FILE, MAXLEN - 1);
strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE, MAXLEN - 1);
tmp = OUTPUT_LIMIT;
config.header_limit = (*tmp - '0');
tmp++;
config.number_limit = (*tmp - '0');
/* Make sure some output format is selected by default */
print_mac_addreses_tmp = OUTPUT_FORMAT;
/* Default sort order is by IPs small to big */
config.reverse_order = false;
config.backups_found = false;
prepare_memory();
/* Parse command line options */
while (1) {
int c;
c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh", long_options, &option_index);
c = getopt_long(argc, argv, "c:l:f:o:s:rL:pAvh", long_options, NULL);
if (c == EOF)
break;
switch (c) {
case 'c':
/* config file */
strncpy(config.dhcpdconf_file, optarg, MAXLEN - 1);
state->dhcpdconf_file = optarg;
break;
case 'l':
/* lease file */
strncpy(config.dhcpdlease_file, optarg, MAXLEN - 1);
state->dhcpdlease_file = optarg;
break;
case 'f':
/* Output format */
print_mac_addreses_tmp = optarg;
state->output_format = optarg[0];
break;
case 's':
{
/* Output sorting option */
struct output_sort *p = config.sorts;
{
/* Output sorting option */
struct output_sort *p = state->sorts;
char *ptr = optarg;
while (p && p->next)
p = p->next;
for (i = 0; i < strlen(optarg); i++) {
if (config.sorts == NULL) {
config.sorts = xcalloc(1, sizeof(struct output_sort));
p = config.sorts;
} else {
p->next = xcalloc(1, sizeof(struct output_sort));
while (p && p->next)
p = p->next;
while (*ptr) {
if (state->sorts == NULL) {
state->sorts =
xcalloc(1, sizeof(struct output_sort));
p = state->sorts;
} else {
p->next = xcalloc(1, sizeof(struct output_sort));
p = p->next;
}
p->func = field_selector(*ptr++);
}
p->func = field_selector(optarg[i]);
}
}
break;
case 'r':
/* What ever sort in reverse order */
config.reverse_order = true;
state->reverse_order = 1;
break;
case 'o':
/* Output file */
strncpy(config.output_file, optarg, MAXLEN - 1);
state->output_file = optarg;
break;
case 'L':
/* Specification what will be printed */
config.header_limit = return_limit(optarg[0]);
config.number_limit = return_limit(optarg[1]);
state->header_limit = return_limit(optarg[0]);
state->number_limit = return_limit(optarg[1]);
break;
case OPT_MUSTACH:
#ifdef BUILD_MUSTACH
state->mustach_template = optarg;
state->output_format = 'm';
state->print_mac_addreses = 1;
#else
error(EXIT_FAILURE, 0, "compiled without mustach support");
#endif
break;
case OPT_COLOR:
state->color_mode = parse_color_mode(optarg);
if (state->color_mode == color_unknown)
error(EXIT_FAILURE, errno, "unknown color mode: %s", quote(optarg));
break;
case OPT_SKIP:
skip_arg_parse(state, optarg);
break;
case OPT_SNET_ALARMS:
config.snet_alarms = true;
state->snet_alarms = 1;
break;
case OPT_WARN:
print_mac_addreses_tmp = "a";
config.warning = strtod_or_err(optarg, "illegal argument");
alarming = 1;
state->warning = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT:
print_mac_addreses_tmp = "a";
config.critical = strtod_or_err(optarg, "illegal argument");
alarming = 1;
state->critical = strtod_or_err(optarg, "illegal argument");
break;
case OPT_WARN_COUNT:
print_mac_addreses_tmp = "a";
config.warn_count = strtod_or_err(optarg, "illegal argument");
alarming = 1;
state->warn_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT_COUNT:
print_mac_addreses_tmp = "a";
config.crit_count = strtod_or_err(optarg, "illegal argument");
alarming = 1;
state->crit_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_MINSIZE:
config.minsize = strtod_or_err(optarg, "illegal argument");
state->minsize = strtod_or_err(optarg, "illegal argument");
break;
case OPT_SET_IPV:
switch (optarg[0]) {
case '4':
set_ipv_functions(state, IPv4);
break;
case '6':
set_ipv_functions(state, IPv6);
break;
default:
error(EXIT_FAILURE, 0, "unknown --ip-version argument: %s", optarg);
}
break;
case 'p':
/* Print additional performance data in alarming mode */
state->perfdata = 1;
break;
case 'A':
/* Treat single networks as shared with network CIDR as name */
state->all_as_shared = 1;
break;
case 'v':
/* Print version */
@ -242,81 +293,76 @@ int main(int argc, char **argv)
/* Print help */
usage(EXIT_SUCCESS);
default:
error(EXIT_FAILURE, 0, "Try %s --help for more information.",
program_name);
error(EXIT_FAILURE, 0, "Try %s --help for more information.", program_name);
}
}
/* Output function selection */
switch (print_mac_addreses_tmp[0]) {
case 't':
output_analysis = output_txt;
config.print_mac_addreses = 0;
break;
case 'a':
output_analysis = output_alarming;
config.print_mac_addreses = 0;
break;
case 'h':
error(EXIT_FAILURE, 0, "html table only output format is deprecated");
break;
case 'H':
output_analysis = output_html;
config.print_mac_addreses = 0;
break;
case 'x':
output_analysis = output_xml;
config.print_mac_addreses = 0;
break;
case 'X':
output_analysis = output_xml;
config.print_mac_addreses = 1;
break;
case 'j':
output_analysis = output_json;
config.print_mac_addreses = 0;
break;
case 'J':
output_analysis = output_json;
config.print_mac_addreses = 1;
break;
case 'c':
output_analysis = output_csv;
config.print_mac_addreses = 0;
break;
default:
clean_up();
error(EXIT_FAILURE, 0, "unknown output format: %s", quote(print_mac_addreses_tmp));
/* Use default dhcpd.conf when user did not define anything. */
if (state->dhcpdconf_file == NULL)
state->dhcpdconf_file = DHCPDCONF_FILE;
/* Use default dhcpd.leases when user did not define anything. */
if (state->dhcpdlease_file == NULL)
state->dhcpdlease_file = DHCPDLEASE_FILE;
/* Use default limits when user did not define anything. */
if (state->header_limit == 8) {
char const *default_limit = OUTPUT_LIMIT;
state->header_limit = return_limit(default_limit[0]);
state->number_limit = return_limit(default_limit[1]);
}
/* Output format is not defined, if alarm thresholds are then it's alarming, else use the
* default. */
if (state->output_format == '\0') {
if (alarming == 1)
state->output_format = 'a';
else {
const char *const default_format = OUTPUT_FORMAT;
state->output_format = default_format[0];
}
}
if (state->output_format == 'X' || state->output_format == 'J') {
state->print_mac_addreses = 1;
}
/* Do the job */
set_ipv_functions(IPvUNKNOWN);
parse_config(true, config.dhcpdconf_file, shared_networks);
parse_leases();
prepare_data();
do_counting();
tmp_ranges = xmalloc(sizeof(struct range_t) * num_ranges);
if (config.sorts != NULL)
mergesort_ranges(ranges, num_ranges, tmp_ranges);
if (config.reverse_order == true)
flip_ranges(ranges, tmp_ranges);
free(tmp_ranges);
ret_val = output_analysis();
clean_up();
return (ret_val);
}
/*! \brief Run time initialization. Global allocations, counter
* initializations, etc are here. */
void prepare_memory(void)
/*!\brief Start of execution. This will mostly call other functions one
* after another.
*
* \return Return value indicates success or fail or analysis, unless
* either --warning or --critical options are in use, which makes the
* return value in some cases to match with Nagios expectations about
* alarming. */
int main(int argc, char **argv)
{
config.ip_version = IPvUNKNOWN;
RANGES = 64;
num_ranges = num_shared_networks = 0;
shared_networks = xmalloc(sizeof(struct shared_network_t) * SHARED_NETWORKS);
ranges = xmalloc(sizeof(struct range_t) * RANGES);
/* First shared network entry is all networks */
shared_networks->name = xstrdup("All networks");
shared_networks->used = 0;
shared_networks->touched = 0;
shared_networks->backups = 0;
config.sorts = NULL;
struct conf_t state = {
.warning = ALARM_WARN,
.critical = ALARM_CRIT,
.warn_count = 0x100000000, /* == 2^32 that is the entire IPv4 space */
.crit_count = 0x100000000, /* basically turns off the count criteria */
.header_limit = 8,
.ranges_size = 64,
.ip_version = IPvUNKNOWN,
.color_mode = color_auto
};
int ret_val;
atexit(close_stdout);
set_program_name(argv[0]);
prepare_memory(&state);
set_ipv_functions(&state, IPvUNKNOWN);
parse_command_line_opts(&state, argc, argv);
/* Do the job */
parse_config(&state, 1, state.dhcpdconf_file, state.shared_net_root);
parse_leases(&state);
prepare_data(&state);
do_counting(&state);
if (state.sorts != NULL)
mergesort_ranges(&state, state.ranges, state.num_ranges, NULL, 1);
if (state.reverse_order == 1)
flip_ranges(&state);
ret_val = output_analysis(&state);
clean_up(&state);
return (ret_val);
}

View file

@ -35,8 +35,6 @@
/*! \file dhcpd-pools.h
* \brief Global definitions of structures, enums, and function prototypes.
* FIXME: The file has too many global variables. Most of them should be
* removed, if not all.
*/
#ifndef DHCPD_POOLS_H
@ -63,22 +61,11 @@
# define unlikely(x) (x)
# endif
/* The __attribute__ feature is available in gcc versions 2.5 and later.
* The attribute __pure__ was added in gcc 2.96. */
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
# define _DP_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
# define _DP_ATTRIBUTE_PURE /* empty */
# endif
/* The __const__ attribute was added in gcc 2.95. */
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
# define _DP_ATTRIBUTE_CONST __attribute__ ((__const__))
# else
# define _DP_ATTRIBUTE_CONST /* empty */
# endif
/* The attribute __hot__ was added in gcc 4.3. */
/*! \def _DP_ATTRIBUTE_HOT
* \brief The function attribute __hot__ was added in gcc 4.3. See gnu
* documentation for further information.
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-hot-function-attribute
*/
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
# define _DP_ATTRIBUTE_HOT __attribute__ ((__hot__))
# else
@ -91,6 +78,7 @@ union ipaddr_t {
uint32_t v4;
unsigned char v6[16];
};
/*! \enum dhcp_version
* \brief The IP version, IPv4 or IPv6, served by the dhcpd.
*/
@ -99,9 +87,11 @@ enum dhcp_version {
IPv4,
IPv6
};
/*! \enum prefix_t
* \brief Enumeration of interesting data in dhcpd.leases file, that has
* to be further examined, and saved.
* \brief Enumeration of interesting data in dhcpd.leases file, that has to
* be further examined, and saved. Functions xstrstr_v4() and xstrstr_v6()
* return one of these values to parse_leases().
*/
enum prefix_t {
PREFIX_LEASE,
@ -112,10 +102,25 @@ enum prefix_t {
PREFIX_BINDING_STATE_ACTIVE,
PREFIX_BINDING_STATE_BACKUP,
PREFIX_HARDWARE_ETHERNET,
PREFIX_STARTS,
PREFIX_ENDS,
PREFIX_HOSTNAME,
NUM_OF_PREFIX
};
/*! \enum color_mode
* \brief Enumeration whether to use or not color output.
*/
enum color_mode {
color_unknown,
color_off,
color_on,
color_auto /*!< Default, use colors when output terminal is interactive. */
};
/*! \struct shared_network_t
* \brief Counters for an individual shared network.
* \brief Counters for an individual shared network. This data entry is
* also used for 'all networks' counting.
*/
struct shared_network_t {
char *name;
@ -123,7 +128,10 @@ struct shared_network_t {
double used;
double touched;
double backups;
struct shared_network_t *next;
int netmask;
};
/*! \struct range_t
* \brief Counters for an individual range.
*/
@ -135,44 +143,62 @@ struct range_t {
double touched;
double backups;
};
/*! \enum isc_conf_parser
* \brief Configuration file parsing state flags.
/*! \struct output_helper_t
* \brief Various per range and shared net temporary calculation results.
*/
enum isc_conf_parser {
ITS_NOTHING_INTERESTING,
ITS_A_RANGE_FIRST_IP,
ITS_A_RANGE_SECOND_IP,
ITS_A_SHAREDNET,
ITS_AN_INCLUCE
struct output_helper_t {
double range_size;
double percent;
double tc;
double tcp;
double bup;
int status;
};
/*! \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.
* \brief Lease state types. These are the possible values in struct leases_t.
*/
enum ltype {
ACTIVE,
FREE,
BACKUP
};
/*! \struct leases_t
* \brief An individual lease. The leaases are hashed.
* \brief An individual lease. These leaases are hashed.
*/
struct leases_t {
union ipaddr_t ip; /* ip as key */
enum ltype type;
char *ethernet;
UT_hash_handle hh;
enum ltype type;
char *ends;
char *starts;
char *hostname;
};
/*! \enum limbits
* \brief Output limit bits: R_BIT ranges, S_BIT shared networks, A_BIT all.
* \brief Output limit bits.
*/
enum limbits {
R_BIT = (1 << 0),
S_BIT = (1 << 1),
A_BIT = (1 << 2)
R_BIT = (1 << 0), /*!< Range limit. */
S_BIT = (1 << 1), /*!< Shared networks limit. */
A_BIT = (1 << 2) /*!< All networks summary limit. */
};
/*! \def STATE_OK
* \brief Nagios alarm exit values.
* \brief Nagios alarm exit value.
*/
# define STATE_OK 0
# define STATE_WARNING 1
@ -190,99 +216,129 @@ struct output_sort {
comparer_t func;
struct output_sort *next;
};
/*! \struct configuration_t
* \brief Runtime configuration.
/*! \struct conf_t
* \brief Runtime configuration state.
*/
struct configuration_t {
char dhcpv6;
enum dhcp_version ip_version;
char *dhcpdconf_file;
char *dhcpdlease_file;
struct output_sort *sorts;
char *output_file;
double warning;
double critical;
double warn_count;
double crit_count;
double minsize;
unsigned int
reverse_order:1,
backups_found:1,
snet_alarms:1,
print_mac_addreses:1,
header_limit:3,
number_limit:3;
struct conf_t {
struct shared_network_t *shared_net_root; /*!< First entry in shared network linked list, that is the 'all networks', */
struct shared_network_t *shared_net_head; /*!< Last entry in shared network linked list. */
struct range_t *ranges; /*!< Array of ranges. */
unsigned int num_ranges; /*!< Number of ranges in the ranges array. */
enum dhcp_version ip_version; /*!< Designator if the dhcpd is running in IPv4 or IPv6 mode. */
size_t ranges_size; /*!< Size of the ranges array. */
struct leases_t *leases; /*!< An array of individual leases from dhcpd.leases file. */
const char *dhcpdconf_file; /*!< Path to dhcpd.conf file. */
const char *dhcpdlease_file; /*!< Path to dhcpd.leases file. */
struct output_sort *sorts; /*!< Linked list how to sort ranges. */
const char *output_file; /*!< Output file path. */
const char *mustach_template; /*!< Mustach template file path. */
double warning; /*!< Warning percent threshold. */
double critical; /*!< Critical percent threshold. */
double warn_count; /*!< Maximum number of free IP's before warning. */
double crit_count; /*!< Maximum number of free IP's before critical. */
double minsize; /*!< Minimum size of range or shared network to be considered exceeding threshold. */
int color_format; /*!< Column to use in color_tags array. */
char output_format; /*!< Output format, such as text, json, xml, .... */
uint32_t
print_mac_addreses:1, /*!< Print mac address in xml or json. */
reverse_order:1, /*!< Reverse sort order. */
backups_found:1, /*!< Indicator if dhcpd.leases file has leases in backup state. */
snet_alarms:1, /*!< Suppress alarming thresholds for ranges that are part of a shared network. */
perfdata:1, /*!< Include performance statistics when using Nagios alarm output format. */
all_as_shared:1, /*!< Treat stand-alone subnets as a shared network. */
header_limit:4, /*!< Bits to suppress header output. */
number_limit:3, /*!< Bits to suppress value output. */
skip_ok:1, /*!< Skip none-alarming values from output. */
skip_warning:1, /*!< Skip warning values from output. */
skip_critical:1, /*!< Skip critical values from output. */
skip_minsize:1, /*!< Skip alarming values that are below minsize from output. */
skip_suppressed:1, /*!< Skip alarming values that are suppressed with --snet-alarms option, or they are shared networks without IP availability. */
color_mode:2; /*!< Indicator if colors should be used in output. */
};
/* Global variables */
/* \var prefix_length Length of each prefix. */
extern int prefix_length[2][NUM_OF_PREFIX];
/* \var config Runtime configuration. */
extern struct configuration_t config;
/* \var shared_networks Pointer holding shared network count results. */
extern struct shared_network_t *shared_networks;
/* \var num_shared_networks Number of shared networks found. */
extern unsigned int num_shared_networks;
/* \var ranges Pointer holding range count results. */
extern struct range_t *ranges;
/* \var num_ranges Number of ranges found. */
extern unsigned int num_ranges;
/* \var leases Pointer holding all leases. */
extern struct leases_t *leases;
/*! \var RANGES Maximum number of ranges. */
extern unsigned int RANGES;
/* Function prototypes */
extern void prepare_memory(void);
extern void set_ipv_functions(int version);
extern int parse_leases(void);
extern void parse_config(int, const char *__restrict, struct shared_network_t *__restrict)
__attribute__ ((nonnull(2, 3)));
extern void prepare_data(void);
extern void do_counting(void);
extern void flip_ranges(struct range_t *__restrict ranges, struct range_t *__restrict tmp_ranges)
__attribute__ ((nonnull(1, 2)));
/* support functions */
extern int (*parse_ipaddr) (const char *restrict src, union ipaddr_t *restrict dst);
extern int parse_ipaddr_init(const char *restrict src,
union ipaddr_t *restrict dst) _DP_ATTRIBUTE_CONST;
extern int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst);
extern int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst);
/* analyze.c */
extern void prepare_data(struct conf_t *state);
extern void do_counting(struct conf_t *state);
/* getdata.c */
extern int parse_leases(struct conf_t *state);
extern void parse_config(struct conf_t *state, const int is_include,
const char *restrict config_file,
struct shared_network_t *restrict shared_p);
/* hash.c */
extern void (*add_lease) (struct conf_t *state, union ipaddr_t *addr, enum ltype type);
extern void add_lease_init(struct conf_t *state, union ipaddr_t *addr, enum ltype type);
extern void add_lease_v4(struct conf_t *state, union ipaddr_t *addr, enum ltype type);
extern void add_lease_v6(struct conf_t *state, union ipaddr_t *addr, enum ltype type);
extern struct leases_t *(*find_lease) (struct conf_t *state, union ipaddr_t *addr);
extern struct leases_t *find_lease_init(struct conf_t *state, union ipaddr_t *addr);
extern struct leases_t *find_lease_v4(struct conf_t *state, union ipaddr_t *addr);
extern struct leases_t *find_lease_v6(struct conf_t *state, union ipaddr_t *addr);
extern void delete_lease(struct conf_t *state, struct leases_t *lease);
extern void delete_all_leases(struct conf_t *state);
/* mustach-dhcpd-pools.c */
extern int mustach_dhcpd_pools(struct conf_t *state);
/* other.c */
extern void set_ipv_functions(struct conf_t *state, int version);
extern void flip_ranges(struct conf_t *state);
extern void clean_up(struct conf_t *state);
extern void parse_cidr(struct conf_t *state, struct range_t *range_p, const char *word);
extern int parse_color_mode(const char *restrict arg);
extern double strtod_or_err(const char *restrict str, const char *restrict errmesg);
extern void __attribute__ ((noreturn)) print_version(void);
extern void __attribute__ ((noreturn)) usage(int status);
extern void dp_time_tool(FILE *file, const char *path, int epoch);
extern int (*parse_ipaddr) (struct conf_t *state, const char *restrict src,
union ipaddr_t *restrict dst);
extern int parse_ipaddr_init(struct conf_t *state, const char *restrict src,
union ipaddr_t *restrict dst);
extern int parse_ipaddr_v4(struct conf_t *state, const char *restrict src,
union ipaddr_t *restrict dst);
extern int parse_ipaddr_v6(struct conf_t *state, const char *restrict src,
union ipaddr_t *restrict dst);
extern int (*xstrstr) (struct conf_t *state, const char *restrict str);
extern int xstrstr_init(struct conf_t *state, const char *restrict str);
extern int xstrstr_v4(struct conf_t *state, const char *restrict str);
extern int xstrstr_v6(struct conf_t *state, const char *restrict str);
extern void (*copy_ipaddr) (union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
extern void copy_ipaddr_init(union ipaddr_t *restrict dst,
const union ipaddr_t *restrict src) _DP_ATTRIBUTE_CONST;
extern void copy_ipaddr_init(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
extern void copy_ipaddr_v4(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
extern void copy_ipaddr_v6(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src);
extern const char *(*ntop_ipaddr) (const union ipaddr_t *ip);
extern const char *ntop_ipaddr_init(const union ipaddr_t *ip) _DP_ATTRIBUTE_CONST;
extern const char *ntop_ipaddr_init(const union ipaddr_t *ip);
extern const char *ntop_ipaddr_v4(const union ipaddr_t *ip);
extern const char *ntop_ipaddr_v6(const union ipaddr_t *ip);
extern double (*get_range_size) (const struct range_t *r);
extern double get_range_size_init(const struct range_t *r) _DP_ATTRIBUTE_CONST;
extern double get_range_size_v4(const struct range_t *r) _DP_ATTRIBUTE_PURE;
extern double get_range_size_v6(const struct range_t *r) _DP_ATTRIBUTE_PURE;
extern double get_range_size_init(const struct range_t *r);
extern double get_range_size_v4(const struct range_t *r);
extern double get_range_size_v6(const struct range_t *r);
extern int (*xstrstr) (const char *__restrict str);
extern int xstrstr_init(const char *__restrict str) _DP_ATTRIBUTE_CONST;
extern int xstrstr_v4(const char *__restrict str)
_DP_ATTRIBUTE_HOT _DP_ATTRIBUTE_PURE;
extern int xstrstr_v6(const char *__restrict str)
_DP_ATTRIBUTE_HOT _DP_ATTRIBUTE_PURE;
/* output.c */
extern int range_output_helper(struct conf_t *state, struct output_helper_t *oh,
struct range_t *range_p);
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);
extern double strtod_or_err(const char *__restrict str, const char *__restrict errmesg);
extern void print_version(void) __attribute__ ((noreturn));
extern void usage(int status) __attribute__ ((noreturn));
/* qsort required functions... */
/* ...for ranges and... */
extern int (*ipcomp) (const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
extern int ipcomp_init(const union ipaddr_t *restrict a,
const union ipaddr_t *restrict b) _DP_ATTRIBUTE_CONST;
extern int ipcomp_v4(const union ipaddr_t *restrict a,
const union ipaddr_t *restrict b) _DP_ATTRIBUTE_PURE;
extern int ipcomp_v6(const union ipaddr_t *restrict a,
const union ipaddr_t *restrict b) _DP_ATTRIBUTE_PURE;
/* sort.c */
extern void mergesort_ranges(struct conf_t *state,
struct range_t *restrict orig, unsigned int size,
struct range_t *restrict temp, const int root_call);
extern int (*leasecomp) (const struct leases_t *restrict a, const struct leases_t *restrict b);
extern int leasecomp_init(const struct leases_t *restrict a
@ -291,46 +347,26 @@ extern int leasecomp_init(const struct leases_t *restrict a
extern int leasecomp_v4(const struct leases_t *restrict a, const struct leases_t *restrict b);
extern int leasecomp_v6(const struct leases_t *restrict a, const struct leases_t *restrict b);
extern int comp_cur(struct range_t *r1, struct range_t *r2) _DP_ATTRIBUTE_PURE;
extern int comp_double(double f1, double f2) _DP_ATTRIBUTE_CONST;
extern int (*ipcomp) (const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
extern int ipcomp_init(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
extern int ipcomp_v4(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
extern int ipcomp_v6(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b);
extern int rangecomp(const void *restrict r1, const void *restrict r2)
__attribute__ ((nonnull(1, 2)));
extern int comp_cur(struct range_t *r1, struct range_t *r2);
extern int comp_double(double f1, double f2);
extern int comp_ip(struct range_t *r1, struct range_t *r2);
extern int comp_max(struct range_t *r1, struct range_t *r2);
extern int comp_percent(struct range_t *r1, struct range_t *r2);
extern int comp_tc(struct range_t *r1, struct range_t *r2) _DP_ATTRIBUTE_PURE;
extern int comp_tc(struct range_t *r1, struct range_t *r2);
extern int comp_tcperc(struct range_t *r1, struct range_t *r2);
extern int comp_touched(struct range_t *r1, struct range_t *r2) _DP_ATTRIBUTE_PURE;
extern int rangecomp(const void *__restrict r1, const void *__restrict r2)
__attribute__ ((nonnull(1, 2)));
/* sort function pointer and functions */
extern int comp_touched(struct range_t *r1, struct range_t *r2);
extern comparer_t field_selector(char c);
extern double ret_percent(struct range_t r);
extern double ret_tc(struct range_t r) _DP_ATTRIBUTE_CONST;
extern double ret_tc(struct range_t r);
extern double ret_tcperc(struct range_t r);
extern void mergesort_ranges(struct range_t *__restrict orig, int size,
struct range_t *__restrict temp)
__attribute__ ((nonnull(1, 3)));
/* output function pointer and functions */
extern int (*output_analysis) (void);
extern int output_txt(void);
extern int output_html(void);
extern int output_xml(void);
extern int output_json(void);
extern int output_csv(void);
extern int output_alarming(void);
/* Memory release, file closing etc */
extern void clean_up(void);
/* Hash functions */
extern void (*add_lease) (union ipaddr_t *ip, enum ltype type);
extern void add_lease_init(union ipaddr_t *ip, enum ltype type) _DP_ATTRIBUTE_CONST;
extern void add_lease_v4(union ipaddr_t *ip, enum ltype type);
extern void add_lease_v6(union ipaddr_t *ip, enum ltype type);
extern struct leases_t *(*find_lease) (union ipaddr_t *ip);
extern struct leases_t *find_lease_init(union ipaddr_t *ip) _DP_ATTRIBUTE_CONST;
extern struct leases_t *find_lease_v4(union ipaddr_t *ip) _DP_ATTRIBUTE_PURE;
extern struct leases_t *find_lease_v6(union ipaddr_t *ip) _DP_ATTRIBUTE_PURE;
extern void delete_lease(struct leases_t *lease);
extern void delete_all_leases(void);
#endif /* DHCPD_POOLS_H */
#endif /* DHCPD_POOLS_H */

View file

@ -43,8 +43,8 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@ -55,88 +55,125 @@
#include "xalloc.h"
#include "dhcpd-pools.h"
#include "defaults.h"
/*! \enum dhcpd_magic_numbers
* \brief MAXLEN is maximum expected line length in dhcpd.conf and
* dhcpd.leases.
*/
enum dhcpd_magic_numbers {
MAXLEN = 1024
};
/*! \enum isc_conf_parser
* \brief Configuration file parsing state flags. The
* is_interesting_config_clause() will return one of these to parse_config().
*/
enum isc_conf_parser {
ITS_NOTHING_INTERESTING,
ITS_A_RANGE_FIRST_IP,
ITS_A_RANGE_SECOND_IP,
ITS_A_SHAREDNET,
ITS_AN_INCLUDE,
ITS_A_SUBNET,
ITS_A_NETMASK
};
/*! \brief Lease file parser. The parser can only read ISC DHCPD
* dhcpd.leases file format. */
int parse_leases(void)
int parse_leases(struct conf_t *state)
{
FILE *dhcpd_leases;
char *line, *ipstring, macstring[20], *stop;
char *line, *ipstring, macstring[20], *stop, endsstr[30], startsstr[30], hostnamestr[MAXLEN];
union ipaddr_t addr;
struct stat lease_file_stats;
bool ethernets = false;
struct leases_t *lease;
dhcpd_leases = fopen(config.dhcpdlease_file, "r");
dhcpd_leases = fopen(state->dhcpdlease_file, "r");
if (dhcpd_leases == NULL)
error(EXIT_FAILURE, errno, "parse_leases: %s", config.dhcpdlease_file);
error(EXIT_FAILURE, errno, "parse_leases: %s", state->dhcpdlease_file);
#ifdef HAVE_POSIX_FADVISE
# ifdef POSIX_FADV_NOREUSE
if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_NOREUSE) != 0)
error(EXIT_FAILURE, errno, "parse_leases: fadvise %s", config.dhcpdlease_file);
# endif /* POSIX_FADV_NOREUSE */
# ifdef POSIX_FADV_SEQUENTIAL
if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL) != 0)
error(EXIT_FAILURE, errno, "parse_leases: fadvise %s", config.dhcpdlease_file);
error(EXIT_FAILURE, errno, "parse_leases: fadvise %s", state->dhcpdlease_file);
# endif /* POSIX_FADV_SEQUENTIAL */
#endif /* HAVE_POSIX_FADVISE */
/* I found out that there's one lease address per 300 bytes in
* dhcpd.leases file. Malloc is little bit pessimistic and uses 250.
* If someone has higher density in lease file I'm interested to
* hear about that. */
if (stat(config.dhcpdlease_file, &lease_file_stats))
error(EXIT_FAILURE, errno, "parse_leases: %s", config.dhcpdlease_file);
line = xmalloc(sizeof(char) * MAXLEN);
line[0] = '\0';
ipstring = xmalloc(sizeof(char) * MAXLEN);
ipstring[0] = '\0';
if (config.print_mac_addreses == 1)
ethernets = true;
endsstr[0] = '\0';
startsstr[0] = '\0';
hostnamestr[0] = '\0';
while (!feof(dhcpd_leases)) {
if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases))
error(EXIT_FAILURE, errno, "parse_leases: %s", config.dhcpdlease_file);
switch (xstrstr(line)) {
error(EXIT_FAILURE, errno, "parse_leases: %s", state->dhcpdlease_file);
switch (xstrstr(state, line)) {
/* It's a lease, save IP */
case PREFIX_LEASE:
stop =
memccpy(ipstring,
line + (config.ip_version ==
line + (state->ip_version ==
IPv4 ? 6 : 9), ' ', strlen(line));
if (stop != NULL) {
--stop;
*stop = '\0';
}
parse_ipaddr(ipstring, &addr);
parse_ipaddr(state, ipstring, &addr);
break;
case PREFIX_BINDING_STATE_FREE:
case PREFIX_BINDING_STATE_ABANDONED:
case PREFIX_BINDING_STATE_EXPIRED:
case PREFIX_BINDING_STATE_RELEASED:
if ((lease = find_lease(&addr)) != NULL)
delete_lease(lease);
add_lease(&addr, FREE);
if ((lease = find_lease(state, &addr)) != NULL)
delete_lease(state, lease);
add_lease(state, &addr, FREE);
break;
case PREFIX_BINDING_STATE_ACTIVE:
/* remove old entry, if exists */
if ((lease = find_lease(&addr)) != NULL)
delete_lease(lease);
add_lease(&addr, ACTIVE);
if ((lease = find_lease(state, &addr)) != NULL)
delete_lease(state, lease);
add_lease(state, &addr, ACTIVE);
break;
case PREFIX_BINDING_STATE_BACKUP:
/* remove old entry, if exists */
if ((lease = find_lease(&addr)) != NULL)
delete_lease(lease);
add_lease(&addr, BACKUP);
config.backups_found = true;
if ((lease = find_lease(state, &addr)) != NULL)
delete_lease(state, lease);
add_lease(state, &addr, BACKUP);
state->backups_found = 1;
break;
case PREFIX_HARDWARE_ETHERNET:
if (ethernets == false)
if (state->print_mac_addreses == 0)
break;
memcpy(macstring, line + 20, 17);
macstring[17] = '\0';
if ((lease = find_lease(&addr)) != NULL)
if ((lease = find_lease(state, &addr)) != NULL) {
lease->ethernet = xstrdup(macstring);
lease->starts = xstrdup(startsstr);
startsstr[0] = '\0';
lease->ends = xstrdup(endsstr);
endsstr[0] = '\0';
}
break;
case PREFIX_ENDS:
if (state->print_mac_addreses == 0)
break;
strncpy(endsstr, line + 7, sizeof(endsstr)-1);
endsstr[strlen(endsstr)-2] = '\0';
break;
case PREFIX_STARTS:
if (state->print_mac_addreses == 0)
break;
strncpy(startsstr, line + 9, sizeof(startsstr)-1);
startsstr[strlen(startsstr)-2] = '\0';
break;
case PREFIX_HOSTNAME:
if (state->print_mac_addreses == 0)
break;
strncpy(hostnamestr, line + 19, sizeof(hostnamestr)-1);
hostnamestr[strlen(hostnamestr)-3] = '\0';
if ((lease = find_lease(state, &addr)) != NULL) {
lease->hostname = xstrdup(hostnamestr);
}
hostnamestr[0] = '\0';
break;
default:
/* do nothing */ ;
@ -152,26 +189,45 @@ int parse_leases(void)
/*! \brief Keyword search in dhcpd.conf file.
* \param s A line from the dhcpd.conf file.
* \return Indicator what configuration was found. */
static int is_interesting_config_clause(char const *restrict s)
static int is_interesting_config_clause(struct conf_t *state, char const *restrict s)
{
if (strstr(s, "range"))
return ITS_A_RANGE_FIRST_IP;
if (strstr(s, "shared-network"))
return ITS_A_SHAREDNET;
if (state->all_as_shared) {
if (strstr(s, "subnet"))
return ITS_A_SUBNET;
if (strstr(s, "netmask"))
return ITS_A_NETMASK;
}
if (strstr(s, "include"))
return ITS_AN_INCLUCE;
return ITS_AN_INCLUDE;
return ITS_NOTHING_INTERESTING;
}
/*! \brief The dhcpd.conf file parser.
* FIXME: This spaghetti monster function need to be rewrote at least
* ones.
/*! \brief Flip first and last IP in range if they are in unusual order.
*/
void parse_config(int is_include, const char *restrict config_file,
static void reorder_last_first(struct range_t *range_p)
{
if (ipcomp(&range_p->first_ip, &range_p->last_ip) > 0) {
union ipaddr_t tmp;
tmp = range_p->first_ip;
range_p->first_ip = range_p->last_ip;
range_p->last_ip = tmp;
}
}
/*! \brief The dhcpd.conf file parser.
* FIXME: This spaghetti monster function needs to be rewrote at least
* ones more.
*/
void parse_config(struct conf_t *state, const int is_include, const char *restrict config_file,
struct shared_network_t *restrict shared_p)
{
FILE *dhcpd_config;
bool newclause = true, comment = false, one_ip_range = false;
int newclause = 1, comment = 0, one_ip_range = 0; /* booleans */
int quote = 0, braces = 0, argument = ITS_NOTHING_INTERESTING;
size_t i = 0;
char *word;
@ -182,16 +238,18 @@ void parse_config(int is_include, const char *restrict config_file,
word = xmalloc(sizeof(char) * MAXLEN);
if (is_include)
/* Default place holder for ranges "All networks". */
shared_p->name = shared_networks->name;
shared_p->name = state->shared_net_root->name;
/* Open configuration file */
dhcpd_config = fopen(config_file, "r");
if (dhcpd_config == NULL)
if (dhcpd_config == NULL) {
if (is_include) {
error(0, errno, "cannot open inlude: %s", config_file);
return;
}
/* config if from command line, just exit with error */
error(EXIT_FAILURE, errno, "parse_config: %s", config_file);
}
#ifdef HAVE_POSIX_FADVISE
# ifdef POSIX_FADV_NOREUSE
if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_NOREUSE) != 0)
error(EXIT_FAILURE, errno, "parse_config: fadvise %s", config_file);
# endif /* POSIX_FADV_NOREUSE */
# ifdef POSIX_FADV_SEQUENTIAL
if (posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_SEQUENTIAL) != 0)
error(EXIT_FAILURE, errno, "parse_config: fadvise %s", config_file);
@ -199,18 +257,20 @@ void parse_config(int is_include, const char *restrict config_file,
#endif /* HAVE_POSIX_FADVISE */
/* Very hairy stuff begins. */
while (unlikely(!feof(dhcpd_config))) {
char c;
int c;
c = fgetc(dhcpd_config);
if (CHAR_MAX < c)
continue;
/* Certain characters are magical */
switch (c) {
/* Handle comments if they are not quoted */
case '#':
if (quote == 0)
comment = true;
comment = 1;
continue;
case '"':
if (comment == false) {
if (comment == 0) {
quote++;
/* Either one or zero */
quote = quote % 2;
@ -220,18 +280,18 @@ void parse_config(int is_include, const char *restrict config_file,
/* New line resets comment section, but
* not if quoted */
if (quote == 0)
comment = false;
comment = 0;
break;
case ';':
/* Quoted colon does not mean new clause */
if (0 < quote)
break;
if (comment == false
if (comment == 0
&& argument != ITS_A_RANGE_FIRST_IP
&& argument != ITS_A_RANGE_SECOND_IP && argument != ITS_AN_INCLUCE) {
newclause = true;
&& argument != ITS_A_RANGE_SECOND_IP && argument != ITS_AN_INCLUDE) {
newclause = 1;
i = 0;
} else if (argument == ITS_A_RANGE_FIRST_IP && one_ip_range == true) {
} else if (argument == ITS_A_RANGE_FIRST_IP && one_ip_range == 1) {
argument = ITS_A_RANGE_SECOND_IP;
c = ' ';
} else if (argument == ITS_A_RANGE_SECOND_IP && 0 < i) {
@ -245,8 +305,9 @@ void parse_config(int is_include, const char *restrict config_file,
break;
} else if (argument == ITS_A_RANGE_SECOND_IP && i == 0) {
if (!range_p) {
puts("parse_config: range_p uninitialized: report a bug");
abort();
long int pos;
pos = ftell(dhcpd_config);
error(EXIT_FAILURE, 0, "parse_config: parsing failed at position: %ld", pos);
}
range_p->last_ip = range_p->first_ip;
goto newrange;
@ -261,123 +322,150 @@ void parse_config(int is_include, const char *restrict config_file,
*
* shared-network DSL{ ... */
if (i == 0) {
newclause = true;
newclause = 1;
continue;
} else
break;
}
break;
case '}':
if (0 < quote)
break;
if (comment == false) {
if (comment == 0) {
braces--;
/* End of shared-network */
if (braces_shared == braces) {
/* FIXME: Using 1000 is lame, but
* works. */
braces_shared = 1000;
shared_p = shared_networks;
shared_p = state->shared_net_root;
}
/* Not literally true, but works for this
/* Not literally 1, but works for this
* program */
newclause = true;
newclause = 1;
}
continue;
default:
break;
}
/* Either inside comment or Nth word of clause. */
if (comment == true || (newclause == false && argument == ITS_NOTHING_INTERESTING))
if (comment == 1 || (newclause == 0 && argument == ITS_NOTHING_INTERESTING))
continue;
/* Strip white spaces before new clause word. */
if ((newclause == true || argument != ITS_NOTHING_INTERESTING)
&& isspace(c) && i == 0 && one_ip_range == false)
if ((newclause == 1 || argument != ITS_NOTHING_INTERESTING)
&& isspace(c) && i == 0 && one_ip_range == 0)
continue;
/* Save to word which clause this is. */
if ((newclause == true || argument != ITS_NOTHING_INTERESTING)
if ((newclause == 1 || argument != ITS_NOTHING_INTERESTING)
&& (!isspace(c) || 0 < quote)) {
word[i] = c;
word[i] = (char) c;
i++;
/* Long word which is almost causing overflow. None
* of words are this long which the program is
* searching. */
if (MAXLEN == i) {
newclause = false;
newclause = 0;
i = 0;
continue;
}
}
/* See if clause is something that parser is looking for. */
else if (newclause == true) {
else if (newclause == 1) {
/* Insert string end & set state */
word[i] = '\0';
if (word[i - 1] != '{')
newclause = false;
newclause = 0;
i = 0;
argument = is_interesting_config_clause(word);
argument = is_interesting_config_clause(state, word);
if (argument == ITS_A_RANGE_FIRST_IP)
one_ip_range = true;
one_ip_range = 1;
}
/* words after range, shared-network or include */
else if (argument != ITS_NOTHING_INTERESTING) {
word[i] = '\0';
newclause = false;
newclause = 0;
i = 0;
switch (argument) {
case ITS_A_RANGE_SECOND_IP:
/* printf ("range 2nd ip: %s\n", word); */
range_p = ranges + num_ranges;
range_p = state->ranges + state->num_ranges;
argument = ITS_NOTHING_INTERESTING;
parse_ipaddr(word, &addr);
if (one_ip_range == true) {
one_ip_range = false;
copy_ipaddr(&range_p->first_ip, &addr);
if (strchr(word, '/')) {
parse_cidr(state, range_p, word);
one_ip_range = 0;
} else {
/* not cidr */
parse_ipaddr(state, word, &addr);
if (one_ip_range == 1) {
one_ip_range = 0;
copy_ipaddr(&range_p->first_ip, &addr);
}
copy_ipaddr(&range_p->last_ip, &addr);
reorder_last_first(range_p);
}
copy_ipaddr(&range_p->last_ip, &addr);
newrange:
range_p->count = 0;
range_p->touched = 0;
range_p->backups = 0;
range_p->shared_net = shared_p;
num_ranges++;
if (RANGES < num_ranges + 1) {
RANGES *= 2;
ranges = xrealloc(ranges, sizeof(struct range_t) * RANGES);
range_p = ranges + num_ranges;
state->num_ranges++;
if (state->ranges_size <= state->num_ranges) {
state->ranges_size *= 2;
state->ranges = xrealloc(state->ranges, sizeof(struct range_t) * state->ranges_size);
range_p = state->ranges + state->num_ranges;
}
newclause = true;
newclause = 1;
break;
case ITS_A_RANGE_FIRST_IP:
/* printf ("range 1nd ip: %s\n", word); */
range_p = ranges + num_ranges;
if (!(parse_ipaddr(word, &addr)))
/* printf ("range 1st ip: %s\n", word); */
range_p = state->ranges + state->num_ranges;
if (!(parse_ipaddr(state, word, &addr)))
/* word was not ip, try again */
break;
copy_ipaddr(&range_p->first_ip, &addr);
one_ip_range = false;
one_ip_range = 0;
argument = ITS_A_RANGE_SECOND_IP;
break;
case ITS_A_SHAREDNET:
/* printf ("shared-network named: %s\n", word); */
num_shared_networks++;
shared_p = shared_networks + num_shared_networks;
case ITS_A_SUBNET:
/* ignore subnets inside a shared-network */
if (argument == ITS_A_SUBNET && shared_p != state->shared_net_root) {
argument = ITS_NOTHING_INTERESTING;
break;
}
state->shared_net_head->next = xcalloc(sizeof(struct shared_network_t), 1);
state->shared_net_head = state->shared_net_head->next;
shared_p = state->shared_net_head;
shared_p->name = xstrdup(word);
shared_p->available = 0;
shared_p->used = 0;
shared_p->touched = 0;
shared_p->backups = 0;
if (SHARED_NETWORKS < num_shared_networks + 2)
/* FIXME: make this to go away by reallocating more space. */
error(EXIT_FAILURE, 0,
"parse_config: increase default.h SHARED_NETWORKS and recompile");
shared_p->netmask = (argument == ITS_A_SUBNET ? -1 : 0); /* do not fill in netmask */
/* record network's mask too */
if (argument == ITS_A_SUBNET)
newclause = 1;
argument = ITS_NOTHING_INTERESTING;
braces_shared = braces;
break;
case ITS_AN_INCLUCE:
case ITS_A_NETMASK:
/* fill in only when requested to do so */
if (shared_p->netmask) {
if (!(parse_ipaddr(state, word, &addr)))
break;
shared_p->netmask = 32;
while ((addr.v4 & 0x01) == 0) {
addr.v4 >>= 1;
shared_p->netmask--;
}
snprintf(word, MAXLEN-1, "%s/%d", shared_p->name, shared_p->netmask);
if (shared_p->name)
free(shared_p->name);
shared_p->name = xstrdup(word);
}
argument = ITS_NOTHING_INTERESTING;
braces_shared = braces;
break;
case ITS_AN_INCLUDE:
/* printf ("include file: %s\n", word); */
argument = ITS_NOTHING_INTERESTING;
parse_config(false, word, shared_p);
newclause = true;
parse_config(state, 0, word, shared_p);
newclause = 1;
break;
case ITS_NOTHING_INTERESTING:
/* printf ("nothing interesting: %s\n", word); */

View file

@ -40,6 +40,8 @@
#include <config.h>
#include <stdlib.h>
#include "xalloc.h"
#include "dhcpd-pools.h"
@ -50,88 +52,104 @@
/*! \brief Add a lease to hash array.
* \param addr Binary IP to be added in leases hash.
* \param type Lease state of the IP. */
void add_lease_init(union ipaddr_t *addr
void add_lease_init(struct conf_t *state __attribute__ ((unused)), union ipaddr_t *addr
__attribute__ ((unused)), enum ltype type __attribute__ ((unused)))
{
}
void add_lease_v4(union ipaddr_t *addr, enum ltype type)
void add_lease_v4(struct conf_t *state, union ipaddr_t *addr, enum ltype type)
{
struct leases_t *l;
l = xmalloc(sizeof(struct leases_t));
copy_ipaddr(&l->ip, addr);
l->type = type;
HASH_ADD_INT(leases, ip.v4, l);
HASH_ADD_INT(state->leases, ip.v4, l);
l->ethernet = NULL;
l->ends = NULL;
l->starts = NULL;
l->hostname = NULL;
}
void add_lease_v6(union ipaddr_t *addr, enum ltype type)
void add_lease_v6(struct conf_t *state, union ipaddr_t *addr, enum ltype type)
{
struct leases_t *l;
l = xmalloc(sizeof(struct leases_t));
copy_ipaddr(&l->ip, addr);
l->type = type;
HASH_ADD_V6(leases, ip.v6, l);
HASH_ADD_V6(state->leases, ip.v6, l);
l->ethernet = NULL;
l->ends = NULL;
l->starts = NULL;
l->hostname = NULL;
}
/*! \brief Find pointer to lease from hash array.
* \param addr Binary IP searched from leases hash.
* \return A lease structure about requested IP, or NULL.
*/
struct leases_t *find_lease_init(union ipaddr_t *addr __attribute__ ((unused)))
struct leases_t *find_lease_init(struct conf_t *state __attribute__ ((unused)), union ipaddr_t *addr
__attribute__ ((unused)))
{
return NULL;
}
struct leases_t *find_lease_v4(union ipaddr_t *addr)
struct leases_t *find_lease_v4(struct conf_t *state, union ipaddr_t *addr)
{
struct leases_t *l;
HASH_FIND_INT(leases, &addr->v4, l);
HASH_FIND_INT(state->leases, &addr->v4, l);
return l;
}
struct leases_t *find_lease_v6(union ipaddr_t *addr)
struct leases_t *find_lease_v6(struct conf_t *state, union ipaddr_t *addr)
{
struct leases_t *l;
HASH_FIND_V6(leases, &addr->v4, l);
HASH_FIND_V6(state->leases, &addr->v4, l);
return l;
}
/*! \brief Delete a lease from hash array.
* \param lease Pointer to lease hash. */
void delete_lease(struct leases_t *lease)
void delete_lease(struct conf_t *state, struct leases_t *lease)
{
free(lease->ethernet);
HASH_DEL(leases, lease);
free(lease->ends);
free(lease->starts);
free(lease->hostname);
HASH_DEL(state->leases, lease);
free(lease);
}
/*! \brief Delete all leases from hash array. */
#ifdef HASH_ITER
void delete_all_leases(void)
void delete_all_leases(struct conf_t *state)
{
struct leases_t *l, *tmp;
HASH_ITER(hh, leases, l, tmp) {
HASH_ITER(hh, state->leases, l, tmp) {
free(l->ethernet);
HASH_DEL(leases, l);
free(l->ends);
free(l->starts);
free(l->hostname);
HASH_DEL(state->leases, l);
free(l);
}
}
#else
void delete_all_leases(void)
void delete_all_leases(struct conf_t *state)
{
while (leases) {
while (state->leases) {
struct leases_t *l;
l = leases;
l = state->leases;
free(l->ethernet);
HASH_DEL(leases, l); /* leases advances to next on delete */
free(l->ends);
free(l->starts);
free(l->hostname);
HASH_DEL(state->leases, l); /* leases advances to next on delete */
free(l);
}
}

519
src/mustach-dhcpd-pools.c Normal file
View file

@ -0,0 +1,519 @@
/*
* 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 mustach-dhcpd-pools.c
* \brief Mustache templating specific functions.
*/
#include <config.h>
#include <fcntl.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include "close-stream.h"
#include "dhcpd-pools.h"
#include "error.h"
#include "mustach.h"
#include "xalloc.h"
/*! \struct expl
* \brief A structure that travels through mustach via closure void pointer.
*/
struct expl {
struct conf_t *state;
struct leases_t *lease_p;
struct range_t *range_p;
struct shared_network_t *shnet_p;
struct output_helper_t oh;
int current;
uint32_t pad;
};
static int must_enter(void *closure, const char *name);
static int must_leave(void *closure);
/*! \brief Template base level tag parser and printer. */
static int must_put_base(void *closure, const char *name, int escape
__attribute__ ((unused)), FILE *file)
{
struct expl *e = closure;
if (!strcmp(name, "localtime")) {
dp_time_tool(file, NULL, 0);
return 0;
}
if (!strcmp(name, "number_of_ranges")) {
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")) {
uint32_t num = 0;
struct shared_network_t *shared_p;
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;
}
/* lease file */
if (!strcmp(name, "lease_file_path")) {
fprintf(file, "%s", e->state->dhcpdlease_file);
return 0;
}
if (!strcmp(name, "lease_file_local_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 0);
return 0;
}
if (!strcmp(name, "lease_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 1);
return 0;
}
/* conf file */
if (!strcmp(name, "conf_file_path")) {
fprintf(file, "%s", e->state->dhcpdconf_file);
return 0;
}
if (!strcmp(name, "conf_file_local_mtime")) {
dp_time_tool(file, e->state->dhcpdconf_file, 0);
return 0;
}
if (!strcmp(name, "conf_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdconf_file, 1);
return 0;
}
/* template file */
if (!strcmp(name, "template_file_path")) {
fprintf(file, "%s", e->state->mustach_template);
return 0;
}
if (!strcmp(name, "template_file_local_mtime")) {
dp_time_tool(file, e->state->mustach_template, 0);
return 0;
}
if (!strcmp(name, "template_file_epoch_mtime")) {
dp_time_tool(file, e->state->mustach_template, 1);
return 0;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
}
/*! \struct mustach_itf
* \brief Mustach function pointers. */
static struct mustach_itf itf = {
.start = NULL,
.enter = must_enter,
.put = must_put_base,
.next = NULL,
.leave = must_leave
};
/*! \brief Mustach active lease aka {{#active_lease}} tag parser and printer. */
static int must_put_active_lease(void *closure, const char *name, int escape
__attribute__((unused)), FILE *file)
{
struct expl *e = closure;
if (!strcmp(name, "ip")) {
fprintf(file, "%s", ntop_ipaddr(&e->lease_p->ip));
return 0;
}
if (!strcmp(name, "macaddress")) {
fprintf(file, "%s", e->lease_p->ethernet);
return 0;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
}
/*! \brief A function to move to next lease when {{/active_lease}} is encountered. */
static int must_next_active_lease(void *closure)
{
struct expl *e = closure;
e->lease_p = e->lease_p->hh.next;
if (e->lease_p == NULL)
return 0;
return 1;
}
/*! \brief Mustach range aka {{#subnets}} tag parser and printer. */
static int must_put_range(void *closure, const char *name, int escape
__attribute__ ((unused)), FILE *file)
{
struct expl *e = closure;
if (!strcmp(name, "location")) {
fprintf(file, "%s", e->range_p->shared_net->name);
return 0;
}
if (!strcmp(name, "range")) {
fprintf(file, "%s - ", ntop_ipaddr(&e->range_p->first_ip));
fprintf(file, "%s", ntop_ipaddr(&e->range_p->last_ip));
return 0;
}
if (!strcmp(name, "first_ip")) {
fprintf(file, "%s", ntop_ipaddr(&e->range_p->first_ip));
return 0;
}
if (!strcmp(name, "last_ip")) {
fprintf(file, "%s", ntop_ipaddr(&e->range_p->last_ip));
return 0;
}
if (!strcmp(name, "used")) {
fprintf(file, "%g", e->range_p->count);
return 0;
}
if (!strcmp(name, "touched")) {
fprintf(file, "%g", e->range_p->touched);
return 0;
}
if (!strcmp(name, "defined")) {
fprintf(file, "%g", e->oh.range_size);
return 0;
}
if (!strcmp(name, "free")) {
fprintf(file, "%g", e->oh.range_size - e->range_p->count);
return 0;
}
if (!strcmp(name, "percent")) {
fprintf(file, "%g", e->oh.percent);
return 0;
}
if (!strcmp(name, "touch_count")) {
fprintf(file, "%g", e->oh.tc);
return 0;
}
if (!strcmp(name, "touch_percent")) {
fprintf(file, "%g", e->oh.tcp);
return 0;
}
if (e->state->backups_found == 1) {
if (!strcmp(name, "backup_count")) {
fprintf(file, "%g", e->range_p->backups);
return 0;
}
if (!strcmp(name, "backup_percent")) {
fprintf(file, "%g", e->oh.bup);
return 0;
}
}
if (!strcmp(name, "status")) {
fprintf(file, "%d", e->oh.status);
return 0;
}
if (!strcmp(name, "gettimeofday")) {
dp_time_tool(file, NULL, 1);
return 0;
}
if (!strcmp(name, "lease_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 1);
return 0;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
}
/*! \brief Mustach shared networks aka {{#shared-networks}} tag parser and printer. */
static int must_put_shnet(void *closure, const char *name, int escape
__attribute__ ((unused)), FILE *file)
{
struct expl *e = closure;
if (!strcmp(name, "location")) {
fprintf(file, "%s", e->shnet_p->name);
return 0;
}
if (!strcmp(name, "defined")) {
fprintf(file, "%g", e->shnet_p->available);
return 0;
}
if (!strcmp(name, "used")) {
fprintf(file, "%g", e->shnet_p->used);
return 0;
}
if (!strcmp(name, "touched")) {
fprintf(file, "%g", e->shnet_p->touched);
return 0;
}
if (!strcmp(name, "free")) {
fprintf(file, "%g", e->shnet_p->available - e->shnet_p->used);
return 0;
}
if (!strcmp(name, "percent")) {
fprintf(file, "%g", e->oh.percent);
return 0;
}
if (!strcmp(name, "touch_count")) {
fprintf(file, "%g", e->oh.tc);
return 0;
}
if (!strcmp(name, "touch_percent")) {
fprintf(file, "%g", e->oh.tcp);
return 0;
}
if (e->state->backups_found == 1) {
if (!strcmp(name, "backup_count")) {
fprintf(file, "%g", e->shnet_p->backups);
return 0;
}
if (!strcmp(name, "backup_percent")) {
fprintf(file, "%g", e->oh.bup);
return 0;
}
}
if (!strcmp(name, "status")) {
fprintf(file, "%d", e->oh.status);
return 0;
}
if (!strcmp(name, "gettimeofday")) {
dp_time_tool(file, NULL, 1);
return 0;
}
if (!strcmp(name, "lease_file_epoch_mtime")) {
dp_time_tool(file, e->state->dhcpdlease_file, 1);
return 0;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
}
/*! \brief A function to move to next range when {{/subnets}} is encountered. */
static int must_next_range(void *closure)
{
struct expl *e = closure;
do {
e->range_p++;
e->current--;
if (e->current <= 0)
return 0;
} while (range_output_helper(e->state, &e->oh, e->range_p));
return 1;
}
/*! \brief A function to move to next shared network when {{/shared-networks}}
* is encountered. */
static int must_next_shnet(void *closure)
{
struct expl *e = closure;
if (e->current == 1 || e->shnet_p == NULL)
return 0;
while (1) {
e->shnet_p = e->shnet_p->next;
if (e->shnet_p == NULL)
break;
if (shnet_output_helper(e->state, &e->oh, e->shnet_p))
continue;
else
return 1;
}
return 0;
}
/*! \brief Function that is called when mustach is searching output loops from
* template file. */
static int must_enter(void *closure, const char *name)
{
struct expl *e = closure;
if (!strcmp(name, "active_lease")) {
itf.put = must_put_active_lease;
itf.next = must_next_active_lease;
e->current = 0;
e->lease_p = e->state->leases;
return must_next_active_lease(closure);
}
if (!strcmp(name, "subnets")) {
itf.put = must_put_range;
itf.next = must_next_range;
e->current = e->state->num_ranges + 1;
e->range_p = e->state->ranges;
/* must_next_range() will skip_ok when needed */
e->range_p--;
return must_next_range(closure);
}
if (!strcmp(name, "shared-networks")) {
itf.put = must_put_shnet;
itf.next = must_next_shnet;
e->shnet_p = e->state->shared_net_root;
e->current = 0;
return must_next_shnet(closure);
}
if (!strcmp(name, "summary")) {
itf.put = must_put_shnet;
itf.next = must_next_shnet;
e->shnet_p = e->state->shared_net_root;
e->current = 1;
shnet_output_helper(e->state, &e->oh, e->shnet_p);
return 1;
}
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name);
return 1;
}
/*! \brief Function that is called when all elements within a print loop are outputted. */
static int must_leave(void *closure)
{
struct expl *e = closure;
e->shnet_p = e->state->shared_net_root;
e->range_p = e->state->ranges;
itf.put = must_put_base;
return 0;
}
/*! \brief Read mustach template to memory. */
static char *must_read_template(const char *filename)
{
int f;
struct stat s;
char *result;
if (filename == NULL)
error(EXIT_FAILURE, 0, "must_read_template: --mustach argument missing");
if ((f = open(filename, O_RDONLY)) < 0) {
error(EXIT_FAILURE, errno, "must_read_template: open: %s", filename);
}
fstat(f, &s);
result = xmalloc(s.st_size + 1);
if (read(f, result, s.st_size) != s.st_size) {
error(EXIT_FAILURE, errno, "must_read_template: read: %s", filename);
}
close(f);
result[s.st_size] = 0;
return result;
}
/*! \brief Start mustach processing. */
int mustach_dhcpd_pools(struct conf_t *state)
{
struct expl e = { .state = state };
char *template;
FILE *outfile;
int ret;
template = must_read_template(state->mustach_template);
if (state->output_file) {
outfile = fopen(state->output_file, "w+");
if (outfile == NULL) {
error(EXIT_FAILURE, errno, "mustach_dhcpd_pools: fopen: %s",
state->output_file);
}
} else {
outfile = stdout;
}
ret = fmustach(template, &itf, &e, outfile);
free(template);
if (outfile == stdout) {
if (fflush(stdout))
error(EXIT_FAILURE, errno, "mustach_dhcpd_pools: fflush");
} else {
if (close_stream(outfile))
error(EXIT_FAILURE, errno, "mustach_dhcpd_pools: fclose");
}
switch (ret) {
case MUSTACH_OK:
return 0;
case MUSTACH_ERROR_SYSTEM:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: system error");
break;
case MUSTACH_ERROR_UNEXPECTED_END:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected end");
break;
case MUSTACH_ERROR_EMPTY_TAG:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: empty tag");
break;
case MUSTACH_ERROR_TAG_TOO_LONG:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: too long tag");
break;
case MUSTACH_ERROR_BAD_SEPARATORS:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: bad separator");
break;
case MUSTACH_ERROR_TOO_DEEP:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: too deep");
break;
case MUSTACH_ERROR_CLOSING:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: closing");
break;
case MUSTACH_ERROR_BAD_UNESCAPE_TAG:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: bad escape tag");
break;
default:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unknown error");
}
return 1;
}

325
src/mustach.c Normal file
View file

@ -0,0 +1,325 @@
/*
Author: José Bollo <jobol@nonadev.net>
Author: José Bollo <jose.bollo@iot.bzh>
https://gitlab.com/jobol/mustach
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define _GNU_SOURCE
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "mustach.h"
#define NAME_LENGTH_MAX 1024
#define DEPTH_MAX 256
#if !defined(NO_OPEN_MEMSTREAM)
static FILE *memfile_open(char **buffer, size_t *size)
{
return open_memstream(buffer, size);
}
static void memfile_abort(FILE *file, char **buffer, size_t *size)
{
fclose(file);
free(*buffer);
*buffer = NULL;
*size = 0;
}
static int memfile_close(FILE *file, char **buffer, size_t *size)
{
int rc;
/* adds terminating null */
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0;
fclose(file);
if (rc == 0)
/* removes terminating null of the length */
(*size)--;
else {
free(*buffer);
*buffer = NULL;
*size = 0;
}
return rc;
}
#else
static FILE *memfile_open(char **buffer, size_t *size)
{
return tmpfile();
}
static void memfile_abort(FILE *file, char **buffer, size_t *size)
{
fclose(file);
*buffer = NULL;
*size = 0;
}
static int memfile_close(FILE *file, char **buffer, size_t *size)
{
int rc;
size_t s;
char *b;
s = (size_t)ftell(file);
b = malloc(s + 1);
if (b == NULL) {
rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
s = 0;
} else {
rewind(file);
if (1 == fread(b, s, 1, file)) {
rc = 0;
b[s] = 0;
} else {
rc = MUSTACH_ERROR_SYSTEM;
free(b);
b = NULL;
s = 0;
}
}
*buffer = b;
*size = s;
return rc;
}
#endif
static int getpartial(struct mustach_itf *itf, void *closure, const char *name, char **result)
{
int rc;
FILE *file;
size_t size;
*result = NULL;
file = memfile_open(result, &size);
if (file == NULL)
rc = MUSTACH_ERROR_SYSTEM;
else {
rc = itf->put(closure, name, 0, file);
if (rc < 0)
memfile_abort(file, result, &size);
else
rc = memfile_close(file, result, &size);
}
return rc;
}
static int process(const char *template, struct mustach_itf *itf, void *closure, FILE *file, const char *opstr, const char *clstr)
{
char name[NAME_LENGTH_MAX + 1], *partial, c, *tmp;
const char *beg, *term;
struct { const char *name, *again; size_t length; int emit, entered; } stack[DEPTH_MAX];
size_t oplen, cllen, len, l;
int depth, rc, emit;
emit = 1;
oplen = strlen(opstr);
cllen = strlen(clstr);
depth = 0;
for(;;) {
beg = strstr(template, opstr);
if (beg == NULL) {
/* no more mustach */
if (emit)
fwrite(template, strlen(template), 1, file);
return depth ? MUSTACH_ERROR_UNEXPECTED_END : 0;
}
if (emit)
fwrite(template, (size_t)(beg - template), 1, file);
beg += oplen;
term = strstr(beg, clstr);
if (term == NULL)
return MUSTACH_ERROR_UNEXPECTED_END;
template = term + cllen;
len = (size_t)(term - beg);
c = *beg;
switch(c) {
case '!':
case '=':
break;
case '{':
for (l = 0 ; clstr[l] == '}' ; l++);
if (clstr[l]) {
if (!len || beg[len-1] != '}')
return MUSTACH_ERROR_BAD_UNESCAPE_TAG;
len--;
} else {
if (term[l] != '}')
return MUSTACH_ERROR_BAD_UNESCAPE_TAG;
template++;
}
c = '&';
/*@fallthrough@*/
case '^':
case '#':
case '/':
case '&':
case '>':
#if !defined(NO_EXTENSION_FOR_MUSTACH) && !defined(NO_COLON_EXTENSION_FOR_MUSTACH)
case ':':
#endif
beg++; len--;
default:
while (len && isspace(beg[0])) { beg++; len--; }
while (len && isspace(beg[len-1])) len--;
#if defined(NO_EXTENSION_FOR_MUSTACH) || defined(NO_ALLOW_EMPTY_TAG)
if (len == 0)
return MUSTACH_ERROR_EMPTY_TAG;
#endif
if (len > NAME_LENGTH_MAX)
return MUSTACH_ERROR_TAG_TOO_LONG;
memcpy(name, beg, len);
name[len] = 0;
break;
}
switch(c) {
case '!':
/* comment */
/* nothing to do */
break;
case '=':
/* defines separators */
if (len < 5 || beg[len - 1] != '=')
return MUSTACH_ERROR_BAD_SEPARATORS;
beg++;
len -= 2;
for (l = 0; l < len && !isspace(beg[l]) ; l++);
if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS;
oplen = l;
tmp = alloca(oplen + 1);
memcpy(tmp, beg, oplen);
tmp[oplen] = 0;
opstr = tmp;
while (l < len && isspace(beg[l])) l++;
if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS;
cllen = len - l;
tmp = alloca(cllen + 1);
memcpy(tmp, beg + l, cllen);
tmp[cllen] = 0;
clstr = tmp;
break;
case '^':
case '#':
/* begin section */
if (depth == DEPTH_MAX)
return MUSTACH_ERROR_TOO_DEEP;
rc = emit;
if (rc) {
rc = itf->enter(closure, name);
if (rc < 0)
return rc;
}
stack[depth].name = beg;
stack[depth].again = template;
stack[depth].length = len;
stack[depth].emit = emit;
stack[depth].entered = rc;
if ((c == '#') == (rc == 0))
emit = 0;
depth++;
break;
case '/':
/* end section */
if (depth-- == 0 || len != stack[depth].length || memcmp(stack[depth].name, name, len))
return MUSTACH_ERROR_CLOSING;
rc = emit && stack[depth].entered ? itf->next(closure) : 0;
if (rc < 0)
return rc;
if (rc) {
template = stack[depth++].again;
} else {
emit = stack[depth].emit;
if (emit && stack[depth].entered)
itf->leave(closure);
}
break;
case '>':
/* partials */
if (emit) {
rc = getpartial(itf, closure, name, &partial);
if (rc == 0) {
rc = process(partial, itf, closure, file, opstr, clstr);
free(partial);
}
if (rc < 0)
return rc;
}
break;
default:
/* replacement */
if (emit) {
rc = itf->put(closure, name, c != '&', file);
if (rc < 0)
return rc;
}
break;
}
}
}
int fmustach(const char *template, struct mustach_itf *itf, void *closure, FILE *file)
{
int rc = itf->start ? itf->start(closure) : 0;
if (rc == 0)
rc = process(template, itf, closure, file, "{{", "}}");
return rc;
}
int fdmustach(const char *template, struct mustach_itf *itf, void *closure, int fd)
{
int rc;
FILE *file;
file = fdopen(fd, "w");
if (file == NULL) {
rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
} else {
rc = fmustach(template, itf, closure, file);
fclose(file);
}
return rc;
}
int mustach(const char *template, struct mustach_itf *itf, void *closure, char **result, size_t *size)
{
int rc;
FILE *file;
size_t s;
*result = NULL;
if (size == NULL)
size = &s;
file = memfile_open(result, size);
if (file == NULL)
rc = MUSTACH_ERROR_SYSTEM;
else {
rc = fmustach(template, itf, closure, file);
if (rc < 0)
memfile_abort(file, result, size);
else
rc = memfile_close(file, result, size);
}
return rc;
}

120
src/mustach.h Normal file
View file

@ -0,0 +1,120 @@
/*
Author: José Bollo <jobol@nonadev.net>
Author: José Bollo <jose.bollo@iot.bzh>
https://gitlab.com/jobol/mustach
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _mustach_h_included_
#define _mustach_h_included_
/**
* mustach_itf - interface for callbacks
*
* All of this function should return a negative value to stop
* the mustache processing. The returned negative value will be
* then returned to the caller of mustach as is.
*
* The functions enter and next should return 0 or 1.
*
* All other functions should normally return 0. If it returns
* a negative value, it means an error that stop the process
* and that is reported to the caller.
*
* @start: Starts the mustach processing of the closure
* 'start' is optional (can be NULL)
*
* @put: Writes the value of 'name' to 'file' with 'escape' or not
* As an extension (see NO_ALLOW_EMPTY_TAG), the 'name' can be
* the empty string. In that later case an implemntation can
* return MUSTACH_ERROR_EMPTY_TAG to refuse empty names.
*
* @enter: Enters the section of 'name' if possible.
* Musts return 1 if entered or 0 if not entered.
* When 1 is returned, the function 'leave' will always be called.
* Conversely 'leave' is never called when enter returns 0 or
* a negative value.
* When 1 is returned, the function must activate the first
* item of the section.
*
* @next: Activates the next item of the section if it exists.
* Musts return 1 when the next item is activated.
* Musts return 0 when there is no item to activate.
*
* @leave: Leaves the last entered section
*/
struct mustach_itf {
int (*start)(void *closure);
int (*put)(void *closure, const char *name, int escape, FILE *file);
int (*enter)(void *closure, const char *name);
int (*next)(void *closure);
int (*leave)(void *closure);
};
#define MUSTACH_OK 0
#define MUSTACH_ERROR_SYSTEM -1
#define MUSTACH_ERROR_UNEXPECTED_END -2
#define MUSTACH_ERROR_EMPTY_TAG -3
#define MUSTACH_ERROR_TAG_TOO_LONG -4
#define MUSTACH_ERROR_BAD_SEPARATORS -5
#define MUSTACH_ERROR_TOO_DEEP -6
#define MUSTACH_ERROR_CLOSING -7
#define MUSTACH_ERROR_BAD_UNESCAPE_TAG -8
/* compatibility with older bad name */
#define MUSTACH_ERROR_TOO_DEPTH MUSTACH_ERROR_TOO_DEEP
/**
* fmustach - Renders the mustache 'template' in 'file' for 'itf' and 'closure'.
*
* @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called
* @file: the file where to write the result
*
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
extern int fmustach(const char *template, struct mustach_itf *itf, void *closure, FILE *file);
/**
* fmustach - Renders the mustache 'template' in 'fd' for 'itf' and 'closure'.
*
* @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called
* @fd: the file descriptor number where to write the result
*
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
extern int fdmustach(const char *template, struct mustach_itf *itf, void *closure, int fd);
/**
* fmustach - Renders the mustache 'template' in 'result' for 'itf' and 'closure'.
*
* @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called
* @result: the pointer receiving the result when 0 is returned
* @size: the size of the returned result
*
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
extern int mustach(const char *template, struct mustach_itf *itf, void *closure, char **result, size_t *size);
#endif

View file

@ -47,24 +47,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "error.h"
#include "progname.h"
#include "quote.h"
#include "xalloc.h"
#include "dhcpd-pools.h"
#include "defaults.h"
static char *(*cidr_last) (union ipaddr_t *restrict addr, const int mask);
static char *cidr_last_v4(union ipaddr_t *restrict addr, const int mask);
static char *cidr_last_v6(union ipaddr_t *restrict addr, const int mask);
/*! \brief Set function pointers depending on IP version.
* \param ip IP version.
*/
void set_ipv_functions(int version)
void set_ipv_functions(struct conf_t *state, int version)
{
switch (version) {
case IPv4:
config.ip_version = version;
state->ip_version = version;
add_lease = add_lease_v4;
copy_ipaddr = copy_ipaddr_v4;
find_lease = find_lease_v4;
@ -73,11 +79,12 @@ void set_ipv_functions(int version)
leasecomp = leasecomp_v4;
ntop_ipaddr = ntop_ipaddr_v4;
parse_ipaddr = parse_ipaddr_v4;
cidr_last = cidr_last_v4;
xstrstr = xstrstr_v4;
break;
case IPv6:
config.ip_version = version;
state->ip_version = version;
add_lease = add_lease_v6;
copy_ipaddr = copy_ipaddr_v6;
find_lease = find_lease_v6;
@ -86,11 +93,12 @@ void set_ipv_functions(int version)
leasecomp = leasecomp_v6;
ntop_ipaddr = ntop_ipaddr_v6;
parse_ipaddr = parse_ipaddr_v6;
cidr_last = cidr_last_v6;
xstrstr = xstrstr_v6;
break;
case IPvUNKNOWN:
config.ip_version = version;
state->ip_version = version;
add_lease = add_lease_init;
copy_ipaddr = copy_ipaddr_init;
find_lease = find_lease_init;
@ -99,6 +107,7 @@ void set_ipv_functions(int version)
leasecomp = leasecomp_init;
ntop_ipaddr = ntop_ipaddr_init;
parse_ipaddr = parse_ipaddr_init;
cidr_last = NULL;
xstrstr = xstrstr_init;
break;
@ -114,21 +123,23 @@ void set_ipv_functions(int version)
* \param dst An union which will hold conversion result.
* \return Was parsing successful.
*/
int parse_ipaddr_init(const char *restrict src, union ipaddr_t *restrict dst)
int parse_ipaddr_init(struct conf_t *state, const char *restrict src, union ipaddr_t *restrict dst)
{
struct in_addr addr;
struct in6_addr addr6;
if (inet_aton(src, &addr) == 1)
set_ipv_functions(IPv4);
set_ipv_functions(state, IPv4);
else if (inet_pton(AF_INET6, src, &addr6) == 1)
set_ipv_functions(IPv6);
set_ipv_functions(state, IPv6);
else
return 0;
return parse_ipaddr(src, dst);
return parse_ipaddr(state, src, dst);
}
int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst)
int parse_ipaddr_v4(struct conf_t *state
__attribute__ ((unused)), const char *restrict src,
union ipaddr_t *restrict dst)
{
int rv;
struct in_addr addr;
@ -138,7 +149,9 @@ int parse_ipaddr_v4(const char *restrict src, union ipaddr_t *restrict dst)
return rv == 1;
}
int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst)
int parse_ipaddr_v6(struct conf_t *state
__attribute__ ((unused)), const char *restrict src,
union ipaddr_t *restrict dst)
{
int rv;
struct in6_addr addr;
@ -148,6 +161,107 @@ int parse_ipaddr_v6(const char *restrict src, union ipaddr_t *restrict dst)
return rv == 1;
}
/*! \brief Convert string to a desimal format network marks.
* \param src Digit that should be a network mask.
* \return Network mask, or -1 when failing.
*/
static int strtol_mask(const char *str)
{
long num;
char *end = NULL;
errno = 0;
if (str == NULL || *str == '\0')
goto err;
num = strtol(str, &end, 10);
if (errno || str == end || (end && *end))
goto err;
if (num < 0 || 128 < num)
goto err;
return (int)num;
err:
return -1;
}
/*! \brief Find last address in IPv4 range by using cidr format.
* \param addr Pointer to memory where address needs to be stored.
* \return Allocated string format of the address.
*/
static char *cidr_last_v4(union ipaddr_t *restrict addr, const int mask)
{
union ipaddr_t last_ip;
uint32_t netmask;
const char *ip;
if (mask)
netmask = (1U << (32 - mask)) - 1;
else
netmask = 0;
last_ip.v4 = addr->v4 | netmask;
ip = ntop_ipaddr(&last_ip);
return xstrdup(ip);
}
/*! \brief Find last address in IPv6 range by using cidr format.
* \param addr Pointer to memory where address needs to be stored.
* \return Allocated string format of the address.
*/
static char *cidr_last_v6(union ipaddr_t *restrict addr, const int mask)
{
union ipaddr_t bitmask;
int i, j;
char ip[128];
memset(&bitmask, 0x0, sizeof(bitmask));
for (i = mask, j = 0; i > 0; i -= 8, j++) {
if (i >= 8)
bitmask.v6[j] = 0xff;
else
bitmask.v6[j] = (unsigned char)(0xffU << (8 - i));
}
for (i = 0; i < (int)sizeof(bitmask); i++)
addr->v6[i] |= ~bitmask.v6[i];
inet_ntop(AF_INET6, addr, ip, sizeof(ip));
return xstrdup(ip);
}
/*! \brief Convert a cidr notated address to a range.
* \param range_p Pointer to memory where addresses need to be stored.
* \param word A range as a cidr string.
*/
void parse_cidr(struct conf_t *state, struct range_t *range_p, const char *word)
{
char *divider;
int mask;
union ipaddr_t addr;
char *last;
/* determine cidr */
divider = strchr(word, '/');
*divider++ = '\0';
mask = strtol_mask(divider);
if (mask < 0)
error(EXIT_FAILURE, 0, "cidr %s invalid mask %s", word, divider);
if (state->ip_version == IPvUNKNOWN) {
if (!strchr(word, ':'))
set_ipv_functions(state, IPv4);
else
set_ipv_functions(state, IPv6);
}
/* start of the range is easy */
parse_ipaddr(state, word, &addr);
copy_ipaddr(&range_p->first_ip, &addr);
/* end of the range depends cidr size */
last = cidr_last(&addr, mask);
parse_ipaddr(state, last, &addr);
copy_ipaddr(&range_p->last_ip, &addr);
free(last);
}
/*! \brief Copy IP address to union.
*
* \param dst Destination for a binary IP address.
@ -184,7 +298,7 @@ const char *ntop_ipaddr_init(const union ipaddr_t *ip __attribute__ ((unused)))
const char *ntop_ipaddr_v4(const union ipaddr_t *ip)
{
static char buffer[sizeof("255.255.255.255")];
static char buffer[INET_ADDRSTRLEN];
struct in_addr addr;
addr.s_addr = htonl(ip->v4);
@ -193,7 +307,7 @@ const char *ntop_ipaddr_v4(const union ipaddr_t *ip)
const char *ntop_ipaddr_v6(const union ipaddr_t *ip)
{
static char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
static char buffer[INET6_ADDRSTRLEN];
struct in6_addr addr;
memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr));
@ -238,17 +352,14 @@ double get_range_size_v6(const struct range_t *r)
* \param str A line from dhcpd.conf
* \return prefix_t enum value
*/
int
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
__attribute__ ((hot))
#endif
xstrstr_init(const char *restrict str)
int xstrstr_init(struct conf_t *state, const char *restrict str)
{
if (memcmp("lease ", str, 6)) {
set_ipv_functions(IPv4);
if (!memcmp("lease ", str, 6)) {
set_ipv_functions(state, IPv4);
return PREFIX_LEASE;
} else if (memcmp(" iaaddr ", str, 9)) {
set_ipv_functions(IPv6);
}
if (!memcmp(" iaaddr ", str, 9)) {
set_ipv_functions(state, IPv6);
return PREFIX_LEASE;
}
return NUM_OF_PREFIX;
@ -264,7 +375,7 @@ int
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
__attribute__ ((hot))
#endif
xstrstr_v4(const char *restrict str)
xstrstr_v4(struct conf_t *state __attribute__ ((unused)), const char *restrict str)
{
size_t len;
@ -300,10 +411,18 @@ int
if (!memcmp(" hardware ethernet", str, 19))
return PREFIX_HARDWARE_ETHERNET;
break;
default:
break;
}
}
if (!memcmp("lease ", str, 6))
return PREFIX_LEASE;
else if (!memcmp(" starts ", str, 9))
return PREFIX_STARTS;
else if (!memcmp(" ends ", str, 7))
return PREFIX_ENDS;
else if (!memcmp(" client-hostname ", str, 18))
return PREFIX_HOSTNAME;
return NUM_OF_PREFIX;
}
@ -317,7 +436,7 @@ int
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
__attribute__ ((hot))
#endif
xstrstr_v6(const char *restrict str)
xstrstr_v6(struct conf_t *state __attribute__ ((unused)), const char *restrict str)
{
size_t len;
@ -353,13 +472,37 @@ int
if (!memcmp(" hardware ethernet", str, 19))
return PREFIX_HARDWARE_ETHERNET;
break;
default:
break;
}
}
if (!memcmp(" iaaddr ", str, 9))
return PREFIX_LEASE;
else if (!memcmp(" starts ", str, 9))
return PREFIX_STARTS;
else if (!memcmp(" ends ", str, 7))
return PREFIX_ENDS;
else if (!memcmp(" client-hostname ", str, 18))
return PREFIX_HOSTNAME;
return NUM_OF_PREFIX;
}
/*! \brief Parse option argument color mode.
*
* \param Color mode string.
* \return color mode enum.
*/
int parse_color_mode(const char *restrict arg)
{
if (!strcmp(arg, "always"))
return color_on;
if (!strcmp(arg, "auto"))
return color_auto;
if (!strcmp(arg, "never"))
return color_off;
return color_unknown;
}
/*! \brief Return a double floating point value.
*
* \param str String to be converted to a double.
@ -384,56 +527,79 @@ double strtod_or_err(const char *restrict str, const char *restrict errmesg)
}
/*! \brief Reverse range.
* Used before output, if a caller has requested reverse sorting.
* FIXME: The temporary memory area handling should be internal to this
* function, not a parameter.
*
* \param flip_me The range that needs to be inverted.
* \param tmp_ranges Temporary memory area for the flip. */
void flip_ranges(struct range_t *restrict flip_me, struct range_t *restrict tmp_ranges)
* Used before output, if a caller has requested reverse sorting. */
void flip_ranges(struct conf_t *state)
{
unsigned int i = num_ranges - 1, j;
unsigned int i = state->num_ranges - 1, j;
struct range_t *tmp_ranges;
for (j = 0; j < num_ranges; j++, i--)
*(tmp_ranges + j) = *(flip_me + i);
memcpy(flip_me, tmp_ranges, num_ranges * sizeof(struct range_t));
tmp_ranges = xmalloc(sizeof(struct range_t) * state->num_ranges);
for (j = 0; j < state->num_ranges; j++, i--)
*(tmp_ranges + j) = *(state->ranges + i);
memcpy(state->ranges, tmp_ranges, state->num_ranges * sizeof(struct range_t));
free(tmp_ranges);
}
/*! \brief Free memory, flush buffers etc. */
void clean_up(void)
void clean_up(struct conf_t *state)
{
struct output_sort *cur, *next;
struct shared_network_t *c, *n;
/* Just in case there something in buffers */
if (fflush(NULL))
error(EXIT_FAILURE, errno, "clean_up: fflush");
free(config.dhcpdconf_file);
free(config.dhcpdlease_file);
free(config.output_file);
free(ranges);
delete_all_leases();
if (shared_networks) {
unsigned int i;
num_shared_networks++;
for (i = 0; i < num_shared_networks; i++)
free((shared_networks + i)->name);
free(shared_networks);
}
for (cur = config.sorts; cur; cur = next) {
free(state->ranges);
delete_all_leases(state);
for (cur = state->sorts; cur; cur = next) {
next = cur->next;
free(cur);
}
for (c = state->shared_net_root; c; c = n) {
n = c->next;
free(c->name);
free(c);
}
}
/*! \brief Print a time stamp of a path or now to output file. */
void dp_time_tool(FILE *file, const char *path, const int epoch)
{
struct stat st;
if (path)
stat(path, &st);
else
clock_gettime(CLOCK_REALTIME, &st.st_mtim);
if (epoch)
fprintf(file, "%ld", st.st_mtim.tv_sec);
else {
char time_stamp[64];
const time_t mtime = st.st_mtim.tv_sec;
struct tm tm;
localtime_r(&mtime, &tm);
strftime(time_stamp, sizeof(time_stamp), "%FT%T%z", &tm);
fprintf(file, "%s", time_stamp);
}
}
/*! \brief A version printing. */
void __attribute__ ((__noreturn__)) print_version(void)
{
#define stringify(s) #s
#define stringify_value(s) stringify(s)
fprintf(stdout, "%s\n"
"Original design by Sami Kerola.\n"
"Original design and maintainer Sami Kerola.\n"
"uthash %s by Troy D. Hanson.\n"
"XML support by Dominic Germain, Sogetel inc.\n"
"IPv6 support by Cheer Xiao.\n\n"
"The software has FreeBSD License.\n", PACKAGE_STRING);
"IPv6 support by Cheer Xiao.\n"
"Mustach templating support by Jose Bollo.\n"
" The dhcpd-pools is FreeBSD Licensed,\n"
" uthash uses BSD license,\n"
" gnulib parts are mostly GPL,\n"
" and mustache uses Apache License.\n", PACKAGE_STRING,
stringify_value(UTHASH_VERSION));
exit(EXIT_SUCCESS);
}
@ -456,6 +622,9 @@ void __attribute__ ((__noreturn__)) usage(int status)
fputs( " j for json\n", out);
fputs( " J for json with active lease details\n", out);
fputs( " c for comma separated values\n", out);
#ifdef BUILD_MUSTACH
fputs( " --mustach=FILE output using mustach template file\n", out);
#endif
fputs( " -s, --sort=[nimcptTe] sort ranges by\n", out);
fputs( " n name\n", out);
fputs( " i IP\n", out);
@ -468,12 +637,18 @@ void __attribute__ ((__noreturn__)) usage(int status)
fputs( " -r, --reverse reverse order sort\n", out);
fputs( " -o, --output=FILE output into a file\n", out);
fputs( " -L, --limit=NR output limit mask 77 - 00\n", out);
fputs( " --warning=PERC set warning alarming limit\n", out);
fputs( " --critical=PERC set critical alarming limit\n", out);
fputs( " --color=WHEN use colors 'always', 'never', or 'auto'\n", out);
fputs( " --warning=PERC set warning alarming threshold\n", out);
fputs( " --critical=PERC set critical alarming threshold\n", out);
fputs( " --skip=WHAT do not print threshold 'ok', 'warning', 'critical',\n", out);
fputs( " 'minsize', or 'suppressed'\n", out);
fputs( " --warn-count=NR a number of free leases before warning raised\n", out);
fputs( " --crit-count=NR a number of free leases before critical raised\n", out);
fputs( " --minsize=size disable alarms for small ranges and shared-nets\n", out);
fputs( " --snet-alarms suppress range alarms that are part of a shared-net\n", out);
fputs( " -p, --perfdata print additional perfdata in alarming mode\n", out);
fputs( " -A, --all-as-shared treat single subnets as shared-network with CIDR as their name\n", out);
fputs( " --ip-version=4|6 force analysis to use either IPv4 or IPv6 functions\n", out);
fputs( " -v, --version output version information and exit\n", out);
fputs( " -h, --help display this help and exit\n", out);
fputs( "\n", out);

File diff suppressed because it is too large Load diff

View file

@ -40,6 +40,7 @@
#include <config.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@ -47,6 +48,7 @@
#include "error.h"
#include "progname.h"
#include "quote.h"
#include "xalloc.h"
#include "dhcpd-pools.h"
@ -117,9 +119,14 @@ int rangecomp(const void *restrict r1, const void *restrict r2)
*/
int comp_double(double f1, double f2)
{
return f1 < f2 ? -1 : f1 > f2 ? 1 : 0;
if (isless(f1, f2))
return -1;
else if (isless(f2, f1))
return 1;
return 0;
}
/*! \brief Compare two range_t by their first_ip.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
@ -239,8 +246,8 @@ comparer_t field_selector(char c)
default:
{
char str[2] = { c, '\0' };
clean_up();
error(EXIT_FAILURE, 0, "field_selector: unknown sort order: %s", quote(str));
error(EXIT_FAILURE, 0, "field_selector: unknown sort order: %s",
quote(str));
}
}
return NULL;
@ -251,12 +258,12 @@ comparer_t field_selector(char c)
* \param right The right side of the merge sort.
* \return Relevant for merge sort decision.
*/
static int merge(struct range_t *restrict left, struct range_t *restrict right)
static int merge(struct conf_t *state, struct range_t *restrict left, struct range_t *restrict right)
{
struct output_sort *p;
int ret;
for (p = config.sorts; p; p = p->next) {
for (p = state->sorts; p; p = p->next) {
if (p->func == NULL) {
/* String sorting is special. */
ret = strcmp(left->shared_net->name, right->shared_net->name);
@ -274,43 +281,46 @@ static int merge(struct range_t *restrict left, struct range_t *restrict right)
}
/*! \brief Mergesort for range table.
* \param orig Pointer to range that is requested to be sorted.
* \param size Number of ranges to be sorted.
* \param temp Temporary memory space, needed when a values has to be
* flipped.
*/
void mergesort_ranges(struct range_t *restrict orig, int size, struct range_t *restrict temp)
void mergesort_ranges(struct conf_t *state, struct range_t *restrict orig, unsigned int size,
struct range_t *restrict temp, const int root_call)
{
int left, right, i;
unsigned int left, i, u_right;
struct range_t hold;
/* Merge sort split size */
static const int MIN_MERGE_SIZE = 8;
static const unsigned int MIN_MERGE_SIZE = 8;
if (temp == NULL)
temp = xmalloc(sizeof(struct range_t) * size);
if (size < MIN_MERGE_SIZE) {
for (left = 0; left < size; left++) {
int s_right;
hold = *(orig + left);
for (right = left - 1; 0 <= right; right--) {
if (merge((orig + right), &hold))
for (s_right = left - 1; 0 <= s_right; s_right--) {
if (merge(state, (orig + s_right), &hold))
break;
*(orig + right + 1) = *(orig + right);
*(orig + s_right + 1) = *(orig + s_right);
}
*(orig + right + 1) = hold;
*(orig + s_right + 1) = hold;
}
if (root_call)
free(temp);
return;
}
mergesort_ranges(orig, size / 2, temp);
mergesort_ranges(orig + size / 2, size - size / 2, temp);
mergesort_ranges(state, orig, size / 2, temp, 0);
mergesort_ranges(state, orig + size / 2, size - size / 2, temp, 0);
left = 0;
right = size / 2;
u_right = size / 2;
i = 0;
while (left < size / 2 && right < size) {
if (merge((orig + left), (orig + right))) {
while (left < size / 2 && u_right < size) {
if (merge(state, (orig + left), (orig + u_right))) {
*(temp + i) = *(orig + left);
left++;
} else {
*(temp + i) = *(orig + right);
right++;
*(temp + i) = *(orig + u_right);
u_right++;
}
i++;
}
@ -319,10 +329,13 @@ void mergesort_ranges(struct range_t *restrict orig, int size, struct range_t *r
left++;
i++;
}
while (right < size) {
*(temp + i) = *(orig + right);
right++;
while (u_right < size) {
*(temp + i) = *(orig + u_right);
u_right++;
i++;
}
memcpy(orig, temp, size * sizeof(struct range_t));
if (root_call)
free(temp);
}

View file

@ -10,18 +10,37 @@ TESTS = \
tests/alarm-warning-ranges \
tests/alarm-warning-snets \
tests/shnet-alarm \
tests/big-small \
tests/binding-states \
tests/bootp \
tests/cidr-v4 \
tests/cidr-v6 \
tests/complete \
tests/complete-perfdata \
tests/empty \
tests/errors \
tests/full-json \
tests/full-xml \
tests/formats \
tests/leading0 \
tests/one-ip \
tests/one-line \
tests/parser \
tests/range4 \
tests/range6 \
tests/same-twice \
tests/shufled \
tests/simple \
tests/skip \
tests/sorts \
tests/v6
tests/statuses \
tests/v6 \
tests/v6-perfdata
if ENABLE_MUSTACH
TESTS += \
tests/mustach
endif
EXTRA_DIST += \
tests/confs \

View file

@ -10,25 +10,32 @@ fi
echo '== warn count ==' > tests/outputs/$IAM
dhcpd-pools --config $top_srcdir/tests/confs/complete --leases $top_srcdir/tests/leases/complete \
--warning=40 --warn-count=20 --output=tests/outputs/$IAM-too
--color=never --warning=40 --warn-count=20 --output=tests/outputs/$IAM-too
echo $? >> tests/outputs/$IAM-too
cat tests/outputs/$IAM-too >> tests/outputs/$IAM
echo '== crit count ==' >> tests/outputs/$IAM
dhcpd-pools --config $top_srcdir/tests/confs/complete --leases $top_srcdir/tests/leases/complete \
--critical=40 --crit-count=20 --output=tests/outputs/$IAM-too
--color=never --critical=40 --crit-count=20 --output=tests/outputs/$IAM-too
echo $? >> tests/outputs/$IAM-too
cat tests/outputs/$IAM-too >> tests/outputs/$IAM
echo '== minsize ==' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--warning=40 --warn-count=20 --minsize=40 -o tests/outputs/$IAM-too
--color=never --warning=40 --warn-count=20 --minsize=40 -o tests/outputs/$IAM-too
echo $? >> tests/outputs/$IAM-too
cat tests/outputs/$IAM-too >> tests/outputs/$IAM
echo '== snet alarms ==' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--warning=40 --snet-alarms -o tests/outputs/$IAM-too
--color=never --warning=40 --snet-alarms -o tests/outputs/$IAM-too
echo $? >> tests/outputs/$IAM-too
cat tests/outputs/$IAM-too >> tests/outputs/$IAM
echo '== shared net count alarms ==' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--color=always --format t --crit-count=20 --critical=0 --warning=0 --warn-count=24 \
--output=tests/outputs/$IAM-too
echo $? >> tests/outputs/$IAM-too
cat tests/outputs/$IAM-too >> tests/outputs/$IAM

1
tests/big-small Symbolic link
View file

@ -0,0 +1 @@
test.sh

14
tests/binding-states Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -c $top_srcdir/tests/confs/$IAM --color=never \
-l $top_srcdir/tests/leases/$IAM -o tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

1
tests/cidr-v4 Symbolic link
View file

@ -0,0 +1 @@
test.sh

1
tests/cidr-v6 Symbolic link
View file

@ -0,0 +1 @@
test.sh

16
tests/complete-perfdata Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
TESTDATA=${IAM%-*}
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -c $top_srcdir/tests/confs/$TESTDATA \
-l $top_srcdir/tests/leases/$TESTDATA -o tests/outputs/$IAM \
--warning 80 --perfdata
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

5
tests/confs/big-small Normal file
View file

@ -0,0 +1,5 @@
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range 10.0.0.10 10.0.0.1;
}
}

1
tests/confs/binding-states Symbolic link
View file

@ -0,0 +1 @@
complete

31
tests/confs/cidr-v4 Normal file
View file

@ -0,0 +1,31 @@
shared-network example1 {
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range 10.0.0.1/27;
}
}
subnet 10.1.0.0 netmask 255.255.255.0 {
pool {
range 10.1.0.1/27;
}
}
}
shared-network example2 {
subnet 10.2.0.0 netmask 255.255.255.0 {
pool {
range 10.2.0.1/27;
}
}
subnet 10.3.0.0 netmask 255.255.255.0 {
pool {
range 10.3.0.1/27;
}
}
}
subnet 10.4.0.0 netmask 255.255.255.0 {
pool {
range 10.4.0.1/28;
}
}

10
tests/confs/cidr-v6 Normal file
View file

@ -0,0 +1,10 @@
subnet6 dead:abba:1000::/56 {
range6 dead:abba:1000::2/120;
prefix6 dead:abba:1000:0100:: dead:abba:1000:ff00::/56;
}
subnet6 dead:abba:40ff::/56 {
range6 dead:abba:4000::2/120;
prefix6 dead:abba:4000:0100:: dead:abba:4000:ff00::/56;
}

1
tests/confs/formats Symbolic link
View file

@ -0,0 +1 @@
complete

31
tests/confs/range4 Normal file
View file

@ -0,0 +1,31 @@
shared-network example1 {
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range 10.0.0.0/27;
}
}
subnet 10.1.0.0 netmask 255.255.255.0 {
pool {
range 10.1.0.1/27;
}
}
}
shared-network example2 {
subnet 10.2.0.0 netmask 255.255.255.0 {
pool {
range 10.2.0.1/28;
}
}
subnet 10.3.0.0 netmask 255.255.255.0 {
pool {
range 10.3.0.1/29;
}
}
}
subnet 10.4.0.0 netmask 255.255.255.0 {
pool {
range 10.4.0.1/32;
}
}

4
tests/confs/range6 Normal file
View file

@ -0,0 +1,4 @@
subnet6 dead:abba:1000::/56 {
range6 dead:abba:1000::/56;
prefix6 dead:abba:1000:0100:: dead:abba:1000:ff00::/56;
}

View file

@ -1,31 +0,0 @@
shared-network example1 {
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range 10.0.0.1 10.0.0.20;
}
}
subnet 10.1.0.0 netmask 255.255.255.0 {
pool {
range 10.1.0.1 10.1.0.20;
}
}
}
shared-network example2 {
subnet 10.2.0.0 netmask 255.255.255.0 {
pool {
range 10.2.0.1 10.2.0.20;
}
}
subnet 10.3.0.0 netmask 255.255.255.0 {
pool {
range 10.3.0.1 10.3.0.20;
}
}
}
subnet 10.4.0.0 netmask 255.255.255.0 {
pool {
range 10.4.0.1 10.4.0.20;
}
}

1
tests/confs/shnet-alarm Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/confs/shufled Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/confs/statuses Symbolic link
View file

@ -0,0 +1 @@
complete

48
tests/errors Executable file
View file

@ -0,0 +1,48 @@
#!/bin/sh
#
# Test error inputs.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
echo '=== output mask' >| tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
-L 88 >> tests/outputs/$IAM 2>&1
echo '=== unknown specifier' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--skip=okish >> tests/outputs/$IAM 2>&1
echo '=== color mode' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--color=sometimes >> tests/outputs/$IAM 2>&1
echo '=== IPv5' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--ip-version=5 >> tests/outputs/$IAM 2>&1
echo '=== missing conf' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete_NXFILE -l $top_srcdir/tests/leases/complete 2>&1 | \
sed 's/: ..\/..\/tests/: .\/tests/'>> tests/outputs/$IAM
echo '=== missing leases' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete_NXFILE 2>&1 | \
sed 's/: ..\/..\/tests/: .\/tests/' >> tests/outputs/$IAM
echo '=== html table' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--format=html >> tests/outputs/$IAM 2>&1
echo '=== none existing format' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
-fz >> tests/outputs/$IAM 2>&1
echo '=== broken percent input' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/complete -l $top_srcdir/tests/leases/complete \
--warning=eighty >> tests/outputs/$IAM 2>&1
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

View file

@ -7,11 +7,28 @@ CRITICAL: dhcpd-pools: Ranges - crit: 3 warn: 0 ok: 2; | range_crit=3 range_warn
Shared nets - crit: 1 warn: 0 ok: 1; | snet_crit=1 snet_warn=0 snet_ok=1
2
== minsize ==
OK: Ranges - crit: 0 warn: 0 ok: 0 ignored: 5; | range_crit=0 range_warn=0 range_ok=0 range_ignored=5
OK: Ranges - crit: 0 warn: 0 ok: 2 ignored: 3; | range_crit=0 range_warn=0 range_ok=2 range_ignored=3
Shared nets - crit: 0 warn: 0 ok: 0 ignored: 2; | snet_crit=0 snet_warn=0 snet_ok=0 snet_ignored=2
0
== snet alarms ==
WARNING: dhcpd-pools: Ranges - crit: 0 warn: 0 ok: 0; | range_crit=0 range_warn=0 range_ok=0
WARNING: dhcpd-pools: Ranges - crit: 0 warn: 0 ok: 2; | range_crit=0 range_warn=0 range_ok=2
Shared nets - crit: 0 warn: 2 ok: 0; | snet_crit=0 snet_warn=2 snet_ok=0
1
== shared net count alarms ==
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
example1 10.0.0.1 - 10.0.0.20 20 11 55.000 0 11 55.000
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000
example2 10.2.0.1 - 10.2.0.20 20 8 40.000 0 8 40.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000
Shared networks:
name max cur percent touch t+c t+c perc
example1 40 21 52.500 0 21 52.500
example2 40 17 42.500 0 17 42.500
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 100 43 43.000 0 43 43.000
0

1
tests/expected/big-small Symbolic link
View file

@ -0,0 +1 @@
simple

View file

@ -0,0 +1,16 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
example1 10.0.0.1 - 10.0.0.20 20 4 20.000 3 7 35.000 2 10.000
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000 0 0.000
example2 10.2.0.1 - 10.2.0.20 20 8 40.000 0 8 40.000 0 0.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000 0 0.000
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000 0 0.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
example1 40 14 35.000 3 17 42.500 2 5.000
example2 40 17 42.500 0 17 42.500 0 0.000
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 36 36.000 3 39 39.000 2 2.000

View file

@ -1,10 +0,0 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
All networks 10.0.0.1 - 10.0.0.10 10 10 100.000 0 10 100.000
Shared networks:
name max cur percent touch t+c t+c perc
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 10 10 100.000 0 10 100.000

1
tests/expected/bootp Symbolic link
View file

@ -0,0 +1 @@
simple

16
tests/expected/cidr-v4 Normal file
View file

@ -0,0 +1,16 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
example1 10.0.0.1 - 10.0.0.31 31 11 35.484 0 11 35.484
example1 10.1.0.1 - 10.1.0.31 31 10 32.258 0 10 32.258
example2 10.2.0.1 - 10.2.0.31 31 8 25.806 0 8 25.806
example2 10.3.0.1 - 10.3.0.31 31 9 29.032 0 9 29.032
All networks 10.4.0.1 - 10.4.0.15 15 5 33.333 0 5 33.333
Shared networks:
name max cur percent touch t+c t+c perc
example1 62 21 33.871 0 21 33.871
example2 62 17 27.419 0 17 27.419
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 139 43 30.935 0 43 30.935

11
tests/expected/cidr-v6 Normal file
View file

@ -0,0 +1,11 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
All networks dead:abba:1000::2 - dead:abba:1000::ff 254 0 0.000 0 0 0.000
All networks dead:abba:4000::2 - dead:abba:4000::ff 254 1 0.394 0 1 0.394
Shared networks:
name max cur percent touch t+c t+c perc
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 508 1 0.197 0 1 0.197

View file

@ -0,0 +1,3 @@
OK: Ranges - crit: 0 warn: 0 ok: 5; | range_crit=0 range_warn=0 range_ok=5 10.4.0.1_r=5;16;18;0;20 10.4.0.1_rt=0 10.3.0.1_r=9;16;18;0;20 10.3.0.1_rt=0 10.2.0.1_r=8;16;18;0;20 10.2.0.1_rt=0 10.1.0.1_r=10;16;18;0;20 10.1.0.1_rt=0 10.0.0.1_r=11;16;18;0;20 10.0.0.1_rt=0
Shared nets - crit: 0 warn: 0 ok: 2; | snet_crit=0 snet_warn=0 snet_ok=2 'example1_s'=21;32;36;0;40 'example1_st'=0 'example2_s'=17;32;36;0;40 'example2_st'=0

27
tests/expected/errors Normal file
View file

@ -0,0 +1,27 @@
=== output mask
dhcpd-pools: return_limit: output mask '88' is illegal
=== unknown specifier
dhcpd-pools: unknown --skip specifier: okish
=== color mode
dhcpd-pools: unknown color mode: 'sometimes'
=== IPv5
dhcpd-pools: unknown --ip-version argument: 5
=== missing conf
dhcpd-pools: cannot open inlude: ./tests/confs/complete_NXFILE: No such file or directory
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
Shared networks:
name max cur percent touch t+c t+c perc
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 0 0 nan 0 0 nan
=== missing leases
dhcpd-pools: parse_leases: ./tests/leases/complete_NXFILE: No such file or directory
=== html table
dhcpd-pools: html table only output format is deprecated
=== none existing format
dhcpd-pools: unknown output format: 'z'
=== broken percent input
dhcpd-pools: illegal argument: 'eighty'

284
tests/expected/formats Normal file
View file

@ -0,0 +1,284 @@
=== color text
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
example1 10.0.0.1 - 10.0.0.20 20 11 55.000 0 11 55.000
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000
example2 10.2.0.1 - 10.2.0.20 20 8 40.000 0 8 40.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000
Shared networks:
name max cur percent touch t+c t+c perc
example1 40 21 52.500 0 21 52.500
example2 40 17 42.500 0 17 42.500
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 100 43 43.000 0 43 43.000
=== html
<!DOCTYPE html>
<html>
<head>
<title>ISC dhcpd dhcpd-pools output</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-2.2.2/datatables.min.css">
<style type="text/css">
table.dhcpd-pools th { text-transform: capitalize }
</style>
</head>
<body>
<div class="container">
<h2>ISC DHCPD status</h2>
<h3>Sum of all</h3>
<table id="a" class="dhcpd-pools order-column table table-hover" summary="all">
<thead>
<tr>
<th>name</th>
<th>max</th>
<th>cur</th>
<th>free</th>
<th>percent</th>
<th>touch</th>
<th>t+c</th>
<th>t+c perc</th>
</tr>
</thead>
<tbody>
<tr>
<td>All networks</td>
<td>100</td>
<td>43</td>
<td>57</td>
<td>43.000</td>
<td>0</td>
<td>43</td>
<td>43.000</td>
</tr>
</tbody>
</table>
<h3>Shared networks</h3>
<table id="s" class="dhcpd-pools order-column table table-hover" summary="snet">
<thead>
<tr>
<th>name</th>
<th>max</th>
<th>cur</th>
<th>free</th>
<th>percent</th>
<th>touch</th>
<th>t+c</th>
<th>t+c perc</th>
</tr>
</thead>
<tbody>
<tr>
<td>example1</td>
<td>40</td>
<td>21</td>
<td>19</td>
<td>52.5</td>
<td>0</td>
<td>21</td>
<td>52.500</td>
</tr>
<tr>
<td>example2</td>
<td>40</td>
<td>17</td>
<td>23</td>
<td>42.5</td>
<td>0</td>
<td>17</td>
<td>42.500</td>
</tr>
</tbody>
</table>
<h3>Ranges</h3>
<table id="r" class="dhcpd-pools order-column table table-hover" summary="ranges">
<thead>
<tr>
<th>shared net name</th>
<th>first ip</th>
<th>last ip</th>
<th>max</th>
<th>cur</th>
<th>free</th>
<th>percent</th>
<th>touch</th>
<th>t+c</th>
<th>t+c perc</th>
</tr>
</thead>
<tbody>
<tr>
<td>example1</td>
<td>10.0.0.1</td>
<td>10.0.0.20</td>
<td>20</td>
<td>11</td>
<td>9</td>
<td>55</td>
<td>0</td>
<td>11</td>
<td>55.000</td>
</tr>
<tr>
<td>example1</td>
<td>10.1.0.1</td>
<td>10.1.0.20</td>
<td>20</td>
<td>10</td>
<td>10</td>
<td>50</td>
<td>0</td>
<td>10</td>
<td>50.000</td>
</tr>
<tr>
<td>example2</td>
<td>10.2.0.1</td>
<td>10.2.0.20</td>
<td>20</td>
<td>8</td>
<td>12</td>
<td>40</td>
<td>0</td>
<td>8</td>
<td>40.000</td>
</tr>
<tr>
<td>example2</td>
<td>10.3.0.1</td>
<td>10.3.0.20</td>
<td>20</td>
<td>9</td>
<td>11</td>
<td>45</td>
<td>0</td>
<td>9</td>
<td>45.000</td>
</tr>
<tr>
<td>All networks</td>
<td>10.4.0.1</td>
<td>10.4.0.20</td>
<td>20</td>
<td>5</td>
<td>15</td>
<td>25</td>
<td>0</td>
<td>5</td>
<td>25.000</td>
</tr>
</tbody>
</table>
<br /><div class="well well-lg">
More info at <a href="https://dhcpd-pools.sourceforge.net/">https://dhcpd-pools.sourceforge.net/</a>
</small></div></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-2.2.2/datatables.min.js"></script>
<script type="text/javascript" class="init">$(document).ready(function() { $('#s').DataTable({ "iDisplayLength": 50, "lengthMenu": [ [25, 50, 100, -1], [25, 50, 100, "All"] ], "order": [[ 4, "desc" ]] } ); } );</script>
<script type="text/javascript" class="init">$(document).ready(function() { $('#r').DataTable({ "iDisplayLength": 100, "lengthMenu": [ [25, 50, 100, -1], [25, 50, 100, "All"] ], "order": [[ 6, "desc" ]] } ); } );</script>
</body></html>
=== xml
<dhcpstatus>
<subnet>
<location>example1</location>
<range>10.0.0.1 - 10.0.0.20</range>
<defined>20</defined>
<used>11</used>
<touched>0</touched>
<free>9</free>
</subnet>
<subnet>
<location>example1</location>
<range>10.1.0.1 - 10.1.0.20</range>
<defined>20</defined>
<used>10</used>
<touched>0</touched>
<free>10</free>
</subnet>
<subnet>
<location>example2</location>
<range>10.2.0.1 - 10.2.0.20</range>
<defined>20</defined>
<used>8</used>
<touched>0</touched>
<free>12</free>
</subnet>
<subnet>
<location>example2</location>
<range>10.3.0.1 - 10.3.0.20</range>
<defined>20</defined>
<used>9</used>
<touched>0</touched>
<free>11</free>
</subnet>
<subnet>
<location>All networks</location>
<range>10.4.0.1 - 10.4.0.20</range>
<defined>20</defined>
<used>5</used>
<touched>0</touched>
<free>15</free>
</subnet>
<shared-network>
<location>example1</location>
<defined>40</defined>
<used>21</used>
<touched>0</touched>
<free>19</free>
</shared-network>
<shared-network>
<location>example2</location>
<defined>40</defined>
<used>17</used>
<touched>0</touched>
<free>23</free>
</shared-network>
<summary>
<location>All networks</location>
<defined>100</defined>
<used>43</used>
<touched>0</touched>
<free>57</free>
</summary>
</dhcpstatus>
=== csv
"Ranges:"
"shared net name","first ip","last ip","max","cur","percent","touch","t+c","t+c perc"
"example1","10.0.0.1","10.0.0.20","20","11","55.000","0","11","55.000"
"example1","10.1.0.1","10.1.0.20","20","10","50.000","0","10","50.000"
"example2","10.2.0.1","10.2.0.20","20","8","40.000","0","8","40.000"
"example2","10.3.0.1","10.3.0.20","20","9","45.000","0","9","45.000"
"All networks","10.4.0.1","10.4.0.20","20","5","25.000","0","5","25.000"
"Shared networks:"
"name","max","cur","percent","touch","t+c","t+c perc"
"example1","40","21","52.500","0","21","52.500"
"example2","40","17","42.500","0","17","42.500"
"Sum of all ranges:"
"name","max","cur","percent","touch","t+c","t+c perc"
"All networks","100","43","43.000","0","43","43.000"
=== json
{
"subnets": [
{ "location":"example1", "range":"10.0.0.1 - 10.0.0.20", "first_ip":"10.0.0.1", "last_ip":"10.0.0.20", "defined":20, "used":11, "touched":0, "free":9, "percent":55, "touch_count":11, "touch_percent":55, "status":0 },
{ "location":"example1", "range":"10.1.0.1 - 10.1.0.20", "first_ip":"10.1.0.1", "last_ip":"10.1.0.20", "defined":20, "used":10, "touched":0, "free":10, "percent":50, "touch_count":10, "touch_percent":50, "status":0 },
{ "location":"example2", "range":"10.2.0.1 - 10.2.0.20", "first_ip":"10.2.0.1", "last_ip":"10.2.0.20", "defined":20, "used":8, "touched":0, "free":12, "percent":40, "touch_count":8, "touch_percent":40, "status":0 },
{ "location":"example2", "range":"10.3.0.1 - 10.3.0.20", "first_ip":"10.3.0.1", "last_ip":"10.3.0.20", "defined":20, "used":9, "touched":0, "free":11, "percent":45, "touch_count":9, "touch_percent":45, "status":0 },
{ "location":"All networks", "range":"10.4.0.1 - 10.4.0.20", "first_ip":"10.4.0.1", "last_ip":"10.4.0.20", "defined":20, "used":5, "touched":0, "free":15, "percent":25, "touch_count":5, "touch_percent":25, "status":0 }
],
"shared-networks": [
{ "location":"example1", "defined":40, "used":21, "touched":0, "free":19, "percent":52.5, "touch_count":21, "touch_percent":52.5, "status":0 },
{ "location":"example2", "defined":40, "used":17, "touched":0, "free":23, "percent":42.5, "touch_count":17, "touch_percent":42.5, "status":0 }
]
}
=== perfdata
CRITICAL: dhcpd-pools: Ranges - crit: 3 warn: 2 ok: 0; | range_crit=3 range_warn=2 range_ok=0 10.4.0.1_r=5;4;8;0;20 10.4.0.1_rt=0 10.3.0.1_r=9;4;8;0;20 10.3.0.1_rt=0 10.2.0.1_r=8;4;8;0;20 10.2.0.1_rt=0 10.1.0.1_r=10;4;8;0;20 10.1.0.1_rt=0 10.0.0.1_r=11;4;8;0;20 10.0.0.1_rt=0
Shared nets - crit: 2 warn: 0 ok: 0; | snet_crit=2 snet_warn=0 snet_ok=0 'example1_s'=21;8;16;0;40 'example1_st'=0 'example2_s'=17;8;16;0;40 'example2_st'=0

317
tests/expected/mustach Normal file
View file

@ -0,0 +1,317 @@
Ethernets:
macaddress: 00:00:00:00:00:01 ip: 10.0.0.1
macaddress: 00:00:00:00:00:02 ip: 10.0.0.2
macaddress: 00:00:00:00:00:03 ip: 10.0.0.3
macaddress: 00:00:00:00:00:04 ip: 10.0.0.4
macaddress: 00:00:00:00:00:05 ip: 10.0.0.5
macaddress: 00:00:00:00:00:06 ip: 10.0.0.6
macaddress: 00:00:00:00:00:07 ip: 10.0.0.7
macaddress: 00:00:00:00:00:08 ip: 10.0.0.8
macaddress: 00:00:00:00:00:09 ip: 10.0.0.9
macaddress: 00:00:00:00:00:10 ip: 10.0.0.10
macaddress: 00:00:00:00:00:11 ip: 10.0.0.11
macaddress: 00:00:00:00:00:12 ip: 10.0.0.12
macaddress: 00:00:00:00:01:00 ip: 10.1.0.0
macaddress: 00:00:00:00:01:01 ip: 10.1.0.1
macaddress: 00:00:00:00:01:02 ip: 10.1.0.2
macaddress: 00:00:00:00:01:03 ip: 10.1.0.3
macaddress: 00:00:00:00:01:04 ip: 10.1.0.4
macaddress: 00:00:00:00:01:05 ip: 10.1.0.5
macaddress: 00:00:00:00:01:06 ip: 10.1.0.6
macaddress: 00:00:00:00:01:07 ip: 10.1.0.7
macaddress: 00:00:00:00:01:08 ip: 10.1.0.8
macaddress: 00:00:00:00:01:09 ip: 10.1.0.9
macaddress: 00:00:00:00:01:10 ip: 10.1.0.10
macaddress: 00:00:00:00:02:00 ip: 10.2.0.0
macaddress: 00:00:00:00:02:01 ip: 10.2.0.1
macaddress: 00:00:00:00:02:02 ip: 10.2.0.2
macaddress: 00:00:00:00:02:03 ip: 10.2.0.3
macaddress: 00:00:00:00:02:04 ip: 10.2.0.4
macaddress: 00:00:00:00:02:05 ip: 10.2.0.5
macaddress: 00:00:00:00:02:06 ip: 10.2.0.6
macaddress: 00:00:00:00:02:07 ip: 10.2.0.7
macaddress: 00:00:00:00:02:08 ip: 10.2.0.8
macaddress: 00:00:00:00:03:00 ip: 10.3.0.0
macaddress: 00:00:00:00:03:01 ip: 10.3.0.1
macaddress: 00:00:00:00:03:02 ip: 10.3.0.2
macaddress: 00:00:00:00:03:03 ip: 10.3.0.3
macaddress: 00:00:00:00:03:04 ip: 10.3.0.4
macaddress: 00:00:00:00:03:05 ip: 10.3.0.5
macaddress: 00:00:00:00:03:06 ip: 10.3.0.6
macaddress: 00:00:00:00:03:07 ip: 10.3.0.7
macaddress: 00:00:00:00:03:08 ip: 10.3.0.8
macaddress: 00:00:00:00:03:09 ip: 10.3.0.9
macaddress: 00:00:00:00:04:00 ip: 10.4.0.0
macaddress: 00:00:00:00:04:01 ip: 10.4.0.1
macaddress: 00:00:00:00:04:02 ip: 10.4.0.2
macaddress: 00:00:00:00:04:03 ip: 10.4.0.3
macaddress: 00:00:00:00:04:04 ip: 10.4.0.4
macaddress: 00:00:00:00:04:05 ip: 10.4.0.5
macaddress: 00:00:00:00:04:06 ip: 10.4.0.6
Subnets:
location: example1
range: 10.0.0.1 - 10.0.0.20
first_ip: 10.0.0.1
last_ip: 10.0.0.20
used: 11
touched: 0
defined: 20
free: 9
percent: 55
touch_count: 11
touch_percent: 55
backup_count: 1
backup_percent: 5
status: 0
location: example1
range: 10.1.0.1 - 10.1.0.20
first_ip: 10.1.0.1
last_ip: 10.1.0.20
used: 10
touched: 0
defined: 20
free: 10
percent: 50
touch_count: 10
touch_percent: 50
backup_count: 0
backup_percent: 0
status: 0
location: example2
range: 10.2.0.1 - 10.2.0.20
first_ip: 10.2.0.1
last_ip: 10.2.0.20
used: 8
touched: 0
defined: 20
free: 12
percent: 40
touch_count: 8
touch_percent: 40
backup_count: 0
backup_percent: 0
status: 0
location: example2
range: 10.3.0.1 - 10.3.0.20
first_ip: 10.3.0.1
last_ip: 10.3.0.20
used: 9
touched: 0
defined: 20
free: 11
percent: 45
touch_count: 9
touch_percent: 45
backup_count: 0
backup_percent: 0
status: 0
location: All networks
range: 10.4.0.1 - 10.4.0.20
first_ip: 10.4.0.1
last_ip: 10.4.0.20
used: 5
touched: 0
defined: 20
free: 15
percent: 25
touch_count: 5
touch_percent: 25
backup_count: 1
backup_percent: 5
status: 0
Shared-networks:
location: example1
defined: 40
used: 21
touched: 0
free: 19
percent: 52.5
touch_count: 21
touch_percent: 52.5
backup_count: 1
backup_percent: 2.5
status: 0
location: example2
defined: 40
used: 17
touched: 0
free: 23
percent: 42.5
touch_count: 17
touch_percent: 42.5
backup_count: 0
backup_percent: 0
status: 0
Summary:
location: All networks
defined: 100
used: 43
touched: 0
free: 57
percent: 43
touch_count: 43
touch_percent: 43
backup_count: 2
backup_percent: 2
status: 0
number_of_ranges: 5
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 ---
Ethernets:
macaddress: 00:00:00:00:00:01 ip: 10.0.0.1
macaddress: 00:00:00:00:00:02 ip: 10.0.0.2
macaddress: 00:00:00:00:00:03 ip: 10.0.0.3
macaddress: 00:00:00:00:00:04 ip: 10.0.0.4
macaddress: 00:00:00:00:00:05 ip: 10.0.0.5
macaddress: 00:00:00:00:00:06 ip: 10.0.0.6
macaddress: 00:00:00:00:00:07 ip: 10.0.0.7
macaddress: 00:00:00:00:00:08 ip: 10.0.0.8
macaddress: 00:00:00:00:00:09 ip: 10.0.0.9
macaddress: 00:00:00:00:00:10 ip: 10.0.0.10
macaddress: 00:00:00:00:00:11 ip: 10.0.0.11
macaddress: 00:00:00:00:00:12 ip: 10.0.0.12
macaddress: 00:00:00:00:01:00 ip: 10.1.0.0
macaddress: 00:00:00:00:01:01 ip: 10.1.0.1
macaddress: 00:00:00:00:01:02 ip: 10.1.0.2
macaddress: 00:00:00:00:01:03 ip: 10.1.0.3
macaddress: 00:00:00:00:01:04 ip: 10.1.0.4
macaddress: 00:00:00:00:01:05 ip: 10.1.0.5
macaddress: 00:00:00:00:01:06 ip: 10.1.0.6
macaddress: 00:00:00:00:01:07 ip: 10.1.0.7
macaddress: 00:00:00:00:01:08 ip: 10.1.0.8
macaddress: 00:00:00:00:01:09 ip: 10.1.0.9
macaddress: 00:00:00:00:01:10 ip: 10.1.0.10
macaddress: 00:00:00:00:02:00 ip: 10.2.0.0
macaddress: 00:00:00:00:02:01 ip: 10.2.0.1
macaddress: 00:00:00:00:02:02 ip: 10.2.0.2
macaddress: 00:00:00:00:02:03 ip: 10.2.0.3
macaddress: 00:00:00:00:02:04 ip: 10.2.0.4
macaddress: 00:00:00:00:02:05 ip: 10.2.0.5
macaddress: 00:00:00:00:02:06 ip: 10.2.0.6
macaddress: 00:00:00:00:02:07 ip: 10.2.0.7
macaddress: 00:00:00:00:02:08 ip: 10.2.0.8
macaddress: 00:00:00:00:03:00 ip: 10.3.0.0
macaddress: 00:00:00:00:03:01 ip: 10.3.0.1
macaddress: 00:00:00:00:03:02 ip: 10.3.0.2
macaddress: 00:00:00:00:03:03 ip: 10.3.0.3
macaddress: 00:00:00:00:03:04 ip: 10.3.0.4
macaddress: 00:00:00:00:03:05 ip: 10.3.0.5
macaddress: 00:00:00:00:03:06 ip: 10.3.0.6
macaddress: 00:00:00:00:03:07 ip: 10.3.0.7
macaddress: 00:00:00:00:03:08 ip: 10.3.0.8
macaddress: 00:00:00:00:03:09 ip: 10.3.0.9
macaddress: 00:00:00:00:04:00 ip: 10.4.0.0
macaddress: 00:00:00:00:04:01 ip: 10.4.0.1
macaddress: 00:00:00:00:04:02 ip: 10.4.0.2
macaddress: 00:00:00:00:04:03 ip: 10.4.0.3
macaddress: 00:00:00:00:04:04 ip: 10.4.0.4
macaddress: 00:00:00:00:04:05 ip: 10.4.0.5
macaddress: 00:00:00:00:04:06 ip: 10.4.0.6
Subnets:
location: example1
range: 10.0.0.1 - 10.0.0.20
first_ip: 10.0.0.1
last_ip: 10.0.0.20
used: 11
touched: 0
defined: 20
free: 9
percent: 55
touch_count: 11
touch_percent: 55
backup_count: 1
backup_percent: 5
status: 1
location: example1
range: 10.1.0.1 - 10.1.0.20
first_ip: 10.1.0.1
last_ip: 10.1.0.20
used: 10
touched: 0
defined: 20
free: 10
percent: 50
touch_count: 10
touch_percent: 50
backup_count: 0
backup_percent: 0
status: 1
location: example2
range: 10.3.0.1 - 10.3.0.20
first_ip: 10.3.0.1
last_ip: 10.3.0.20
used: 9
touched: 0
defined: 20
free: 11
percent: 45
touch_count: 9
touch_percent: 45
backup_count: 0
backup_percent: 0
status: 1
Shared-networks:
location: example1
defined: 40
used: 21
touched: 0
free: 19
percent: 52.5
touch_count: 21
touch_percent: 52.5
backup_count: 1
backup_percent: 2.5
status: 1
Summary:
location: All networks
defined: 100
used: 43
touched: 0
free: 57
percent: 43
touch_count: 43
touch_percent: 43
backup_count: 2
backup_percent: 2
status: 0
number_of_ranges: 5
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

1
tests/expected/parser Symbolic link
View file

@ -0,0 +1 @@
complete

16
tests/expected/range4 Normal file
View file

@ -0,0 +1,16 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
example1 10.0.0.0 - 10.0.0.31 32 12 37.500 0 12 37.500
example1 10.1.0.1 - 10.1.0.31 31 10 32.258 0 10 32.258
example2 10.2.0.1 - 10.2.0.15 15 8 53.333 0 8 53.333
example2 10.3.0.1 - 10.3.0.7 7 7 100.000 0 7 100.000
All networks 10.4.0.1 - 10.4.0.1 1 1 100.000 0 1 100.000
Shared networks:
name max cur percent touch t+c t+c perc
example1 63 22 34.921 0 22 34.921
example2 22 15 68.182 0 15 68.182
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 86 38 44.186 0 38 44.186

10
tests/expected/range6 Normal file
View file

@ -0,0 +1,10 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
All networks dead:abba:1000:: - dead:abba:1000:ff:ffff:ffff:ffff:ffff 4.72237e+21 2 0.000 1 3 0.000
Shared networks:
name max cur percent touch t+c t+c perc
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 4.72237e+21 2 0.000 1 3 0.000

View file

@ -1,9 +1,9 @@
{
"active_leases": [
{ "ip":"10.0.0.5", "macaddress":"00:00:00:00:00:00" }
{ "ip":"10.0.0.5", "macaddress":"00:00:00:00:00:00", "starts":"", "ends":"", "hostname":"" }
],
"subnets": [
{ "location":"All networks", "range":"10.0.0.1 - 10.0.0.10", "defined":10, "used":1, "touched":0, "free":9 }
{ "location":"All networks", "range":"10.0.0.1 - 10.0.0.10", "first_ip":"10.0.0.1", "last_ip":"10.0.0.10", "defined":10, "used":1, "touched":0, "free":9, "percent":10, "touch_count":1, "touch_percent":10, "status":0 }
],
"shared-networks": [
],
@ -12,6 +12,12 @@
"defined":10,
"used":1,
"touched":0,
"free":9
"free":9,
"percent":10,
"touch_count":1,
"touch_percent":10,
"status":0
},
"trivia": {
}
}

View file

@ -2,6 +2,9 @@
<active_lease>
<ip>10.0.0.5</ip>
<macaddress>00:00:00:00:00:00</macaddress>
<starts></starts>
<ends></ends>
<hostname></hostname>
</active_lease>
<subnet>
<location>All networks</location>

16
tests/expected/shufled Normal file
View file

@ -0,0 +1,16 @@
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
All networks 10.4.0.1 - 10.4.0.20 20 3 15.000 0 3 15.000
example1 10.0.0.1 - 10.0.0.20 20 9 45.000 0 9 45.000
example1 10.1.0.1 - 10.1.0.20 20 4 20.000 0 4 20.000
example2 10.2.0.1 - 10.2.0.20 20 4 20.000 0 4 20.000
example2 10.3.0.1 - 10.3.0.20 20 3 15.000 0 3 15.000
Shared networks:
name max cur percent touch t+c t+c perc
example1 40 13 32.500 0 13 32.500
example2 40 7 17.500 0 7 17.500
Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 100 23 23.000 0 23 23.000

80
tests/expected/skip Normal file
View file

@ -0,0 +1,80 @@
--- skip ok ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
example1 10.0.0.1 - 10.0.0.20 20 11 55.000 0 11 55.000 1 5.000
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000 0 0.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000 0 0.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
example1 40 21 52.500 0 21 52.500 1 2.500
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000
--- skip warning ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
example1 10.0.0.1 - 10.0.0.20 20 11 55.000 0 11 55.000 1 5.000
example2 10.2.0.1 - 10.2.0.20 20 8 40.000 0 8 40.000 0 0.000
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000 1 5.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
example1 40 21 52.500 0 21 52.500 1 2.500
example2 40 17 42.500 0 17 42.500 0 0.000
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000
--- skip critical ok ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000 0 0.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000 0 0.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000
--- skip suppressed ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000 1 5.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
example1 40 21 52.500 0 21 52.500 1 2.500
example2 40 17 42.500 0 17 42.500 0 0.000
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000
--- skip minsize ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
example1 40 21 52.500 0 21 52.500 1 2.500
example2 40 17 42.500 0 17 42.500 0 0.000
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000
--- skip count ok ---
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc bu bu perc
example1 10.0.0.1 - 10.0.0.20 20 11 55.000 0 11 55.000 1 5.000
example1 10.1.0.1 - 10.1.0.20 20 10 50.000 0 10 50.000 0 0.000
example2 10.2.0.1 - 10.2.0.20 20 8 40.000 0 8 40.000 0 0.000
example2 10.3.0.1 - 10.3.0.20 20 9 45.000 0 9 45.000 0 0.000
Shared networks:
name max cur percent touch t+c t+c perc bu bu perc
Sum of all ranges:
name max cur percent touch t+c t+c perc bu bu perc
All networks 100 43 43.000 0 43 43.000 2 2.000

View file

@ -34,7 +34,7 @@ Sum of all ranges:
name max cur percent touch t+c t+c perc
All networks 100 43 43.000 0 43 43.000
0
== maxium ==
== maximum ==
Ranges:
shared net name first ip last ip max cur percent touch t+c t+c perc
All networks 10.4.0.1 - 10.4.0.20 20 5 25.000 0 5 25.000

29
tests/expected/statuses Normal file
View file

@ -0,0 +1,29 @@
{
"subnets": [
{ "location":"example1", "range":"10.0.0.1 - 10.0.0.20", "first_ip":"10.0.0.1", "last_ip":"10.0.0.20", "defined":20, "used":11, "touched":0, "free":9, "percent":55, "touch_count":11, "touch_percent":55, "status":4 },
{ "location":"example1", "range":"10.1.0.1 - 10.1.0.20", "first_ip":"10.1.0.1", "last_ip":"10.1.0.20", "defined":20, "used":10, "touched":0, "free":10, "percent":50, "touch_count":10, "touch_percent":50, "status":4 },
{ "location":"example2", "range":"10.2.0.1 - 10.2.0.20", "first_ip":"10.2.0.1", "last_ip":"10.2.0.20", "defined":20, "used":8, "touched":0, "free":12, "percent":40, "touch_count":8, "touch_percent":40, "status":4 },
{ "location":"example2", "range":"10.3.0.1 - 10.3.0.20", "first_ip":"10.3.0.1", "last_ip":"10.3.0.20", "defined":20, "used":9, "touched":0, "free":11, "percent":45, "touch_count":9, "touch_percent":45, "status":4 },
{ "location":"10.4.0.0/24", "range":"10.4.0.1 - 10.4.0.20", "first_ip":"10.4.0.1", "last_ip":"10.4.0.20", "defined":20, "used":5, "touched":0, "free":15, "percent":25, "touch_count":5, "touch_percent":25, "status":4 }
],
"shared-networks": [
{ "location":"example1", "defined":40, "used":21, "touched":0, "free":19, "percent":52.5, "touch_count":21, "touch_percent":52.5, "status":2 },
{ "location":"example2", "defined":40, "used":17, "touched":0, "free":23, "percent":42.5, "touch_count":17, "touch_percent":42.5, "status":2 },
{ "location":"10.4.0.0/24", "defined":20, "used":5, "touched":0, "free":15, "percent":25, "touch_count":5, "touch_percent":25, "status":1 }
]
}
== minsize
{
"subnets": [
{ "location":"example1", "range":"10.0.0.1 - 10.0.0.20", "first_ip":"10.0.0.1", "last_ip":"10.0.0.20", "defined":20, "used":11, "touched":0, "free":9, "percent":55, "touch_count":11, "touch_percent":55, "status":3 },
{ "location":"example1", "range":"10.1.0.1 - 10.1.0.20", "first_ip":"10.1.0.1", "last_ip":"10.1.0.20", "defined":20, "used":10, "touched":0, "free":10, "percent":50, "touch_count":10, "touch_percent":50, "status":3 },
{ "location":"example2", "range":"10.2.0.1 - 10.2.0.20", "first_ip":"10.2.0.1", "last_ip":"10.2.0.20", "defined":20, "used":8, "touched":0, "free":12, "percent":40, "touch_count":8, "touch_percent":40, "status":3 },
{ "location":"example2", "range":"10.3.0.1 - 10.3.0.20", "first_ip":"10.3.0.1", "last_ip":"10.3.0.20", "defined":20, "used":9, "touched":0, "free":11, "percent":45, "touch_count":9, "touch_percent":45, "status":3 },
{ "location":"10.4.0.0/24", "range":"10.4.0.1 - 10.4.0.20", "first_ip":"10.4.0.1", "last_ip":"10.4.0.20", "defined":20, "used":5, "touched":0, "free":15, "percent":25, "touch_count":5, "touch_percent":25, "status":3 }
],
"shared-networks": [
{ "location":"example1", "defined":40, "used":21, "touched":0, "free":19, "percent":52.5, "touch_count":21, "touch_percent":52.5, "status":2 },
{ "location":"example2", "defined":40, "used":17, "touched":0, "free":23, "percent":42.5, "touch_count":17, "touch_percent":42.5, "status":2 },
{ "location":"10.4.0.0/24", "defined":20, "used":5, "touched":0, "free":15, "percent":25, "touch_count":5, "touch_percent":25, "status":3 }
]
}

View file

@ -0,0 +1,3 @@
OK: Ranges - crit: 0 warn: 0 ok: 2; | range_crit=0 range_warn=0 range_ok=2 dead:abba:4000::2_r=1;203.2;228.6;0;254 dead:abba:4000::2_rt=0 dead:abba:1000::2_r=2;3.77789e+21;4.25013e+21;0;4.72237e+21 dead:abba:1000::2_rt=1
Shared nets - crit: 0 warn: 0 ok: 0; | snet_crit=0 snet_warn=0 snet_ok=0

37
tests/formats Executable file
View file

@ -0,0 +1,37 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
echo '=== color text' > tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM --color=always \
-l $top_srcdir/tests/leases/$IAM >> tests/outputs/$IAM
echo '=== html' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM --color=always --format=H \
-l $top_srcdir/tests/leases/$IAM |
sed '/was last modified at/d; /Generated using/d' >> tests/outputs/$IAM
echo '=== xml' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM -fx \
-l $top_srcdir/tests/leases/$IAM >> tests/outputs/$IAM
echo '=== csv' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM -fc \
-l $top_srcdir/tests/leases/$IAM >> tests/outputs/$IAM
echo '=== json' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM -fj --limit=33 \
-l $top_srcdir/tests/leases/$IAM >> tests/outputs/$IAM
echo '=== perfdata' >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/tests/confs/$IAM --perfdata --warning=20 --critical=40 \
-l $top_srcdir/tests/leases/$IAM >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

View file

@ -7,7 +7,8 @@ if [ ! -d tests/outputs ]; then
fi
dhcpd-pools -f J -c $top_srcdir/tests/confs/same-twice \
-l $top_srcdir/tests/leases/same-twice \
-o tests/outputs/same-twice-json
-l $top_srcdir/tests/leases/same-twice |
sed '/"version":"/d; /"conf_file_.*":/d; /"lease_file_.*":/d' \
>| tests/outputs/same-twice-json
diff -u $top_srcdir/tests/expected/same-twice-json tests/outputs/same-twice-json
exit $?

1
tests/leases/big-small Symbolic link
View file

@ -0,0 +1 @@
simple

241
tests/leases/binding-states Normal file
View file

@ -0,0 +1,241 @@
lease 10.0.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.0.0.1 {
binding state free;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.1 {
binding state abandoned;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.1 {
binding state expired;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.1 {
binding state released;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.1 {
binding state backup;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.0.0.2 {
binding state free;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.2 {
binding state abandoned;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.2 {
binding state expired;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.2 {
binding state released;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.2 {
binding state backup;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.0.0.3 {
binding state free;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.0.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.0.0.5 {
binding state expired;
hardware ethernet 00:00:00:00:00:05;
}
lease 10.0.0.6 {
binding state released;
hardware ethernet 00:00:00:00:00:06;
}
lease 10.0.0.7 {
binding state backup;
hardware ethernet 00:00:00:00:00:07;
}
lease 10.0.0.8 {
binding state none-existing-state;
hardware ethernet 00:00:00:00:00:08;
}
lease 10.0.0.9 {
binding state active;
hardware ethernet 00:00:00:00:00:09;
}
lease 10.0.0.20 {
binding state active;
hardware ethernet 00:00:00:00:00:10;
}
lease 10.0.0.21 {
binding state active;
hardware ethernet 00:00:00:00:00:11;
}
lease 10.1.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.1.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.1.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.1.0.3 {
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.1.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.1.0.5 {
binding state active;
hardware ethernet 00:00:00:00:00:05;
}
lease 10.1.0.6 {
binding state active;
hardware ethernet 00:00:00:00:00:06;
}
lease 10.1.0.7 {
binding state active;
hardware ethernet 00:00:00:00:00:07;
}
lease 10.1.0.8 {
binding state active;
hardware ethernet 00:00:00:00:00:08;
}
lease 10.1.0.9 {
binding state active;
hardware ethernet 00:00:00:00:00:09;
}
lease 10.1.0.10 {
binding state active;
hardware ethernet 00:00:00:00:00:10;
}
lease 10.2.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.2.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.2.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.2.0.3 {
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.2.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.2.0.5 {
binding state active;
hardware ethernet 00:00:00:00:00:05;
}
lease 10.2.0.6 {
binding state active;
hardware ethernet 00:00:00:00:00:06;
}
lease 10.2.0.7 {
binding state active;
hardware ethernet 00:00:00:00:00:07;
}
lease 10.2.0.8 {
binding state active;
hardware ethernet 00:00:00:00:00:08;
}
lease 10.3.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.3.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.3.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.3.0.3 {
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.3.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.3.0.5 {
binding state active;
hardware ethernet 00:00:00:00:00:05;
}
lease 10.3.0.6 {
binding state active;
hardware ethernet 00:00:00:00:00:06;
}
lease 10.3.0.7 {
binding state active;
hardware ethernet 00:00:00:00:00:07;
}
lease 10.3.0.8 {
binding state active;
hardware ethernet 00:00:00:00:00:08;
}
lease 10.3.0.9 {
binding state active;
hardware ethernet 00:00:00:00:00:09;
}
lease 10.4.0.0 {
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
lease 10.4.0.1 {
binding state active;
hardware ethernet 00:00:00:00:00:01;
}
lease 10.4.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:02;
}
lease 10.4.0.3 {
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.4.0.4 {
binding state active;
hardware ethernet 00:00:00:00:00:04;
}
lease 10.4.0.5 {
binding state active;
hardware ethernet 00:00:00:00:00:05;
}

1
tests/leases/cidr-v4 Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/leases/cidr-v6 Symbolic link
View file

@ -0,0 +1 @@
v6

1
tests/leases/formats Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/leases/parser Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/leases/range4 Symbolic link
View file

@ -0,0 +1 @@
complete

1
tests/leases/range6 Symbolic link
View file

@ -0,0 +1 @@
v6

198
tests/leases/shufled Normal file
View file

@ -0,0 +1,198 @@
lease 10.0.0.7 {
}
binding state active;
hardware ethernet 00:00:00:00:00:07;
hardware ethernet 00:00:00:00:00:10;
lease 10.2.0.4 {
lease 10.2.0.6 {
lease 10.0.0.11 {
binding state active;
}
hardware ethernet 00:00:00:00:00:03;
lease 10.3.0.9 {
}
hardware ethernet 00:00:00:00:00:04;
}
binding state active;
lease 10.1.0.7 {
}
}
lease 10.1.0.9 {
hardware ethernet 00:00:00:00:00:07;
hardware ethernet 00:00:00:00:00:01;
binding state active;
binding state active;
}
}
}
binding state active;
lease 10.4.0.1 {
}
lease 10.0.0.0 {
}
hardware ethernet 00:00:00:00:00:10;
}
}
binding state active;
hardware ethernet 00:00:00:00:00:00;
}
}
binding state active;
}
lease 10.3.0.2 {
hardware ethernet 00:00:00:00:00:01;
binding state active;
hardware ethernet 00:00:00:00:00:02;
binding state active;
lease 10.1.0.3 {
binding state active;
}
binding state active;
}
lease 10.1.0.1 {
lease 10.3.0.8 {
lease 10.2.0.1 {
hardware ethernet 00:00:00:00:00:07;
}
}
lease 10.4.0.0 {
hardware ethernet 00:00:00:00:00:01;
}
binding state active;
hardware ethernet 00:00:00:00:00:02;
lease 10.0.0.10 {
binding state active;
}
hardware ethernet 00:00:00:00:00:04;
hardware ethernet 00:00:00:00:00:11;
hardware ethernet 00:00:00:00:00:08;
binding state active;
hardware ethernet 00:00:00:00:00:08;
binding state active;
lease 10.2.0.5 {
hardware ethernet 00:00:00:00:00:01;
lease 10.1.0.8 {
lease 10.0.0.3 {
binding state active;
binding state active;
lease 10.0.0.1 {
lease 10.4.0.5 {
hardware ethernet 00:00:00:00:00:06;
hardware ethernet 00:00:00:00:00:06;
hardware ethernet 00:00:00:00:00:02;
lease 10.2.0.3 {
binding state active;
lease 10.1.0.10 {
binding state active;
}
}
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
}
hardware ethernet 00:00:00:00:00:05;
lease 10.0.0.2 {
}
binding state active;
}
hardware ethernet 00:00:00:00:00:06;
lease 10.3.0.6 {
lease 10.0.0.8 {
hardware ethernet 00:00:00:00:00:01;
lease 10.4.0.3 {
}
}
}
binding state active;
binding state active;
lease 10.1.0.6 {
lease 10.1.0.2 {
hardware ethernet 00:00:00:00:00:05;
binding state active;
}
}
lease 10.2.0.7 {
}
}
hardware ethernet 00:00:00:00:00:03;
binding state active;
}
binding state active;
hardware ethernet 00:00:00:00:00:03;
}
lease 10.1.0.0 {
hardware ethernet 00:00:00:00:00:04;
binding state active;
}
lease 10.3.0.1 {
lease 10.2.0.2 {
binding state active;
hardware ethernet 00:00:00:00:00:09;
}
binding state active;
hardware ethernet 00:00:00:00:00:00;
binding state active;
lease 10.0.0.6 {
hardware ethernet 00:00:00:00:00:02;
binding state active;
}
binding state active;
}
lease 10.3.0.0 {
lease 10.0.0.9 {
binding state active;
lease 10.0.0.4 {
hardware ethernet 00:00:00:00:00:08;
binding state active;
hardware ethernet 00:00:00:00:00:07;
hardware ethernet 00:00:00:00:00:00;
binding state active;
lease 10.1.0.4 {
lease 10.4.0.2 {
binding state active;
}
}
lease 10.3.0.4 {
hardware ethernet 00:00:00:00:00:05;
hardware ethernet 00:00:00:00:00:05;
binding state active;
binding state active;
lease 10.0.0.5 {
hardware ethernet 00:00:00:00:00:04;
binding state active;
hardware ethernet 00:00:00:00:00:02;
binding state active;
hardware ethernet 00:00:00:00:00:09;
hardware ethernet 00:00:00:00:00:08;
lease 10.2.0.8 {
}
binding state active;
binding state active;
hardware ethernet 00:00:00:00:00:06;
hardware ethernet 00:00:00:00:00:00;
lease 10.3.0.7 {
lease 10.4.0.4 {
}
hardware ethernet 00:00:00:00:00:04;
}
binding state active;
lease 10.3.0.3 {
hardware ethernet 00:00:00:00:00:03;
lease 10.2.0.0 {
binding state active;
binding state active;
hardware ethernet 00:00:00:00:00:05;
binding state active;
}
hardware ethernet 00:00:00:00:00:00;
binding state active;
lease 10.1.0.5 {
hardware ethernet 00:00:00:00:00:09;
lease 10.3.0.5 {
}

1
tests/leases/statuses Symbolic link
View file

@ -0,0 +1 @@
complete

23
tests/mustach Executable file
View file

@ -0,0 +1,23 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
remove='/gettimeofday:/d; /^localtime:/d; /^conf_file_/d; /lease_file_/d; /^template_file_/d; /^version:/d'
dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \
--mustach $top_srcdir/samples/mustach.template |
sed "$remove" >| tests/outputs/$IAM
echo "--- skip ok ---" >> tests/outputs/$IAM
dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \
--mustach $top_srcdir/samples/mustach.template --skip=ok --warning 44 |
sed "$remove" >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

30
tests/parser Executable file
View file

@ -0,0 +1,30 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
cat <<EOF >"./${IAM}-conf"
#shared-network "example3 " {
# subnet 10.0.6.0 netmask 255.255.255.0 {
# pool {
# range 10.0.6.1 10.0.6.20;
# }
# }
# subnet 10.1.7.0 netmask 255.255.255.0 {
# pool {
# range 10.1.7.1 10.1.7.20;
# }
# }
#}
include "tests/confs/complete";
EOF
dhcpd-pools -c "./${IAM}-conf" --color=never \
-l $top_srcdir/tests/leases/$IAM -o tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
rm -f "./${IAM}-conf"
exit $?

1
tests/range4 Symbolic link
View file

@ -0,0 +1 @@
test.sh

1
tests/range6 Symbolic link
View file

@ -0,0 +1 @@
test.sh

15
tests/shufled Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
#
# Minimal regression test suite.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -c $top_srcdir/tests/confs/$IAM --color=never \
--sort nimcptTenimcptTe --sort nimcptTe \
-l $top_srcdir/tests/leases/$IAM -o tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

Some files were not shown because too many files have changed in this diff Show more