Compare commits

..

355 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
Sami Kerola
4cd85b62ff
release: 2.28
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-06 17:48:56 +00:00
Sami Kerola
ace697b472
fix out of tree build tests
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-06 17:44:30 +00:00
Sami Kerola
1a7d982495
change NAN markup to make tests work on mac
For some unknown reason mac osx does not change NAN to negative in printout
when asking to do so.  To get rid of false positive test results change the
sign of NAN to positive, that may break something for someone if there are
people expecting -NAN when devision with zero happens.  But that sort of
breakage is pretty unlikely because it requires broken dhcpd.conf.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-06 11:46:07 +00:00
Sami Kerola
01aa13cf43
test all sorting options
Not perfect test, but atleast something.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-05 19:51:53 +00:00
Sami Kerola
da4b7a783a
add --warn-count and --crit-count test, and fix related bug
I should consider writing tests before features.  Sadly recently added new
options did not even work.  Oh well, at least I did not release them before
noticing this.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-05 19:38:08 +00:00
Sami Kerola
15802d6648
unify quotation in error messages
Use quote() from gnulib to do this.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-05 19:00:32 +00:00
Sami Kerola
d6486e7730
make usage() easier to read
None-continuous print out blocks are difficult.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-05 18:59:40 +00:00
Sami Kerola
bd45266f74
drop a core when bug condition happens
Having a core will help enormously debugging these issues.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-05 18:50:28 +00:00
Sami Kerola
8fca82f148
print include system error message when output fails
Users want to know why write fail - was it because disk full, or destination
read-only, or IO error, and so on.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-04 20:35:35 +00:00
Sami Kerola
f5cd7383e4
fix improve variable names
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-04 19:32:50 +00:00
Sami Kerola
49835cccb5
fix doxygen build
And .gitignore doxygen related outputs.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-03 21:35:13 +00:00
Sami Kerola
98bcdf9378
simplify output format selection, and passing
Use of enum is a lot more readable than passing strings, and comparing
characters, around.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-01 23:25:54 +00:00
Sami Kerola
b524296016
use bitmap for booleans and other config that has known size
Bitmaps are more c style than bool coming from c++ land.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-01 23:24:14 +00:00
Sami Kerola
5ed9958b69
fix protocol specifier in html output
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-12-01 21:58:52 +00:00
Sami Kerola
0369340710
remove upper limit of sort order definitions
Unlikely to be needed by anyone, but because arbitrary limits are from code
style point of view ugly.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-30 00:50:18 +00:00
Sami Kerola
327691f34a
use more descriptive names in limit bits enum definition
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-29 23:36:19 +00:00
Sami Kerola
4aff49ed80
correct return value FIXME items
Not all markups were quite right.  The output_* functions must return an
int.  The rest were as a matter of fact correct.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-28 21:03:38 +00:00
Sami Kerola
f11ca0bec2
fix typo in README
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-28 20:51:18 +00:00
Sami Kerola
1299737d76
make html output to use Bootstrap and DataTables
This make the table output good looking, and allows users to click table
headings to sort data by column without rerunning the analysis.
Unfortunately this change is breaking change, meaning the old CSS tags are
no longer supported, nor partial html output that printed only the table.

Proposed-by: Aaron Paetznick <aaronp@critd.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-28 20:37:23 +00:00
Sami Kerola
c7917152d3
improve README file instructions
Proposed-by: Derrick Lin <d.lin@garvan.org.au>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-28 11:22:28 +00:00
Sami Kerola
5cede1ff31
add --warn-count and --crit-count options to suppress alarm noise
Alarm criteria based solely on percentage was found to be difficult to be
tricky to setup in environments that has small ranges and big shared-nets
mixed up together.  These two new options should help making alarming more
useful.

Requested-by: Frank Bulk <fbulk@mypremieronline.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-28 00:33:12 +00:00
Sami Kerola
7f3d553c7f
add --snet-alarms option to suppress excess range alarms
Some users may not want to have alarms about ranges that are part of a
shared-network, so allow them to suppress such.

Requested-by: Frank Bulk <fbulk@mypremieronline.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-27 23:42:23 +00:00
Sami Kerola
99b6af70ef
update doxygen.conf file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-25 22:02:41 +00:00
Sami Kerola
2528c4c9d6
make binary exec path dynamic in scripts referring to it
Everything should just work out of the box without poking.  This change
makes that goal to be yet agian one step closer.  In same go make all
autotools related variable substitutions better.

Requested-by: Martijn van Brummelen <martijn@brumit.nl>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-11-25 21:53:29 +00:00
Sami Kerola
c30c122027
fix couple compiler warnings
src/getdata.c:248:22: warning: 'range_p' may be used uninitialized in this
function [-Wmaybe-uninitialized]
src/other.c:383:1: warning: control reaches end of non-void function
[-Wreturn-type]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-10-26 22:43:31 +00:00
Sami Kerola
535dfc4fc2
portability: Solaris 10 does not have err.h
Use error(3) function, that has gnulib portability fixes, instead of err(3)
and warn(3) family.

Reported-by: Anton Tkachev <antont@bk.ru>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-10-26 22:29:32 +00:00
Sami Kerola
fae20302cf release: 2.27
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-09-05 13:35:44 +01:00
Sami Kerola
167c4b6989 gitignore: update gnulib file list
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-09-05 13:34:41 +01:00
Sami Kerola
d8aef85d01 man: fix character class change
Debian package lint found going back to roman mode was broken.

Reported-by: Martijn van Brummelen <martijn@brumit.nl>
Signed-off-by: Sami Kerola <kerolasa@cloudflare.com>
2015-09-05 13:15:19 +01:00
Sami Kerola
cf26e17fe7 add hint about configure options to README
Proposed-by: Tim Cantin <tcantin@wellesley.edu>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-05-29 09:18:08 +01:00
Sami Kerola
9d1241c006 improve html output
Remove unnecessary html indentation, so that there is less page content
to transfer.  Right align the network names, and IP's so that they are
easier to read.  And ensure quoting is done correctly.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-05-02 19:40:06 +01:00
Sami Kerola
c4e5ef6198 add xml format check
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-05-02 18:51:39 +01:00
Sami Kerola
0d6c61d437 add touched addresses counts to xml and json reports
For some reason missing information has been overlooked for years.
Perhaps there is aren't that many users who are interested of the touched
addresses.

Proposed-by: Aaron Paetznick <aaronp@critd.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-05-02 18:48:52 +01:00
Sami Kerola
73b357484d output: remove empty element from xml
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-05-02 18:00:10 +01:00
Sami Kerola
735c5db817 docs: remove todo items that will never happen
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-04-01 23:15:38 +01:00
Sami Kerola
34dd1dee6e docs: remove very basic git usage info
This is not a git beginner manual project.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2015-04-01 23:11:28 +01:00
Sami Kerola
c7379e3e25 release: 2.26
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-15 10:03:41 +00:00
Sami Kerola
cfbd69c20b maint: remove unnecessary braces, spaces, update gnulib .gitignore
Improve code readability, and small maintenance.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-15 09:44:28 +00:00
Sami Kerola
33894fba74 other: disallow unsigned counter ever to have minus value
src/other.c:398:4: runtime error: unsigned integer overflow: 0 - 1 cannot
be represented in type 'unsigned int'

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-14 21:57:21 +00:00
Sami Kerola
8e076fcc4f output: avoid division by zero
This correction makes the shared networks alarming to work when all
available leases are used.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-14 21:54:27 +00:00
Sami Kerola
0705b0c17f tests: add regression test to avoid shared-net off by one alarming issue
This tests ensures the problem fixed by Wolfgang Steudel cannot reoccur.
See the reference commit for details.

Reference: 5519763ba9
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-14 20:13:08 +00:00
Wolfgang Steudel
5519763ba9 alarming: include last shared network in alarming [off by one]
We have defined some shared networks with a couple of address ranges
and wanted to monitor the availability of free IP addresses in the
shared networks.  We were wondering why in some cases there was no
warning, although one shared network's usage was above the threshold.

We found the reason.  In output_alarming() the code was not skipping
"All networks", but missing the last shared network in the list.
Moving "shared_p++" to the beginning of the loop seems to solve the
bug.

Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Wolfgang Steudel <wolfgang.steudel@tu-ilmenau.de>
2014-11-14 19:41:21 +00:00
Sami Kerola
190df198a4 output: prefer thread safe function localtime_r()
While the dhcpd-pools might not be threading there is no reason why
software should use worse function when always correct alternative is
equally easy to use.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-09 22:31:30 +00:00
Sami Kerola
e401c2c7e6 other: reduce variable scope
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-09 22:25:25 +00:00
Sami Kerola
0d2b30b62d getdata: fix buffer overflow [AddressSanitizer]
==12031==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x61900000a980 at pc 0x0000004bca22 bp 0x7fff580dd6d0 sp 0x7fff580dd6c8
WRITE of size 1 at 0x61900000a980 thread T0
    #0 0x4bca21 in parse_config /home/src/dhcpd-pools/src/getdata.c:323:4
    #1 0x4bb332 in main /home/src/dhcpd-pools/src/dhcpd-pools.c:266:2
    #2 0x7fe03ecc403f in __libc_start_main (/usr/lib/libc.so.6+0x2003f)
    #3 0x4b9c0c in _start (/home/src/dhcpd-pools/dhcpd-pools+0x4b9c0c)

0x61900000a980 is located 0 bytes to the right of 1024-byte region
[0x61900000a580,0x61900000a980) allocated by thread T0 here:
    #0 0x49c58b in __interceptor_malloc (/home/src/dhcpd-pools/dhcpd-pools+0x49c58b)
    #1 0x4cbc0d in xmalloc /home/src/dhcpd-pools/lib/xmalloc.c:41:13
    #2 0x4bbed8 in parse_config /home/src/dhcpd-pools/src/getdata.c:195:9
    #3 0x4bb332 in main /home/src/dhcpd-pools/src/dhcpd-pools.c:266:2
    #4 0x7fe03ecc403f in __libc_start_main (/usr/lib/libc.so.6+0x2003f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/src/dhcpd-pools/src/getdata.c:323 parse_config

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-11-02 21:56:43 +00:00
Sami Kerola
bd5877bf4f update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-10-24 20:58:27 +01:00
Sami Kerola
15502d3c97 getdata: fix buffer-overflows reported by address sanitizer
These happen when input configuration or leases files are empty.

==12876==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x61900000a480 at pc 0x000000487442 bp 0x7fffbc3e16b0 sp 0x7fffbc3e0e70
READ of size 1025 at 0x61900000a480 thread T0
    #0 0x487441 in __interceptor_strlen (/home/src/dhcpd-pools/dhcpd-pools+0x487441)
    #1 0x4bbb10 in parse_leases /home/src/dhcpd-pools/src/getdata.c:112:35
    #2 0x4bb337 in main /home/src/dhcpd-pools/src/dhcpd-pools.c:268:2
    #3 0x7f51909bf03f in __libc_start_main (/usr/lib/libc.so.6+0x2003f)
    #4 0x4b9c0c in _start (/home/src/dhcpd-pools/dhcpd-pools+0x4b9c0c)

0x61900000a480 is located 0 bytes to the right of 1024-byte region
[0x61900000a080,0x61900000a480)
allocated by thread T0 here:
    #0 0x49c58b in __interceptor_malloc (/home/src/dhcpd-pools/dhcpd-pools+0x49c58b)
    #1 0x4cbbcd in xmalloc /home/src/dhcpd-pools/lib/xmalloc.c:41:13
    #2 0x4bb801 in parse_leases /home/src/dhcpd-pools/src/getdata.c:96:9
    #3 0x4bb337 in main /home/src/dhcpd-pools/src/dhcpd-pools.c:268:2
    #4 0x7f51909bf03f in __libc_start_main (/usr/lib/libc.so.6+0x2003f)

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-10-24 20:57:57 +01:00
Sami Kerola
74c6ef2566 update kernel.org url in README
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-08-09 19:34:18 +01:00
Sami Kerola
e09f655a7b add appropriate sorting function for struct leases_t
The HASH_SORT in analyze needs this.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-08-09 19:28:23 +01:00
Sami Kerola
965875d20b declare global variables only once
Global variable declarations belong near main, and the header has to have
extern reference to them.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-08-09 19:09:04 +01:00
Sami Kerola
4392a5b917 reindent all files
And update the indent.pro to match with the style I like.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-07-20 18:05:00 +01:00
Sami Kerola
9090cfb1d7 news: add the note about .sig pgp key id
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-05-31 18:54:01 +01:00
Sami Kerola
6b267387cc release: 2.25
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-05-31 18:14:23 +01:00
Sami Kerola
6e680ee04f contrib: add release siging key to contrib/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-05-31 18:13:21 +01:00
Sami Kerola
502daf8306 build-sys: require automake 1.12 to get working test-driver
With older automake versions one can end up after ./bootstrap with
situation where test-driver script is missing, and subsequent compilation
fails.  Requiring automake 1.12 should usually help, but unfortunately
the case Dennis reported is different.

Something goes wrong with 1.13 and autoconf 2.69, in 32 bit RHEL system.
That sort of system seems to require AM_PROG_CC_C_O, and even when that
is added following error happens.  It is yet unknown to me why this is
the case.

parallel-tests: error: required file 'build-aux/test-driver' not found

Reference: http://git.savannah.gnu.org/cgit/automake.git/tree/NEWS?id=v1.12#n113
Reported-by: Dennis Ortsen <dortsen@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-04-13 21:14:42 +01:00
Sami Kerola
0f66becd57 build-sys: update bootstrap script
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-04-13 20:55:34 +01:00
Sami Kerola
eb55946595 output: use symbolic exit values for nagios commands
And ensure the exit values are set no matter how user will limit output.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-03-24 21:56:34 +00:00
Sami Kerola
5454ab7086 build-sys: update gitinore file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-03-24 21:38:10 +00:00
Sami Kerola
f3e282f122 output: make nagios output have performance data
Just in case someone wants to graph what is going on.

Reference: http://nagios.sourceforge.net/docs/3_0/pluginapi.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2014-03-24 21:34:35 +00:00
Sami Kerola
ca0b1c3262 tests: fix testing error
The commit 7fc354827a introduced an symlink
that end up to update simple test causing it to break.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-17 18:39:47 +00:00
Sami Kerola
d089a19fb5 generic: use pure and const function attributes when possible
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-17 18:25:52 +00:00
Sami Kerola
affb3d70a3 thanks: add Fredrik Lysén & Conor McCarthy
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-08 21:01:21 +00:00
Sami Kerola
6b88e8d872 man: add tip analysis of include files can be useful
Reported-by: Fredrik Lysén <fredrik.lysen@uadm.uu.se>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-08 20:50:26 +00:00
Sami Kerola
7fc354827a getdata: fix consecutive range definition regression
The added test demonstrates the issue.  If a did not end with whitespace
it was skipped.

Reported-by: Fredrik Lysén <fredrik.lysen@uadm.uu.se>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-08 20:30:28 +00:00
Sami Kerola
48caf5fb42 getdata: add missing HAVE_POSIX_FADVISE protection
Reported-by: Conor McCarthy <mr.spuratic@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-08 19:21:19 +00:00
Sami Kerola
631bf0bf7c build-sys: use more strict method to check __builtin_expect
The problem with the detection of gcc's __builtin_expect, the autoconf
set up uses EX_COMPILE_IFELSE which only compiles the test code with gcc
-c, it does not link so a missing __builtin_expect is treated as a
missing symbol and is not detected.

Reported-by: Conor McCarthy <mr.spuratic@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-08 19:19:27 +00:00
Sami Kerola
1eca347196 release: 2.24
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-03 16:53:49 +00:00
Sami Kerola
6379ace9c7 getdata: fix one ip ranges when they have trailing spaces in definition
Ranges that defined single IP and followed each other, for example

range 10.20.30.40 ;
range 10.20.30.41 ;
range 10.20.30.42 ;

were misinterpreted, and every second (the .41 in example) were skipped.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-03 16:52:05 +00:00
Sami Kerola
d2d8abd660 various: fix memory leaks
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-11-03 14:30:37 +00:00
Sami Kerola
8da98bbc89 various: split functions to IPv4 and IPv6 versions
The code selection will be set with function pointer, which avoids
numerous IP version checks.  As a result with some inputs the analysis
runs quicker.  Most users will not notice much of difference.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-21 12:37:52 +01:00
Sami Kerola
97c6f0292f getdata: split busy function to segments used via function pointer
When it is known IPv4 is in use there is no need to spend time with if
statements checking whether IPv6 is in use.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-18 00:56:54 +01:00
Sami Kerola
5b8ad97611 getdata: memccpy() is better than own similar function
The memccpy() is maintained in libc so there is no reason to reimplement
similar functionality within this software.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-18 00:05:16 +01:00
Sami Kerola
5189333c95 analyze: remove unnecessary function
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-17 22:58:53 +01:00
Sami Kerola
20ec1c2b42 getdata: use correct file caching advice
The POSIX_FADV_NOREUSE is more appropriate considering dhcpd-pools may
need cache, but not necessarily.

Reference: http://lwn.net/Articles/449420/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-10 21:36:46 +01:00
Sami Kerola
7c872ef8d7 build-sys: AC_PROG_CC_C99 is obsolete; use AC_PROG_CC
Reference: http://lists.gnu.org/archive/html/autoconf-commit/2012-10/msg00001.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-07 16:56:46 +01:00
Sami Kerola
e8f8c04979 build-sys: update gnulib modules
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-07 16:55:31 +01:00
Sami Kerola
47582ed8d8 other: memcmp() is tiny bit quicker than strncmp()
With the large input samples I have use of memcmp makes run to take about
2-3% less time.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-09-02 22:21:32 +01:00
Sami Kerola
06ffa5ed04 xstrstr: speed up analysis by avoiding string comparisons
With large input one should see cut 15% for overall run time.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-08-31 00:30:28 +01:00
Sami Kerola
d70b08244f thanks: Dan Pritts
For good ideas how to improve alarming.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-12 20:01:20 +01:00
Sami Kerola
3944e289c8 docs: add an example how to use limits with alarming
Proposed-by: Dan Pritts <danno@umich.edu>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-12 19:59:50 +01:00
Sami Kerola
57ddd4f785 tests: test small network alarm ignoring
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-12 19:32:27 +01:00
Sami Kerola
28f1e8c54c output: allow user to ignore small ranges and shared networks
Some have configuration which combines small ranges such as one host, and
greater address ranges that are important to monitor.  Especially the one
host ranges tend to cause a lot of false-positive alarms, as they are
immediately 100% full when a machine requests an address.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-12 19:29:44 +01:00
Sami Kerola
4becf97fb3 docs: inform how the limits affect to printing when alarming is in use
Proposed-by: Dan Pritts <danno@umich.edu>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-11 20:47:09 +01:00
Sami Kerola
978ddeddeb tests: fix tests to use the new OK printing limit
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-11 20:37:55 +01:00
Sami Kerola
9f676f5276 output: allow alarming, in case of success, be silent
This will allow runnign dhcpd with cron, and when nothing is wrong emails
will not be sent.

Proposed-by: Dan Pritts <danno@umich.edu>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-11 20:37:37 +01:00
Sami Kerola
c0e7b50bd3 tests: add alarming tests
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-10 22:42:25 +01:00
Sami Kerola
08c9bcc502 output: make output limits to apply to alarm return values
The earlier behavior made alarming nearly impossible to use for shared
networks only, as they often are expected to be whole lot less full than
ranges.  Unfortunately if a alarm level was exceeded either by range or
shared network the exit value changed.  In most of the cases that lead
alarms to be sent, without sensible message.

Reported-by: Dan Pritts <danno@umich.edu>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-07-10 22:34:47 +01:00
Sami Kerola
7de719a80c build-sys: update configure.ac
Run autoupdate, and fix few items manually such as prefer AS_CASE rather
than shell case clause.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-06-23 13:07:27 +01:00
Sami Kerola
3f3d447ad8 release: 2.23
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-05-11 17:41:24 +01:00
Sami Kerola
824a6aec73 build-sys: update bootstrap from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-05-11 17:35:38 +01:00
Sami Kerola
8dba1c749d gnulib: add gnulib modules
Some systems, such as freebsd, does not have program_invocation_short_name
available.  There are also problems finding AF_INET{,6} definitions.

CC: Peter Fraser <p_fraser@hotmail.com>
Reported-by: Ryan Steinmetz <zi@freebsd.org>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-05-11 17:09:25 +01:00
Sami Kerola
0002aa57e6 release: 2.22
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-24 22:46:21 +01:00
Sami Kerola
30238e9d1c build-sys: use non-recursive build
For reasons see excellent paper 'Recursive Make Considered Harmful' by
Peter Miller.

References: http://miller.emu.id.au/pmiller/books/rmch/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-24 22:46:04 +01:00
Sami Kerola
0495ea4edf build-sys: fix gnulib function order
gl_EARLY should be called before gl_INIT

References: http://www.gnu.org/software/gnulib/manual/html_node/Initial-import.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-24 21:12:37 +01:00
Sami Kerola
ab535d8ab1 tests: add a test for one ip range
A regression test for commit ffffbc9 fix.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-22 23:16:18 +01:00
Sami Kerola
ffffbc96cc getdata: make single address ranges work
The dhcpd.conf can contain single IP range definitions, such as

range 10.20.30.40;

and they must be understood similar way as the range definiton would have
two IP's that are the same IP, e.g.,

range 10.20.30.40 10.20.30.40;

Reported-by: Joey D. <jobewan@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-22 23:08:21 +01:00
Sami Kerola
b24fc42ec8 getdata: make a lease address detection more robust
The commit 805d353584 did not fix all
possible problem cases.  This commit attempts to address remaining
issues.

Reported-by: Joey D. <jobewan@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-22 22:47:25 +01:00
Sami Kerola
1a7649beb3 tests: check how command works with invalid input
Lack of this check resulted to bug that was shipped to users, which was
fixed in commit 805d353.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-21 14:37:34 +01:00
Sami Kerola
805d353584 getdata: certain input files caused SIGSEGV
When dhcpd.conf file got to be parsed such way that IP version could not
be determined the dhcpd.lease file parsing resulted to SIGSEGV.

Reported-by: Joey D. <jobewan@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-21 14:30:21 +01:00
Sami Kerola
5966360f12 getdata: posix_fadvise() error checking
Helmut reported run of 'make check' failing in debian pbuilder
environment.  The posix_fadvise() functions were failing with a message
such as

 dhcpd-pools: parse_config: fadvise ../tests/confs/complete: Cannot allocate memory

which to me is likely error in how an error is determined.  Relying on
errno value not being mangled by libc is unreliable.  Attempt to fix this
is simple, check return values of these function calls and ignore the
errno.

Reported-by: Helmut Grohne <h.grohne@cygnusnetworks.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-21 14:05:59 +01:00
Sami Kerola
90c1a4e4c5 build-sys: reorder gnulib macro in relation to C standard
When ./bootstrap has ran it tells to

  - invoke gl_EARLY in ./configure.ac, right after AC_PROG_CC_C99,

Also AC_USE_SYSTEM_EXTENSIONS is needed to suppress spurious gnulib
warnings.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:17:52 +01:00
Sami Kerola
3e677d8a24 tests: binding states commit needs to be reflected in expected results
The commit b858a4778b changed a little bit
to which category various binding states fall into.  That has to be
reflected in expected test results.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:04:24 +01:00
Sami Kerola
7c34231004 build-sys: update git-version-gen from gnulib
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:04:24 +01:00
Sami Kerola
d2b7d10dbc build-sys: ensure distribution has version file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:04:23 +01:00
Sami Kerola
327b601ea4 docs: fix spelling mistakes in manual page
Also quote dashes used in EXAMPLEs section.

Reported-by: Helmut Grohne <h.grohne@cygnusnetworks.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:04:23 +01:00
Sami Kerola
5ee1aca2b9 build-sys: add git-version-gen and test.sh to release package
Without this patch autoreconf, when done with release tarball, fails like
this:

$ autoreconf -f -i
sh: 1: build-aux/git-version-gen: not found
configure.ac:12: error: AC_INIT should be called with package and version arguments
/usr/share/aclocal-1.11/init.m4:26: AM_INIT_AUTOMAKE is expanded from...
configure.ac:12: the top level
autom4te: /usr/bin/m4 failed with exit status: 1
aclocal: /usr/bin/autom4te failed with exit status: 1
autoreconf: aclocal failed with exit status: 1

Further down the road tests start to fail after autoreconf.

make[4]: Leaving directory `/home/grohne/debian/dhcpd-pools-debian/tests'
make[3]: *** No rule to make target `../tests/test.sh', needed by `check-local'.  Stop.
make[3]: Leaving directory `/home/grohne/debian/dhcpd-pools-debian/tests'
make[2]: *** [check-am] Error 2
make[2]: Leaving directory `/home/grohne/debian/dhcpd-pools-debian/tests'
make[1]: *** [check-recursive] Error 1
make[1]: Leaving directory `/home/grohne/debian/dhcpd-pools-debian'

Which is a symptom of not having test.sh in distribution.

Reported-by: Helmut Grohne <h.grohne@cygnusnetworks.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-09 21:04:19 +01:00
Cheer Xiao
b858a4778b getdata: treat binding states abandoned, expired and release like free 2013-04-07 20:16:44 +08:00
Sami Kerola
cdf2c81f31 build-sys: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-05 23:21:49 +01:00
Sami Kerola
c3e492165c cppcheck: fix variable scoping
[src/dhcpd-pools.c:68]: (style) The scope of the variable 'c' can be reduced.
[src/getdata.c:210]: (style) The scope of the variable 'c' can be reduced.
[src/hash.c:102]: (style) The scope of the variable 'l' can be reduced.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-04-05 23:13:10 +01:00
Sami Kerola
23aae87356 include: add missing declarations to dhcpd-pool.h
This will fix eight warnings similar to the example below.

sort.c:104:5: warning: no previous declaration for 'comp_ip' [-Wmissing-declarations]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-03-08 23:38:25 +00:00
Sami Kerola
8e2da89c88 tests: add complete check including multiple ranges and shared networks
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-16 12:56:22 +00:00
Sami Kerola
f3a476ba52 release: 2.21
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 20:30:32 +00:00
Sami Kerola
625c54d834 docs: fix doxygen make distcheck breakage
The docs directory needs to be handled properly, e.g., create Makefile
which nothing, when doxygen is not enabled.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 20:28:26 +00:00
Sami Kerola
e50d0a7d38 tests: fix make distcheck
It is best to make dhcpd-pools used from PATH, which makes out of tree
build check to work.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 20:28:26 +00:00
Sami Kerola
34f73dbae1 docs: thanks to Cheer Xiao this software has IPv6 support
The prof. Xing Li in Tsinghua University, with LI Zimu, asked Cheer to
make the dhcpd-pools more usable for them which I, as a project
maintainer, could not be more pleased.  Whils making the IPv6 analysis to
work Cheer also fixed various other issues.  Kudos to him, and big thanks
to everyone.

CC: Xing Li <xing@cernet.edu.cn>
CC: LI Zimu <lzm@cernet.edu.cn>
CC: Cheer Xiao <xiaqqaix@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 17:41:38 +00:00
Sami Kerola
632e97834b build-sys: update .gitignore files
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 17:30:01 +00:00
Sami Kerola
3be3f34bd4 build-sys: allow tests run parallel
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2013-01-15 17:27:50 +00:00
Cheer Xiao
478bbe1b44 output: fix doc of output_double 2013-01-09 10:19:06 +08:00
Cheer Xiao
ff7ca8c419 tests: update expected/v6
The range size in the old file was also incorrect.
2013-01-08 23:00:57 +08:00
Cheer Xiao
75d979bb00 sort: let comp_* functions compare double 2013-01-08 22:59:35 +08:00
Cheer Xiao
9c4184bd9a counting: Let get_range_size return double 2013-01-08 22:57:33 +08:00
Cheer Xiao
afd9f77051 sort: let field_selector return NULL at the end 2013-01-08 22:57:07 +08:00
Cheer Xiao
6820c9fc09 fix: Put prototype of field_selector back to dhcpd-pools.h
It's needed in main to check unknown field selectors.
2013-01-08 22:52:54 +08:00
Cheer Xiao
6642335c8a counting & output: Convert all counters to double 2013-01-08 22:47:50 +08:00
Cheer Xiao
39e1fb9e5a sort: Get rid of global comparer 2013-01-08 22:41:41 +08:00
Cheer Xiao
137c1d37c2 sort: Use a comparer instead of returner
This resolves the FIXME of sorting ranges according to first_ip in IPv6 mode.
2013-01-08 22:41:36 +08:00
Sami Kerola
4051a953bd smatch scan: fix few warnings
dhcpd-pools.h:79:17: warning: comma at end of enumerator list [-pedantic]
hash.c:85 delete_lease() info: redundant null check on lease->ethernet calling free()

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-20 20:04:06 +00:00
Sami Kerola
70c65f4d59 getdata: be consistant with symbolic numbers
The program counts quotes, which is never true/false value, and one of
the symbolic parse state values was missed in bd5ee58.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 23:38:37 +00:00
Sami Kerola
51143b6b3c clean up: fix few indentation slips
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 23:28:58 +00:00
Sami Kerola
82df7c98d4 clean up: rename get_order() to merge() and mark static
No other function than mergesort_ranges() can use the merge(), so calling
it with rather generic name and making it static seems right to me.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 23:26:03 +00:00
Sami Kerola
bd5ee58a3f clean up: convert parsing magic numbers to symbolic values
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 23:26:03 +00:00
Sami Kerola
4b014eba1c clean up: use enum as symbolic bit masks
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 23:25:57 +00:00
Sami Kerola
d3ee104a59 clean up: move global variables to config structure
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 22:56:07 +00:00
Sami Kerola
b59e980cab hash: make delete to use HASH_ITER if it is available
This commit also makes the functions ansi C compliant by adding void to
function argument list.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 22:43:32 +00:00
Sami Kerola
a9d2d9c82f clean up: move code to more proper location
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 22:40:00 +00:00
Sami Kerola
2008e1a047 clean up: remove unused functions
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 22:27:58 +00:00
Sami Kerola
f1411858cb backup counting: fix output regression
The backup count was not printed at all.  This bug was introduced in
version 2.17 (May 2012) when the uthash was taken in use.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 22:15:14 +00:00
Sami Kerola
3471c91796 docs: add doxygen tags, configuration file, and autotooling
When ./configure --enable-doxygen is used one can browse internal api
documentation from docs/html directory.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-09 21:06:32 +00:00
Sami Kerola
aa7928b3ab output ethernet: do not crash if ethernet is missing
Real dhcpd.leases file should always have ethernet address markup, but
test data or malformed files might not have.  Even if the check is 99.99%
useless there are the corner cases, and crashing at them is not good.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-07 22:32:28 +00:00
Sami Kerola
fdc560bab9 ouput format: fix active lease printing
Earlier ethernet address collection did not remove duplicated.  Basically
the problem was the same as in problem fixed in commit
ae7747db87, but this time affecting only
the ethernet addresses.  The fix is, as one can see, to make ethernet
collection to share structure with the lease, so that if one is wrong
both are wrong the same way.

Reported-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-07 21:55:06 +00:00
Sami Kerola
d8aae53968 tests: add json tests, and make fail output loud
Gilles reported the full-json is currently broken, which the new check
demonstrates.  Luckily the issue occurs only when active leases details
are being queried, leaving the count to be correct.  That said bug is a
bug, and that should be corrected.

Reported-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-07 20:25:21 +00:00
Sami Kerola
a768049f3e json output: use defined output file for all printing
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-07 20:12:34 +00:00
Gilles Bouthenot
443b197901 contrib: add munin plugins
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
2012-12-05 18:18:03 +00:00
Gilles Bouthenot
bc654bcc68 json output: bugfix: correct range specify only first ip
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
2012-12-05 18:05:08 +00:00
Gilles Bouthenot
e9d196e816 json output: remove useless, empty fields
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
2012-12-05 18:04:19 +00:00
Gilles Bouthenot
48a23c94e5 json output: add newline at end
And remove extra empty lines where they are not needed.

Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
2012-12-05 18:02:51 +00:00
Sami Kerola
d34259092d build-sys: more clean ups
The gnulib will set AC_GNU_SOURCE equivivelant if necessary.  The awk is
relevant only for contrib stuff, and compiler program was something I had
not understood quite right some years ago when I added it.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-04 22:08:15 +00:00
Gilles Bouthenot
a302bc6829 output: add json format support
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Gilles Bouthenot <gilles.bouthenot@univ-fcomte.fr>
2012-12-04 21:30:09 +00:00
Sami Kerola
179e2ac147 output: remove unnecessary new line printing
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-02 21:36:39 +00:00
Sami Kerola
a2fa69a403 tests: add v6 check
The counting of total maximum address space seems to be broken at the
moment, and the check is expected to fail until a counting fix is
available.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-02 21:33:07 +00:00
Sami Kerola
1424db9427 build-sys: update .gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-12-02 20:41:06 +00:00
Cheer Xiao
a57d399643 IPv6: add DHCPv6 support
The DHCP version is determined according to the first IP address that
appears in the configuration file.  Caveat; counters are of native long
type.  Since IPv6 address space has 2^128 addresses, they are subject to
overflow.

[Sami Kerola:  This commit also fixed a percent sorting bug, which has
been broken always.  See changes ret_percent() for the fix.]

CC: LI Zimu <lzm@cernet.edu.cn>
CC: Xing Li <xing@cernet.edu.cn>
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Cheer Xiao <xiaqqaix@gmail.com>
2012-12-02 20:35:54 +00:00
Sami Kerola
71bcee14e9 tests: add basic tests
The tests can be ran using 'make check'.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-29 21:02:40 +00:00
Sami Kerola
6684772550 tools: add indent command configuration file
And reindent all files.

Reference: http://www.gnu.org/software/indent/
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-28 19:57:19 +00:00
Sami Kerola
761c9560d7 build-sys: remove c++ compiler check
I have no idea why that was there.  My guess is that I had no idea at the
time I added the line what it does.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-28 19:48:10 +00:00
Sami Kerola
3e0faec144 release: 2.20
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:25:56 +00:00
Sami Kerola
7685d08cf0 man: fix errors in alarm warning and critical options text
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:23:38 +00:00
Sami Kerola
9df90042e2 build-sys: make alarm warning & critical default configurable
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:03:19 +00:00
Sami Kerola
7e403b50b4 build-sys: clean up configure.ac
Remove checks that are done in gnulib, and reindent autotools code.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:03:19 +00:00
Sami Kerola
c66d13774b build-sys: update gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:03:19 +00:00
Sami Kerola
c48a8d411f man: use configured dhcpd.conf and dhcpd.leases paths
Making dhcpd.conf and dhcpd.leases file references being dynamic causes
manual contents being replaced at compile time, so make some other data
items dynamic as well.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-25 18:03:13 +00:00
Sami Kerola
822ca33804 getdata & analyze: fix first_ip and last_ip arithmetics
There were too clever tricks done with first and last.  Earlier the aim
was to minimize '<=' and '>=' by fiddling with the numbers at the time
when they were saved.  While the program logic seemed to work there were
some off by one mistakes, resulting to a count error.  Even worse there
is not even that many of such comparisons, so that one cannot really even
justify added complexity.  I really hope this patch is last this kind fix
ever needed.

Reported-by: Cheer Xiao <xiaqqaix@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-21 21:50:09 +00:00
Sami Kerola
83e12457bc docs: fix spelling mistakes
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-20 21:09:53 +00:00
Cheer Xiao
88d989bbe2 Fix spelling mistakes. 2012-11-20 20:53:30 +00:00
Cheer Xiao
1b56bafaf5 Replace all htonl in getdata.c with ntohl.
They are always the same macro, but the semantics was wrong.
2012-11-20 20:53:30 +00:00
Cheer Xiao
dc83f1ffd4 ignore /gnulib/ 2012-11-20 20:53:29 +00:00
Sami Kerola
0a0fea05ad xstrstr: add function attributes
The pointers arguments are never null, and the function should be
optimized as much as possible.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-12 19:19:18 +00:00
Sami Kerola
34f99d2f08 header: let gnulib do what it is best of
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-12 19:19:17 +00:00
Sami Kerola
acba2e265e (un)likely: use __builtin_expect to inform expected path
Remove also unnecessary comparison in getdata nth_field().

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-12 19:19:01 +00:00
Sami Kerola
6f179db03d sort: fix get_order() if else return statement
Another instance of where returns happen in else clause removed.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-10 00:22:32 +00:00
Sami Kerola
6f4104acbc analyze: use gnulib
The gnulib is grippled without config.h in use.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-10 00:09:43 +00:00
Sami Kerola
4341d92d41 getdata: skip strings before nth_field analysis
This will allow nth_field function to begin from first field, and stop
immediately when it ends, which makes function much more simple and quite
a bit quicker.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-10 00:07:09 +00:00
Sami Kerola
b918e9157d getdata: stop looking after interesting field
The nth_field function continued looking for words after they where known
not to be interesting.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-09 22:52:30 +00:00
Sami Kerola
5f59daa692 analyze, getdata: write functions in frequency order
According to test data free is seen most often in leases file.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-09 22:20:04 +00:00
Sami Kerola
72a41d8086 getdata: fix if else return statements
If something is true, and it returns using else is pointless.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-09 21:39:43 +00:00
Sami Kerola
629796cce7 sort: fix if else return statements
If something is true, and it returns using else is pointless.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-09 07:55:48 +00:00
Sami Kerola
18f2835fd5 analyze: sort ranges before analysis
At the other day I where wondering why so much time was spent on analysis
function, when I realized regression.  At the time uthash was introduced
to the project range sorting got to be dropped, which caused same leases
to be walked in analysis time after time.

Now when the regression is removed, and the test cases run about 28% over
all quicker.  The rule of thumb is that the greater the data set the
bigger is the benefit having this fix.  My largest test data is now
roughly 35% faster.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-08 22:02:02 +00:00
Sami Kerola
7a86746710 analyze: use simpler comparison
In some cases the this can make run time to take 2.5% less time.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-07 21:42:18 +00:00
Sami Kerola
5714e95228 release: 2.19
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-06 20:15:59 +00:00
Sami Kerola
31c506ee73 build-sys: update gitignore
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-06 20:09:48 +00:00
Sami Kerola
22bf014ab5 docs: mention gnulib in README file
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-06 19:59:32 +00:00
Sami Kerola
c8a348e93b build-sys: remove files which where added by accident
Sometimes I do not seem to be careful enough when committing.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-06 19:50:54 +00:00
Sami Kerola
b61c93b7a1 performance: add few restict and const key words
This should make the run to be couple percentages quicker.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-05 21:05:42 +00:00
Sami Kerola
dbf3927c39 build-sys: clean gnulib & autotools checks
Add gnulib modules which make sense and remove few.  The stuff gnulib
takes care can be dropped from configure.am.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-05 20:30:53 +00:00
Sami Kerola
ab699e71ad build-sys: add gnulib
This will mean better portability, and a good reason to get rid of
various portability autotools directives which where part of this
project.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-11-05 00:03:03 +00:00
Sami Kerola
b5e518cd5e docs: clarify man page
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-10-09 22:01:49 +01:00
Sami Kerola
7eb2e42625 build-sys: be conservative about posix_fadvice
Check that function availability before use.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-10-09 21:52:19 +01:00
Sami Kerola
14d7183c3d build-sys: add what autoscan found bein missing
configure.ac: warning: missing AC_CHECK_FUNCS([atexit]) wanted by: src/dhcpd-pools.c:88
configure.ac: warning: missing AC_CHECK_HEADERS([limits.h]) wanted by: src/dhcpd-pools.c:55
configure.ac: warning: missing AC_FUNC_ERROR_AT_LINE wanted by: src/other.c:213
configure.ac: warning: missing AC_FUNC_STRTOD wanted by: src/other.c:148

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-10-09 21:31:43 +01:00
Sami Kerola
b15e63afd2 output: fix sign-compare warning [clang]
output.c:819:17: warning: comparison of integers of different signs:
'int' and ' unsigned int' [-Wsign-compare]
                for (i = 0; i < num_ranges; i++) {
                            ~ ^ ~~~~~~~~~~
output.c:832:17: warning: comparison of integers of different signs:
'int' and ' unsigned int' [-Wsign-compare]
                for (i = 0; i < num_shared_networks; i++) {
                            ~ ^ ~~~~~~~~~~~~~~~~~~~

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-10-08 19:39:26 +01:00
Sami Kerola
e8acaa42c8 build-sys: use AM_CPPFLAGS rather than INCLUDES
The INCLUDES is an older name for the same functionality as AM_CPPFLAGS.

References: http://www.gnu.org/software/automake/manual/html_node/Program-Variables.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-09-30 20:45:35 +01:00
Sami Kerola
6817d234ca style: fix few indentation issues
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-07-17 17:59:39 +02:00
Sami Kerola
b3e02ce0ba all: fix compiler warninings
Use compiler warnings from coreutils to check nothing complains, and
fix everything that did.

CFLAGS='-Wall -W -Wformat-y2k -Wformat-security -Winit-self
-Wmissing-include-dirs -Wunused -Wunknown-pragmas -Wstrict-aliasing
-Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align
-Wwrite-strings -Wmissing-declarations -Wmissing-noreturn -Wpacked
-Winvalid-pch -Wvolatile-register-var -Wdisabled-optimization
-Woverlength-strings -Wbuiltin-macro-redefined -Wmudflap
-Wpacked-bitfield-compat -Wsync-nand -Wattributes -Wcoverage-mismatch
-Wabi -Wcpp -Wdeprecated -Wdeprecated-declarations -Wdiv-by-zero
-Wendif-labels -Wextra -Wformat-contains-nul -Wformat-extra-args
-Wformat-zero-length -Wformat=2 -Wmultichar -Wnormalized=nfc -Woverflow
-Wpointer-to-int-cast -Wpragmas -Wsuggest-attribute=noreturn
-Wtrampolines -Wno-sign-compare -Wno-unused-parameter
-Wsuggest-attribute=noreturn -Wno-format-nonliteral -Wno-logical-op
-fdiagnostics-show-option -funit-at-a-time'

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-07-17 17:59:39 +02:00
Sami Kerola
37563d8d59 build-sys: create only xz compressed distribution package
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-06-26 10:10:40 +02:00
Sami Kerola
7600d32b89 contrib: add nagios.conf example
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-06-26 10:06:27 +02:00
Sami Kerola
a05d793378 docs: add note how to limit alarming scope
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-06-24 16:51:33 +02:00
Sami Kerola
dd5bc03f12 docs: add examples to manual page
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-06-24 16:41:22 +02:00
Sami Kerola
42dd80aeac alarming: make native nagios support to dhcpd-pools
This commit makes integrating the command with nagios much easier.

$ dhcpd-pools -c dhcpd.conf -l dhcpd.leases --critical 80 --warning 75
CRITICAL: dhcpd-pools: Ranges; crit: 14 warn: 22 ok: 220 Shared nets; crit: 1 warn: 0 ok: 4

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
2012-06-24 16:40:25 +02:00
185 changed files with 14005 additions and 2171 deletions

56
.gitignore vendored
View file

@ -1,27 +1,33 @@
aclocal.m4
autom4te.cache/
autoscan.log
config.guess
config.h
config.h.in
config.h.in~
config.log
config.status
config.sub
configure
configure.scan
contrib/Makefile
contrib/Makefile.in
depcomp
INSTALL
install-sh
libtool
ltmain.sh
m4/*.m4
# Wildcard + in any subdir.
*.o
*.gcno
*.gcda
*.[ch].gcov
# Exact filename in any subdir.
.deps
.dirstamp
Makefile
Makefile.in
man/Makefile
man/Makefile.in
missing
stamp-h1
tags
# Exact wildcard, e.g., not in subdirs.
/tests/*.log
/tests/*.trs
# Exact match, if a directory then everything in directory.
/.version
/aclocal.m4
/autom4te.cache/
/config.h
/config.h.in
/config.log
/config.status
/configure
/dhcpd-pools
/INSTALL
/libtool
/m4/
/man/dhcpd-pools.1
/stamp-h1
/test-suite.log
/tests/outputs/

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

@ -23,7 +23,7 @@ See "git log" for change information.
2009-05-14 Dan Thorson
* Memory boundary check. Lack of this caused illegal memory
refrences when there was plenty of backup leases.
references when there was plenty of backup leases.
2009-02-18 Sami Kerola <kerolasa@iki.fi> && Dan Thorson
* posix_fadvice to make read-ahead quicker. (SK)

View file

@ -1,6 +1,55 @@
## Makefile.am -- Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = gnu
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src man contrib
EXTRA_DIST = \
.version \
build-aux/git-version-gen \
m4/gnulib-cache.m4
SUBDIRS = lib
BUILT_SOURCES = $(top_srcdir)/.version
$(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
PATHFILES =
CLEANFILES = $(PATHFILES)
EXTRA_DIST += $(PATHFILES:=.in)
CLEAN_LOCALS =
edit_cmd = sed \
-e 's|@ALARM_CRIT[@]|$(ALARM_CRIT)|g' \
-e 's|@ALARM_WARN[@]|$(ALARM_WARN)|g' \
-e 's|@DHCPDCONF_FILE[@]|$(DHCPDCONF_FILE)|g' \
-e 's|@DHCPDLEASE_FILE[@]|$(DHCPDLEASE_FILE)|g' \
-e 's|@OUTPUT_FORMAT[@]|$(OUTPUT_FORMAT)|g' \
-e 's|@OUTPUT_LIMIT[@]|$(OUTPUT_LIMIT)|g' \
-e 's|@PACKAGE_BUGREPORT[@]|$(PACKAGE_BUGREPORT)|g' \
-e 's|@PACKAGE_MAINTAINER[@]|$(PACKAGE_MAINTAINER)|g' \
-e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \
-e 's|@PACKAGE_URL[@]|$(PACKAGE_URL)|g' \
-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) mkdir -p $$(dirname $@)
$(AM_V_GEN) srcdir=''; \
test -f ./$@.in || srcdir=$(srcdir)/; \
$(edit_cmd) $${srcdir}$@.in >$@.tmp
@ mv $@.tmp $@
include contrib/Makemodule.am
include doc/Makemodule.am
include man/Makemodule.am
include samples/Makemodule.am
include src/Makemodule.am
include tests/Makemodule.am
clean-local: $(CLEAN_LOCALS)

434
NEWS
View file

@ -5,6 +5,440 @@ See the end for copying conditions.
Please send dhcpd-pools bug reports to kerolasa@iki.fi.
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):
portability: Solaris 10 does not have err.h
fix couple compiler warnings
make binary exec path dynamic in scripts referring to it
update doxygen.conf file
add --snet-alarms option to suppress excess range alarms
add --warn-count and --crit-count options to suppress alarm noise
improve README file instructions
make html output to use Bootstrap and DataTables
fix typo in README
correct return value FIXME items
use more descriptive names in limit bits enum definition
remove upper limit of sort order definitions
fix protocol specifier in html output
use bitmap for booleans and other config that has known size
simplify output format selection, and passing
fix doxygen build
fix improve variable names
print include system error message when output fails
drop a core when bug condition happens
make usage() easier to read
unify quotation in error messages
add --warn-count and --crit-count test, and fix related bug
test all sorting options
change NAN markup to make tests work on mac
fix out of tree build tests
release: 2.28
Version 2.27
Sami Kerola (9):
docs: remove very basic git usage info
docs: remove todo items that will never happen
output: remove empty element from xml
add touched addresses counts to xml and json reports
add xml format check
improve html output
add hint about configure options to README
man: fix character class change
gitignore: update gnulib file list
release: 2.27
Version 2.26
$ git shortlog v2.25..v2.26
Sami Kerola (15):
news: add the note about .sig pgp key id
reindent all files
declare global variables only once
add appropriate sorting function for struct leases_t
update kernel.org url in README
getdata: fix buffer-overflows reported by address sanitizer
update bootstrap from gnulib
getdata: fix buffer overflow [AddressSanitizer]
other: reduce variable scope
output: prefer thread safe function localtime_r()
tests: add regression test to avoid shared-net off by one alarming
issue
output: avoid division by zero
other: disallow unsigned counter ever to have minus value
maint: remove unnecessary braces, spaces, update gnulib .gitignore
release: 2.26
Wolfgang Steudel (1):
alarming: include last shared network in alarming [off by one]
Version 2.25
$ git shortlog v2.24..v2.25
Sami Kerola (14):
build-sys: use more strict method to check __builtin_expect
getdata: add missing HAVE_POSIX_FADVISE protection
getdata: fix consecutive range definition regression
man: add tip analysis of include files can be useful
thanks: add Fredrik Lysén & Conor McCarthy
generic: use pure and const function attributes when possible
tests: fix testing error
output: make nagios output have performance data
build-sys: update gitinore file
output: use symbolic exit values for nagios commands
build-sys: update bootstrap script
build-sys: require automake 1.12 to get working test-driver
contrib: add release siging key to contrib/
release: 2.25
Version 2.24
$ git shortlog v2.23..v2.24
Sami Kerola (22):
build-sys: update configure.ac
output: make output limits to apply to alarm return values
tests: add alarming tests
output: allow alarming, in case of success, be silent
tests: fix tests to use the new OK printing limit
docs: inform how the limits affect to printing when alarming is in use
output: allow user to ignore small ranges and shared networks
tests: test small network alarm ignoring
docs: add an example how to use limits with alarming
thanks: Dan Pritts
xstrstr: speed up analysis by avoiding string comparisons
other: memcmp() is tiny bit quicker than strncmp()
build-sys: update gnulib modules
build-sys: AC_PROG_CC_C99 is obsolete; use AC_PROG_CC
getdata: use correct file caching advice
analyze: remove unnecessary function
getdata: memccpy() is better than own similar function
getdata: split busy function to segments used via function pointer
various: split functions to IPv4 and IPv6 versions
various: fix memory leaks
getdata: fix one ip ranges when they have trailing spaces in definition
release: 2.24
Version 2.23
$ git shortlog v2.22..v2.23
Sami Kerola (3):
gnulib: add gnulib modules
build-sys: update bootstrap from gnulib
release: 2.23
Version 2.22
$ git shortlog v2.21..v2.22
Cheer Xiao (1):
getdata: treat binding states abandoned, expired and release like free
Sami Kerola (19):
tests: add complete check including multiple ranges and shared networks
include: add missing declarations to dhcpd-pool.h
cppcheck: fix variable scoping
build-sys: update .gitignore
build-sys: add git-version-gen and test.sh to release package
docs: fix spelling mistakes in manual page
build-sys: ensure distribution has version file
build-sys: update git-version-gen from gnulib
tests: binding states commit needs to be reflected in expected results
build-sys: reorder gnulib macro in relation to C standard
getdata: posix_fadvise() error checking
getdata: certain input files caused SIGSEGV
tests: check how command works with invalid input
getdata: make a lease address detection more robust
getdata: make single address ranges work
tests: add a test for one ip range
build-sys: fix gnulib function order
build-sys: use non-recursive build
release: 2.22
Version 2.21
$ git shortlog v2.20..v2.21
Cheer Xiao (10):
IPv6: add DHCPv6 support
sort: Use a comparer instead of returner
sort: Get rid of global comparer
counting & output: Convert all counters to double
fix: Put prototype of field_selector back to dhcpd-pools.h
sort: let field_selector return NULL at the end
counting: Let get_range_size return double
sort: let comp_* functions compare double
tests: update expected/v6
output: fix doc of output_double
Gilles Bouthenot (5):
output: add json format support
json output: add newline at end
json output: remove useless, empty fields
json output: bugfix: correct range specify only first ip
contrib: add munin plugins
Sami Kerola (29):
build-sys: remove c++ compiler check
tools: add indent command configuration file
tests: add basic tests
build-sys: update .gitignore
tests: add v6 check
output: remove unnecessary new line printing
build-sys: more clean ups
json output: use defined output file for all printing
tests: add json tests, and make fail output loud
ouput format: fix active lease printing
output ethernet: do not crash if ethernet is missing
docs: add doxygen tags, configuration file, and autotooling
backup counting: fix output regression
clean up: remove unused functions
clean up: move code to more proper location
hash: make delete to use HASH_ITER if it is available
clean up: move global variables to config structure
clean up: use enum as symbolic bit masks
clean up: convert parsing magic numbers to symbolic values
clean up: rename get_order() to merge() and mark static
clean up: fix few indentation slips
getdata: be consistant with symbolic numbers
smatch scan: fix few warnings
build-sys: allow tests run parallel
build-sys: update .gitignore files
docs: thanks to Cheer Xiao this software has IPv6 support
tests: fix make distcheck
docs: fix doxygen make distcheck breakage
release: 2.21
Version 2.20
$ git shortlog v2.19..v2.20
Cheer Xiao (3):
ignore /gnulib/
Replace all htonl in getdata.c with ntohl.
Fix spelling mistakes.
Sami Kerola (20):
analyze: use simpler comparison
analyze: sort ranges before analysis
sort: fix if else return statements
getdata: fix if else return statements
analyze, getdata: write functions in frequency order
getdata: stop looking after interesting field
getdata: skip strings before nth_field analysis
analyze: use gnulib
sort: fix get_order() if else return statement
(un)likely: use __builtin_expect to inform expected path
header: let gnulib do what it is best of
xstrstr: add function attributes
docs: fix spelling mistakes
getdata & analyze: fix first_ip and last_ip arithmetics
man: use configured dhcpd.conf and dhcpd.leases paths
build-sys: update gitignore
build-sys: clean up configure.ac
build-sys: make alarm warning & critical default configurable
man: fix errors in alarm warning and critical options text
release: 2.20
Version 2.19
$ git shortlog v2.18..v2.19
Sami Kerola (19):
alarming: make native nagios support to dhcpd-pools
docs: add examples to manual page
docs: add note how to limit alarming scope
contrib: add nagios.conf example
build-sys: create only xz compressed distribution package
all: fix compiler warninings
style: fix few indentation issues
build-sys: use AM_CPPFLAGS rather than INCLUDES
output: fix sign-compare warning [clang]
build-sys: add what autoscan found bein missing
build-sys: be conservative about posix_fadvice
docs: clarify man page
build-sys: add gnulib
build-sys: clean gnulib & autotools checks
performance: add few restict and const key words
build-sys: remove files which where added by accident
docs: mention gnulib in README file
build-sys: update gitignore
release: 2.19
Version 2.18
$ git shortlog v2.17..v2.18

218
README
View file

@ -1,190 +1,62 @@
This is dhcpd-pools which is made for ISC dhcpd pool range analysis.
This is dhcpd-pools - ISC dhcpd lease status utility.
== Quick start
Quick start.
./autogen.sh
./configure --prefix=/usr/local
Get the uthash, assuming you do not have it already.
cd /tmp
wget https://github.com/troydhanson/uthash/archive/master.zip
unzip master.zip
Build the dhcpd-pools project.
cd /tmp/dhcpd-pools
./bootstrap # only when building git clone
./configure --with-uthash=/tmp/uthash-master/include
make
make check
make install
Notice that there are configuration options for default dhcpd.conf,
dhcpd.leases paths, among other things.
== General information
./configure --help
With this command you can check usage of pool addresses
when address space is great. Command is designed so that
it will not get slow even there is thousands of IPs in
lease file. This kind of huge dhcpd installation can be
near by DSL DSLAMs or some other public access connection
points.
Remember to read the friendly manual page.
This command will not print nice to know information like
DHCPStatus does. Output is limited only to list only
usage for ranges, shared network and total address space.
Limiting what is printed is the right thing to do when
there is thousands of addresses. If your address space is
small some other dhcp analyzer might be more suitable for
you.
man ./man/dhcpd-pools.1
== Dependencies to other projects
Dependencies to other projects.
http://uthash.sourceforge.net/
https://www.gnu.org/software/gnulib/
== Test data wanted
You can avoid repeated gnulib downloads by setting
GNULIB_SRCDIR environment variable. For example:
git clone git://git.savannah.gnu.org/gnulib.git ~/src/gnulib
export GNULIB_SRCDIR="$HOME/src/gnulib"
Assumign detached gnulib please remember to git pull the
latest updates before building dhcpd-pools.
https://troydhanson.github.io/uthash/
See quick start.
https://getbootstrap.com/
https://datatables.net/
Bootstrap and DataTables java scripts are used in html
output.
Test data wanted.
Maintainer is interested to get copy of your dhcpd.conf
and dhcpd.leases file, with includes if you use them.
and dhcpd.leases files, and include files if you use them.
Intention is to collect large set of data to build
realistic regression test environment. By giving your
data to maintainer you can be sure that updates will work
for you.
realistic regression test environment.
If you are interested to help this way put all files into
tar.gz, and send them to kerolasa@iki.fi. It would be nice
that email subject line would have 'dhcpd-pools test data'.
tar.gz, and send them to:
== Instructions for developers
AUTOTOOLS:
* "./autogen.sh" generates all files needed to compile
and install the code (run it after checkout from git)
* "make distclean" removes all unnecessary files, but the
code can still be recompiled with "./configure; make"
PATCHES:
* First get familiar with git. In case you are completely
lost watch Greg Kroah-Hartman explaining the very
basics.
http://archive.fosdem.org/2010/schedule/events/linuxkernelpatch
* Get up to date version of the code base.
$ git clone git://dhcpd-pools.git.sourceforge.net/gitroot/dhcpd-pools/dhcpd-pools
* Don't include generated (autotools) stuff to your
patches (hint: use git-clean [-X])
* Add a Signed-off-by line, use "git commit -s"
* Patches are delivered via email only. The following
commands will do the correct thing.
$ git format-patch -C origin/master..yourbranch -o ~/patches
When you send only one patch use the following.
$ git send-email --to kerolasa@iki.fi 0001*
The command above expects you have configured email
sending properly. See git.wiki for help.
https://git.wiki.kernel.org/index.php/GitTips#Mail
* One patch per email, with the changelog in the body of
the email.
* When you send series of pathes include introductory
message.
$ git send-email --compose --to kerolasa@iki.fi ~/00*
Good introductory message will have at least
-- snip
Your Name (3):
firstfile.c: short description
secondfile.c: another description
firstfile.c | 2 +-
secondfile.c | 2 +-
secondfile.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
-- snip
Above introductory can be generated with git.
$ git shortlog master..yourbranch
$ git diff --stat master..yourbranch
* Subject: [PATCH] subsystem: description. Following
~/.gitconfig will help you a little.
-- snip
[user]
name = Your Name
email = your.name@example.com
[format]
subjectprefix = PATCH
numbered = auto
signoff = yes
[sendemail]
chainreplyto = false
cc = your.name@example.com
-- snip
* If someone else wrote the patch, they should be
credited (and blamed) for it. To communicate this, add
a line:
From: John Doe <jdoe@wherever.com>
The sign-off is a simple line at the end of the
explanation for the patch, which certifies that you
wrote it or otherwise have the right to pass it on as a
open-source patch. The rules are pretty simple: if you
can certify the below:
By making a contribution to this project, I certify
that:
(a) The contribution was created in whole or in
part by me and I have the right to submit it
under the open source license indicated in the
file; or
(b) The contribution is based upon previous work
that, to the best of my knowledge, is covered
under an appropriate open source license and I
have the right under that license to submit
that work with modifications, whether created
in whole or in part by me, under the same open
source license (unless I am permitted to submit
under a different license), as indicated in the
file; or
(c) The contribution was provided directly to me by
some other person who certified (a), (b) or (c)
and I have not modified it.
(d) I understand and agree that this project and
the contribution are public and that a record
of the contribution (including all personal
information I submit with it, including my
sign-off) is maintained indefinitely and may be
redistributed consistent with this project or
the open source license(s) involved.
then you just add a line saying
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name (sorry, no pseudonyms or anonymous
contributions.)
* If the the business with git is too difficult just send
source code files as is as email attachment to
maintainer.
CODING STYLE:
* The preferred coding style is based on the linux kernel
Documentation/CodingStyle. For more details see:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/CodingStyle
* Source code is pretty printed by using two, and only
the two, indent command switches -kr -i8
Sami Kerola <kerolasa@iki.fi>

41
THANKS
View file

@ -5,21 +5,50 @@ 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
Helmut Grohne
Joey D.
Ryan Steinmetz
Dan Pritts
Fredrik Lysén
Conor McCarthy
Wolfgang Steudel
Aaron Paetznick
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δμ

38
TODO
View file

@ -8,7 +8,6 @@ Reported-by: Huangyu: I found dhcpd-pools didn't consider if the
### Feature requests
o IPv6 support (Frank)
o Assigned IPs count (Nelson)
o Subnet counting class (Henryk)
o When time stamps are part of lease situation evaluation (see
@ -16,26 +15,19 @@ o When time stamps are part of lease situation evaluation (see
expiry happens.
o Add lease time histogram support.
### Next major version
### When releasing
1 Well structured code, with extendible sane architecture.
2 Server, which has analysis in cache for N seconds and will
answer via socket.
3 Configuration file for server.
4 State file, where different ranges, shared networks etc have
unique identifiers (needed for graphs).
5 Support for snmp and munin protocols.
6 SNMP traps when limits get exceeded.
7 Some clever check_dhcpd_pools binary for Nagios & other
monitoring software.
8 Super server support, which will collect analysis from other
dhcpd-pool servers.
9 Nice http view interface on super server, much can be copied
from http://piwik.org/
10 IPv6 support.
11 And some other things perhaps...
When items 1-7 are done v3 can be released. To support rewrite
there should be a design document with nice blue print, which is
a web page.
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

View file

@ -1,79 +0,0 @@
#!/bin/sh
#
# Helps generate autoconf/automake stuff, when code is checked
# out from SCM.
#
# The script is copied from util-linux package.
#
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
THEDIR=`pwd`
cd $srcdir
DIE=0
test -f src/dhcpd-pools.c || {
echo
echo "You must run this script in the top-level dhcpd-pools directory"
echo
DIE=1
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to generate dhcpd-pools build system."
echo
DIE=1
}
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoheader installed to generate dhcpd-pools build system."
echo "The autoheader command is part of the GNU autoconf package."
echo
DIE=1
}
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have libtool-2 installed to generate dhcpd-pools build system."
echo
DIE=1
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to generate dhcpd-pools build system."
echo
DIE=1
}
ltver=$(libtoolize --version | awk '/^libtoolize/ { print $4 }')
test ${ltver##2.} = "$ltver" && {
echo "You must have libtool version >= 2.x.x, but you have $ltver."
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
echo
echo "Generate build-system by:"
echo " aclocal: $(aclocal --version | head -1)"
echo " autoconf: $(autoconf --version | head -1)"
echo " autoheader: $(autoheader --version | head -1)"
echo " automake: $(automake --version | head -1)"
echo " libtoolize: $(libtoolize --version | head -1)"
set -e
libtoolize --force $LT_OPTS
aclocal $AL_OPTS
autoconf $AC_OPTS
autoheader $AH_OPTS
automake --add-missing $AM_OPTS
cd $THEDIR
echo
echo "Now type '$srcdir/configure' and 'make' to compile."
echo

1631
bootstrap Executable file

File diff suppressed because it is too large Load diff

93
bootstrap.conf Normal file
View file

@ -0,0 +1,93 @@
# Bootstrap configuration. -*- sh -*-
# 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
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 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 <https://www.gnu.org/licenses/>.
# gnulib modules used by this package.
gnulib_modules="
close-stream
closeout
error
fclose
fcntl-h
fdopen
fflush
fopen
getopt-gnu
inet_pton
isnan
netinet_in
nstrftime
progname
quote
realloc-gnu
stat
stddef
stdio
stdlib
stpncpy
strdup-posix
strstr
strtod
time_r
xalloc
"
# Additional xgettext options to use. Use "\\\newline" to break lines.
XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
--from-code=UTF-8\\\
--flag=asprintf:2:c-format --flag=vasprintf:2:c-format\\\
--flag=asnprintf:3:c-format --flag=vasnprintf:3:c-format\\\
--flag=wrapf:1:c-format\\\
'
# If "AM_GNU_GETTEXT(external" or "AM_GNU_GETTEXT([external]"
# appears in configure.ac, exclude some unnecessary files.
# Without grep's -E option (not portable enough, pre-configure),
# the following test is ugly. Also, this depends on the existence
# of configure.ac, not the obsolescent-named configure.in. But if
# you're using this infrastructure, you should care about such things.
gettext_external=0
grep '^[ ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null &&
gettext_external=1
grep '^[ ]*AM_GNU_GETTEXT(\[external]' configure.ac > /dev/null &&
gettext_external=1
if test $gettext_external = 1; then
# Gettext supplies these files, but we don't need them since
# we don't have an intl subdirectory.
excluded_files='
m4/glibc2.m4
m4/intdiv0.m4
m4/lcmessage.m4
m4/lock.m4
m4/printf-posix.m4
m4/size_max.m4
m4/uintmax_t.m4
m4/ulonglong.m4
m4/visibility.m4
m4/xsize.m4
'
fi
# Build prerequisites
buildreq="\
autoconf 2.59
automake 1.9.6
git 1.5.5
tar -
"

12
build-aux/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
/ar-lib
/compile
/config.guess
/config.rpath
/config.sub
/depcomp
/install-sh
/ltmain.sh
/mdate-sh
/missing
/test-driver
/texinfo.tex

View file

@ -1,12 +1,12 @@
#!/bin/sh
# Print a version string.
scriptversion=2011-02-19.19; # UTC
scriptversion=2022-01-27.18; # UTC
# Copyright (C) 2007-2011 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=2011-02-19.19; # 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)
@ -44,8 +44,10 @@ scriptversion=2011-02-19.19; # UTC
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# It is probably wise to add these two files to .gitignore, so that you
# don't accidentally commit either generated file.
# As with any generated file in a VC'd directory, you should add
# /.version to .gitignore, so that you don't accidentally commit it.
# .tarball-version is never generated in a VC'd directory, so needn't
# be listed there.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
@ -57,24 +59,76 @@ scriptversion=2011-02-19.19; # UTC
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .tarball-version will
# exist in distribution tarballs.
# will be present for dependencies, and so that .version and
# .tarball-version will exist in distribution tarballs.
#
# 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
case $# in
1|2) ;;
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version" \
'[TAG-NORMALIZATION-SED-SCRIPT]'
exit 1;;
esac
tarball_version_file=$1
tag_sed_script="${2:-s/x/x/}"
me=$0
year=`expr "$scriptversion" : '\([^-]*\)'`
version="git-version-gen $scriptversion
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]
Print a version string.
Options:
--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
Running without arguments will suffice in most cases."
prefix=v
fallback=
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?};;
-*)
echo "$0: Unknown option '$1'." >&2
echo "$0: Try '--help' for more information." >&2
exit 1;;
*)
if test "x$tarball_version_file" = x; then
tarball_version_file="$1"
elif test "x$tag_sed_script" = x; then
tag_sed_script="$1"
else
echo "$0: extra non-option argument '$1'." >&2
exit 1
fi;;
esac
shift
done
if test "x$tarball_version_file" = x; then
echo "$usage"
exit 1
fi
tag_sed_script="${tag_sed_script:-s/x/x/}"
nl='
'
@ -89,25 +143,23 @@ then
v=`cat $tarball_version_file` || v=
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test -z "$v" \
&& echo "$0: WARNING: $tarball_version_file is missing or damaged" 1>&2
test "x$v" = x \
&& echo "$0: WARNING: $tarball_version_file is damaged" 1>&2
fi
if test -n "$v"
if test "x$v" != x
then
: # use $v
# Otherwise, if there is at least one git commit involving the working
# directory, and "git describe" output looks sensible, use that to
# derive a version string.
elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
&& v=`git describe --tags --abbrev=4 --match='v*' HEAD 2>/dev/null \
|| git describe --tags --abbrev=4 HEAD 2>/dev/null` \
&& v=`git describe --abbrev=4 --match="$prefix*" HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
&& case $v in
v[0-9]*) ;;
$prefix[0-9]*) ;;
*) (exit 1) ;;
esac
then
@ -115,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
@ -132,21 +185,23 @@ 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
else
elif test "x$fallback" = x || git --version >/dev/null 2>&1; then
v=UNKNOWN
else
v=$fallback
fi
v=`echo "$v" |sed 's/^v//'`
v=`echo "$v" |sed "s/^$prefix//"`
# Test whether to append the "-dirty" suffix only if the version
# 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 -n "$v_from_git"; then
# Don't declare a version "dirty" merely because a time stamp has changed.
if test "x$v_from_git" != x; then
# 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=
@ -161,12 +216,12 @@ if test -n "$v_from_git"; 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:

5
build-aux/snippet/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/_Noreturn.h
/arg-nonnull.h
/c++defs.h
/unused-parameter.h
/warn-on-use.h

View file

@ -1,24 +1,40 @@
# -*- Autoconf -*-
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.64)
AC_CONFIG_MACRO_DIR([m4])
AC_PREREQ([2.69])
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/])
AM_INIT_AUTOMAKE
[m4_esyscmd([build-aux/git-version-gen .tarball-version])],
[kerolasa@iki.fi],[],
[https://dhcpd-pools.sourceforge.net/])
PACKAGE_MAINTAINER="Sami Kerola"
AC_SUBST([PACKAGE_MAINTAINER])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([
-Wall
-Wextra-portability
1.12
foreign
dist-xz
no-dist-gzip
parallel-tests
subdir-objects
tar-pax
])
AC_CONFIG_SRCDIR([src/dhcpd-pools.h])
AC_CONFIG_HEADERS([config.h])
AC_GNU_SOURCE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
# Checks for programs
AC_PROG_AWK
AC_PROG_CC_C99
AC_USE_SYSTEM_EXTENSIONS
AC_C_RESTRICT
AC_PROG_CXX
AC_PROG_CC
gl_EARLY
gl_INIT
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
LT_INIT
# Checks for libraries.
LT_INIT
@ -26,34 +42,22 @@ LT_INIT
# Checks for header files.
AC_CHECK_HEADERS([\
arpa/inet.h \
error.h \
fcntl.h \
langinfo.h \
libintl.h \
netinet/in.h \
stddef.h \
stdio_ext.h \
stdlib.h \
string.h \
strings.h \
limits.h \
sys/socket.h \
unistd.h \
])
AC_ARG_WITH(uthash,
AC_HELP_STRING([--with-uthash=DIR], [Use uthash from [DIR]/uthash.h)]),
[ case "$with_uthash" in
yes)
;;
no)
AC_MSG_ERROR([the uthash.h is required])
;;
*)
CPPFLAGS="$CPPFLAGS -I$with_uthash"
;;
esac]
AC_ARG_WITH(
[uthash],
[AS_HELP_STRING([--with-uthash=DIR], [Use uthash from [DIR]/uthash.h)])],
[AS_CASE([$with_uthash],
[yes], [],
[no], [AC_MSG_ERROR([the uthash is required])],
[CPPFLAGS="$CPPFLAGS -I$with_uthash"]
)]
)
AC_CHECK_HEADER(uthash.h, [], [AC_MSG_ERROR([Unable to find uthash.h])])
AC_CHECK_HEADER([uthash.h], [], [AC_MSG_ERROR([Unable to find uthash.h])])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
@ -62,55 +66,107 @@ AC_TYPE_SIZE_T
AC_TYPE_UINT32_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_FUNC_ERROR_AT_LINE
AC_CHECK_FUNCS([\
__fpending \
error \
inet_ntoa \
memset \
nl_langinfo \
strdup \
strerror \
strrchr \
strstr \
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([[]], [[
return __builtin_expect(1, 1) ? 1 : 0
]])],[
have_builtin_expect=yes
AC_MSG_RESULT([yes])
],[
have_builtin_expect=no
AC_MSG_RESULT([no])
])
AS_IF([test x$have_builtin_expect = xyes], [
AC_DEFINE([HAVE_BUILTIN_EXPECT], [1],
[The compiler supports __builtin_expect])
])
AC_CONFIG_FILES([Makefile
man/Makefile
src/Makefile
contrib/Makefile])
AC_ARG_WITH([dhcpd-conf],
[AS_HELP_STRING([--with-dhcpd-conf=FILE],[default path of dhcpd.conf])],
[dhcpd_conf_path="$withval"],
[dhcpd_conf_path="/etc/dhcpd.conf"])
AC_DEFINE_UNQUOTED([DHCPDCONF_FILE], ["$dhcpd_conf_path"], [default path of dhcpd.conf])
AC_SUBST([DHCPDCONF_FILE], [$dhcpd_conf_path])
AC_MSG_CHECKING(whether program_invocation_short_name is defined)
AC_TRY_COMPILE([#include <argp.h>],
[program_invocation_short_name = "test";],
AC_DEFINE(HAVE_PROGRAM_INVOCATION_SHORT_NAME, 1,
[Define if program_invocation_short_name is defined])
AC_MSG_RESULT(yes),
AC_MSG_RESULT(no))
AC_ARG_WITH([dhcpd-leases],
[AS_HELP_STRING([--with-dhcpd-leases=FILE],[default path of dhcpd.leases])],
[dhcpd_leases_path="$withval"],
[dhcpd_leases_path="/var/lib/dhcp/dhcpd.leases"])
AC_DEFINE_UNQUOTED([DHCPDLEASE_FILE], ["$dhcpd_leases_path"], [default path of dhcpd.leases])
AC_SUBST([DHCPDLEASE_FILE], [$dhcpd_leases_path])
AC_MSG_CHECKING([whether __progname is defined])
AC_LINK_IFELSE([AC_LANG_PROGRAM([extern char *__progname;],
[if (*__progname == 0) return;])],
AC_DEFINE(HAVE___PROGNAME, 1, [Define if __progname is defined])
AC_MSG_RESULT(yes),
AC_MSG_RESULT(no))
AC_ARG_WITH([output-format],
[AS_HELP_STRING([--with-output-format=FORMAT],[default output format])],
[output_format="$withval"],
[output_format="text"])
AC_DEFINE_UNQUOTED([OUTPUT_FORMAT], ["$output_format"], [default output format])
AC_SUBST([OUTPUT_FORMAT], [$output_format])
AC_ARG_WITH(dhcpd-conf,
[AC_HELP_STRING([--with-dhcpd-conf], [default path of dhcpd.conf])],
AC_DEFINE_UNQUOTED(DHCPDCONF_FILE,"$withval"),
AC_DEFINE(DHCPDCONF_FILE,["/etc/dhcpd.conf"],[default path of dhcpd.conf]))
AC_ARG_WITH(dhcpd-leases,
[AC_HELP_STRING([--with-dhcpd-leases], [default path of dhcpd.leases])],
AC_DEFINE_UNQUOTED(DHCPDLEASE_FILE,"$withval"),
AC_DEFINE(DHCPDLEASE_FILE,["/var/lib/dhcp/dhcpd.leases"],[default path of dhcpd.leases]))
AC_ARG_WITH(output-format,
[AC_HELP_STRING([--with-output-format], [default output format])],
AC_DEFINE_UNQUOTED(OUTPUT_FORMAT,"$withval"),
AC_DEFINE(OUTPUT_FORMAT,["text"],[default output format]))
AC_ARG_WITH(output-limit,
[AC_HELP_STRING([--with-output-limit], [default output limitations])],
AC_DEFINE_UNQUOTED(OUTPUT_LIMIT,"$withval"),
AC_DEFINE(OUTPUT_LIMIT,["77"],[default output limitations]))
AC_ARG_WITH([output-limit],
[AS_HELP_STRING([--with-output-limit=MASK],[default output limit])],
[output_limit="$withval"],
[output_limit="77"])
AC_DEFINE_UNQUOTED([OUTPUT_LIMIT], ["$output_limit"], [default output limit])
AC_SUBST([OUTPUT_LIMIT], [$output_limit])
AC_ARG_WITH([warning],
[AS_HELP_STRING([--with-warning=NUM],[monitoring warning default])],
[warning_percent="$withval"],
[warning_percent="80"])
AC_DEFINE_UNQUOTED([ALARM_WARN], [$warning_percent], [monitoring warning default])
AC_SUBST([ALARM_WARN], [$warning_percent])
AC_ARG_WITH([critical],
[AS_HELP_STRING([--with-critical=NUM],[monitoring critical default])],
[critical_percent="$withval"],
[critical_percent="90"])
AC_DEFINE_UNQUOTED([ALARM_CRIT], [$critical_percent], [monitoring critical default])
AC_SUBST([ALARM_CRIT], [$critical_percent])
AC_ARG_ENABLE([doxygen],
AS_HELP_STRING([--enable-doxygen],[build internal api documentation @<:@default=disabled@:>@]),
[], [enable_doxygen=no])
AM_CONDITIONAL([ENABLE_DOXYGEN], [test "x$enable_doxygen" = "xyes"])
AS_IF([test x$enable_doxygen = xyes], [
AC_CHECK_PROGS([DOXYGEN], [doxygen])
AS_IF([test "x$DOXYGEN" = "x"],
AC_MSG_ERROR([doxygen not in path])
)
AC_CHECK_PROGS([DOXYGEN_DOT], [dot])
AS_IF([test "x$DOXYGEN" = "x"],
AC_MSG_WARN([dot not in path, internal documentation graphs are not generated])
)
])
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x"])
AM_CONDITIONAL([HAVE_DOXYGEN_DOT], [test "x$DOXYGEN_DOT" != "x"])
AC_CONFIG_FILES([
Makefile
lib/Makefile
])
AC_OUTPUT

1
contrib/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/nagios.conf

View file

@ -1,2 +0,0 @@
contribdir = $(datadir)/dhcpd-pools/
dist_contrib_SCRIPTS = dhcpd-pools.cgi snmptest.pl

5
contrib/Makemodule.am Normal file
View file

@ -0,0 +1,5 @@
contribdir = $(datadir)/dhcpd-pools/
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 @@
#!/bin/sh
#
# 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>"
/usr/local/bin/dhcpd-pools --format html
echo "</body>"
echo "</html>"
# EOF

111
contrib/kerolasa.gpg Normal file
View file

@ -0,0 +1,111 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFLH/jcBEADNgkgZAr7b/qvHzNkme8eSplDA8UHhcCFQmBnQ8HYFEYBi1Y5a
GhICcuisRSuZIPLtqRF8ntoOXsOHOUxnn5hVR62HxMLgOC1PQMw8TzREobbkAxMp
Vg66c6JXD2+jEGuAbhRk1XyWJHaCN2ewT06ToqGi7jhlw6nz1AHyohhyxeRlyMff
a4daTIRREnh2qouImSOE0E8ETAb0eOnFOsweHhmbpC/RDzuY7Ns8YcNH3FbWT1Kl
4W9vOstB1JcgSz38/tnzoMG2Mf2jI8LgR+6xiHTb7i6bgyWiBOxcJWouTVam6SC0
Bc5cAe8EqHT6NMEjtNjDEzmb3ZFpFUnNKgKK5Wzghf17HAvYwpjYxNNoQl9jNIkf
XroquAyDDXW0IkNdGDARjJGW17r38oRH/R3q79DZNlqV/DPk4YLb0EAKzRAdBYGm
v8Bj+uLXc4JT9kTB5E8DT2ZR+61E4eT/zk4rpZ5j6tTktLNaSG58VYc+oQlPkPsB
ntraDsORpa5cK9uPUbHIHN1qd4gi35O4UDSqS023XnStQqsUD4vlzICedPDypn28
h9q2nlNQHSDjIRnZFD+z9IHfVoBNTfm5/UH7NKBAvSS6rP5zsgi2fittt5AFdbmQ
VBOtpYp5vbcdSt8gNdJRy8FRaiQ/2n74xF1Zso/PGni1xRmseS+qBGI95QARAQAB
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-----

View file

@ -0,0 +1,44 @@
#!/usr/bin/env node
var command = "dhcpd-pools"
var timeout = 5000; // (ms) if the command take longer, then kill it
var execFile = require('child_process').execFile;
var echo = require('util').print;
var arg = process.argv[2];
if ("autoconf" === arg) {
echo("yes\n");
return 0;
}
execFile(command, [ "--format=j", "--sort=n" ], { timeout: timeout }, function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
return 1;
}
stdout = JSON.parse(stdout);
if ("config" === arg) {
echo("graph_title dhcp usage (number of machines)\n");
echo("graph_vlabel nb of machines\n");
echo("graph_scale no\n");
echo("graph_category network\n");
stdout["subnets"].forEach(function(subnet) {
var location = subnet["location"];
var range = subnet["range"];
echo(location + '.label ' + location + ' (' + range + ')\n');
});
} else {
stdout["shared-networks"].forEach(function(network) {
var location = network["location"];
var used = network["used"];
var defined = network["defined"];
echo(location + '.value ' + used + '\n');
});
}
});

View file

@ -0,0 +1,37 @@
#!/usr/bin/env php
<?php
error_reporting(E_ALL);
ini_set("display_errors", true);
$ret="";
$xml = exec("dhcpd-pools --format x --sort n", $ret);
$xml = join($ret);
$xml = new SimpleXMLElement($xml);
if ($argc>1 && $argv[1]=="autoconf") {
echo "yes\n";
return;
} elseif ($argc>1 && $argv[1]=="config") {
$xml2 = $xml->xpath("subnet");
echo "graph_title dhcp usage (number of machines)\n";
echo "graph_vlabel nb of machines\n";
echo "graph_scale no\n";
echo "graph_category network\n";
foreach ($xml2 as $xml3) {
$location = (string) $xml3->location;
$range = (string) $xml3->range;
echo "$location.label $location ($range)\n";
}
} else {
$xml2 = $xml->xpath("shared-network");
foreach ($xml2 as $xml3) {
$location = (string) $xml3->location;
$used = (int) $xml3->used;
$defined = (int) $xml3->defined;
$pourcent = ceil($used*10000/$defined)/100;
echo "$location.value $used\n";
}
}

View file

@ -0,0 +1,49 @@
#!/usr/bin/env node
var command = "dhcpd-pools"
var timeout = 5000; // (ms) if the command take longer, then kill it
var execFile = require('child_process').execFile;
var echo = require('util').print;
var arg = process.argv[2];
if ("autoconf" === arg) {
echo("yes\n");
return 0;
}
execFile(command, [ "--format=j", "--sort=n" ], { timeout: timeout }, function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
return 1;
}
stdout = JSON.parse(stdout);
if ("config" === arg) {
echo("graph_title dhcp usage (in percent)\n");
echo("graph_args --upper-limit 100 -l 0 --rigid\n");
echo("graph_vlabel %\n");
echo("graph_scale no\n");
echo("graph_category network\n");
stdout["subnets"].forEach(function(subnet) {
var location = subnet["location"];
var range = subnet["range"];
echo(location + '.label ' + location + ' (' + range + ')\n');
echo(location + '.warning 75\n');
echo(location + '.critical 90\n');
});
} else {
stdout["shared-networks"].forEach(function(network) {
var location = network["location"];
var used = network["used"];
var defined = network["defined"];
// keep 1 digit after decimal point
var percent = Math.ceil(used * 100 / defined) / 10;
echo(location + '.value ' + percent + '\n');
});
}
});

View file

@ -0,0 +1,42 @@
#!/usr/bin/env php
<?php
error_reporting(E_ALL);
ini_set("display_errors", true);
//$xml = file_get_contents("test.xml");
$ret="";
$xml = exec("dhcpd-pools --format x --sort n", $ret);
$xml = join($ret);
$xml = new SimpleXMLElement($xml);
if ($argc>1 && $argv[1]=="autoconf") {
echo "yes\n";
return;
} elseif ($argc>1 && $argv[1]=="config") {
$xml2 = $xml->xpath("subnet");
echo "graph_title dhcp usage (in percent)\n";
echo "graph_args --upper-limit 100 -l 0 --rigid\n";
echo "graph_vlabel %\n";
echo "graph_scale no\n";
echo "graph_category network\n";
foreach ($xml2 as $xml3) {
$location = (string) $xml3->location;
$range = (string) $xml3->range;
echo "$location.label $location ($range)\n";
echo "$location.warning 75\n";
echo "$location.critical 90\n";
}
} else {
$xml2 = $xml->xpath("shared-network");
foreach ($xml2 as $xml3) {
$location = (string) $xml3->location;
$used = (int) $xml3->used;
$defined = (int) $xml3->defined;
// keep 1 digit after decimal point
$pourcent = ceil($used*1000/$defined)/10;
echo "$location.value $pourcent\n";
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

1
contrib/nagios.conf.in Normal file
View file

@ -0,0 +1 @@
command[check_dhcpd_pools]=@bindir@/dhcpd-pools --warning $ARG1$ --critical $ARG2$

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

3
doc/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/doxy.conf
/doxyfile.stamp
/html

24
doc/Makemodule.am Normal file
View file

@ -0,0 +1,24 @@
PATHFILES += \
doc/doxy.conf
nodist_noinst_DATA = \
doc/doxy.conf
EXTRA_DIST += \
doc/introduction.dox
if ENABLE_DOXYGEN
doc/doxyfile.stamp:
$(DOXYGEN) doc/doxy.conf
date > doc/doxyfile.stamp
CLEANFILES += doc/doxyfile.stamp
all-local: doc/doxyfile.stamp
clean-local-doc:
-rm -rf doc/*html
CLEAN_LOCALS += clean-local-doc
endif

2424
doc/doxy.conf.in Normal file

File diff suppressed because it is too large Load diff

49
doc/introduction.dox Normal file
View file

@ -0,0 +1,49 @@
/*!
@mainpage
@section introduction Introduction
This is dhcpd-pools ISC dhcp shared network and pool range usage
analysis. Purpose of command is to count usage ratio of each IP range
and shared network pool which ISC dhcpd is in control of. Users of the
command are most likely ISPs and other organizations that have large IP
space.
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 roughly
100k leases per second. Number of ranges, or shared networks, does not
make any significant difference in getting analysis done.
@section main-copyright Copyright Policy
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.
*/

262
lib/.gitignore vendored Normal file
View file

@ -0,0 +1,262 @@
/alloca.h
/alloca.in.h
/arg-nonnull.h
/arpa/
/arpa_inet.c
/arpa_inet.in.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++defs.h
/cdefs.h
/cloexec.c
/cloexec.h
/close.c
/closeout.c
/closeout.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
/filename.h
/flexmember.h
/float.c
/float+.h
/float.h
/float.in.h
/fopen.c
/fpending.c
/fpending.h
/fpurge.c
/freading.c
/freading.h
/free.c
/fseek.c
/fseeko.c
/fstat.c
/ftell.c
/ftello.c
/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
/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
/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
/Makefile.am
/malloca.c
/malloca.h
/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
/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
/quotearg.c
/quotearg.h
/quote.h
/reallocarray.c
/realloc.c
/setenv.c
/setlocale-lock.c
/setlocale_null.c
/setlocale_null.h
/setlocale_null-unlocked.c
/stat.c
/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.h
/stdio-impl.h
/stdio.in.h
/stdio-read.c
/stdio-write.c
/stdlib.c
/stdlib.h
/stdlib.in.h
/stpncpy.c
/strdup.c
/streq.h
/strerror.c
/strerror-override.c
/strerror-override.h
/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_types.in.h
/sys_uio.in.h
/timegm.c
/time.h
/time.in.h
/time-internal.h
/time_r.c
/time_rz.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
/verify.h
/warn-on-use.h
/wchar.h
/wchar.in.h
/wctype.h
/wctype-h.c
/wctype.in.h
/windows-initguard.h
/xalloc-die.c
/xalloc.h
/xalloc-oversized.h
/xmalloc.c

View file

@ -1,5 +0,0 @@
## Process this file with automake to produce Makefile.in
man_MANS = dhcpd-pools.1
EXTRA_DIST = $(man_MANS)
MAINTAINERCLEANFILES = $(man_MANS)

2
man/Makemodule.am Normal file
View file

@ -0,0 +1,2 @@
man_MANS = man/dhcpd-pools.1
PATHFILES += man/dhcpd-pools.1

View file

@ -1,162 +0,0 @@
.\" Sami Kerola
.\" http://www.iki.fi/kerolasa/
.\" kerolasa@iki.fi
.\"
.\" Add'l ontributions by:
.\" Dan Thorson
.\"
.TH DHCPD-POOLS "1" "September 2011" "dhcpd-pools" "User Commands"
.SH NAME
dhcpd-pools \- ISC dhcpd pools usage analysis
.SH SYNOPSIS
.B dhcpd-pools
[options]
[\fIOPTIONS\fR]
.SH DESCRIPTION
The program analyses ISC dhcpd shared network and pool usage and outputs the
results in a format selected by user.
.SH FIELDS
.TP
.I "shared net name"
Name of the shared-network for the range.
.TP
.I "first ip"
First IP in lease pool range.
.TP
.I "last ip"
Last IP in lease pool range.
.TP
.I "max"
Number of IPs which exist in a pool, shared network or all together.
.TP
.I "cur"
Number of leases currently in use.
.TP
.I "percent"
Percent of IPs currently in use compared to max.
.TP
.I "touch"
Number of IP's which appear in the lease file, but who's leases have expired.
A touched IP is either expired or abandoned. The touched IP count is
somewhat misleading when you try to determine if an IP pool is big enough; it
is a better indicator of whether a pool is too large.
.TP
.I "t+c"
The sum of Touched and Currently in-use leases.
.TP
.I "t+c perc"
Percent of IPs either touched or currently in use, compared to max.
.TP
.I "bu"
Failover pair can allocate these addresses. The count appears only if there
is failover configuration.
.TP
.I "bu perc"
Percent of addresses that failover pair can allocate. The percent appears
only if there is failover configuration.
.SH ARGUMENTS
.TP
\fB\-c\fR, \fB\-\-config\fR=\fIFILE\fR
Path to the dhcpd.conf file.
.TP
\fB\-l\fR, \fB\-\-leases\fR=\fIFILE\fR
Path to the dhcpd.leases file.
.TP
\fB\-s\fR, \fB\-\-sort\fR=\fI[nimcptTe]\fR
Sort ranges by chosen fields as a sorting keys. Maximum of five sort keys
can be defined. Keys weight from left to right i.e. if more weighting keys
are equal next one is used. The IP field is default sort key.
.TP
\fB\-r\fR, \fB\-\-reverse\fR
Sort results in reverse order.
.TP
\fB\-f\fR, \fB\-\-format\fR=\fI[thHcxX]\fR
Output format. The default is
text
.RI ( t ).
Standard html
.RI ( h )
outputs only the HTML tables, and is useful for embeding more complex web
pages. Full-html
.RI ( H )
provides complete HTML headers, etc., including in-line CSS. The
.RI ( c )
stands for comma-separated values. Output format xml
.RI ( x )
is similar to the dhcpstatus Perl module output. The extended xml
.RI ( X )
format will print ethernet address details.
.TP
\fB\-o\fR, \fB\-\-output\fR=\fIFILE\fR
.I File
where output is written. Default is stdout.
.TP
\fB\-L\fR, \fB\-\-limit\fR=\fINR\fR
The
.I NR
will limit what will be printed. Syntax is similar to
.IR chmod (1)
permission string. The
.I NR
limit string uses two digits which vary between
.IR 0 \ to \ 7 .
The first digit determines which headers to display, and the second digit
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 77 .
.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
.TP
\fB\-v\fR, \fB\-\-version\fR
Print version information to standard output and exit successfully.
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help to standard output and exit successfully.
.SH FILES
.TP
/etc/dhcpd.conf
ISC dhcpd configuration file.
.TP
/var/lib/dhcp/dhcpd.leases
ISC dhcpd lease file.
.SH AUTHOR
Written by Sami Kerola.
.br
XML support by Dominic Germain, Sogetel inc.
.PP
The software has FreeBSD License.
.SH "REPORTING BUGS"
Report bugs to
.MT kerolasa@iki.fi
Sami Kerola
.ME
.br
.UR http://dhcpd-pools.sourceforge.net/
Home page
.UE
.SH "SEE ALSO"
.BR dhcpd.leases (5),
.BR dhcpd.conf (5),
.BR chmod (1)

329
man/dhcpd-pools.1.in Normal file
View file

@ -0,0 +1,329 @@
'\" t
.TH DHCPD-POOLS "1" "2024-08-09" "@VERSION@" "User Commands"
.SH NAME
dhcpd-pools \- ISC dhcpd pools usage analysis
.SH SYNOPSIS
.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.
.SH OUTPUT FIELDS
.TP
.I "shared net name"
Name of the shared-network for the range.
.TP
.I "first ip"
First IP in lease pool range.
.TP
.I "last ip"
Last IP in lease pool range.
.TP
.I "max"
Number of IPs which exist in a pool, shared network or all together.
.TP
.I "cur"
Number of leases currently in use.
.TP
.I "percent"
Percent of IPs currently in use compared to max.
.TP
.I "touch"
Number of IP's which appear in the lease file, but who's leases have expired.
A touched IP is either expired or abandoned. The touched IP count is
somewhat misleading when you try to determine if an IP pool is big enough; it
is a better indicator of whether a pool is too large.
.TP
.I "t+c"
The sum of Touched and Currently in-use leases.
.TP
.I "t+c perc"
Percent of IPs either touched or currently in use, compared to max.
.TP
.I "bu"
Failover pair can allocate these addresses. The count appears only if there
is failover configuration.
.TP
.I "bu perc"
Percent of addresses that failover pair can allocate. The percent appears
only if there is failover configuration.
.SH OPTIONS
.TP
\fB\-c\fR, \fB\-\-config\fR=\fIFILE\fR
Path to the dhcpd.conf file. If the dhcpd.conf has include files they
can be analysed separately, that can be useful when trying to understand
or monitor subset of data.
.TP
\fB\-l\fR, \fB\-\-leases\fR=\fIFILE\fR
Path to the dhcpd.leases file.
.TP
\fB\-s\fR, \fB\-\-sort\fR=\fI[nimcptTe]\fR
Sort ranges by chosen fields as a sorting keys. Keys weight from left to
right, i.e., if more weighting keys are equal next one is used. The IP
field is default sort key.
.TP
\fB\-r\fR, \fB\-\-reverse\fR
Sort results in reverse order.
.TP
\fB\-f\fR, \fB\-\-format\fR=\fI[tHcxXjJ]\fR
Output format.
Text
.RI ( t ).
Full-html
.RI ( H )
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 )
is similar to the dhcpstatus Perl module output. The extended xml
.RI ( X )
format will print ethernet address details. The
.RI ( j )
will output in json format, which can be extended with
.RI ( J )
to include ethernet address.
.IP
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.
.TP
\fB\-L\fR, \fB\-\-limit\fR=\fINR\fR
The
.I NR
will limit what will be printed. Syntax is similar to
.IR chmod (1)
permission string. The
.I NR
limit string uses two digits which vary between
.IR 0 \ to \ 7 .
The first digit determines which headers to display, and the second digit
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@ .
.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
and
.B \-\-critical
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
warning level return value of the command is
.BR 1 .
If only range monitoring is needed one can use limit option for scoping,
for example
.IR \-L10 .
To monitor shared network only the limit would be
.IR \-L20 .
If warning percentage is not specified it defaults to
.BR @ALARM_WARN@ .
The
.I percent
argument allows fractions, e.g., 88.8, to be used.
.TP
\fB\-\-critical\fR=\fIpercent\fR
The option is similar to warning, with exception of return value which
is
.BR 2 .
If critical percentage is not specified it defaults to
.BR @ALARM_CRIT@ .
.TP
\fB\-\-warn\-count\fR=\fInumber\fR
A
.I number
of free leases before alarm is raised. When specified both \-\-warning
.I percent
and count
.I number
are required to be exceeded in order to alarm criteria being fulfilled.
.IP
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
is to set percentage to a level that makes small ranges to ring, and set the
count to match level when an enormous shared-network is too few free leases.
.IP
Defaults to 2^32, that is size of entire IPv4 address space.
.TP
\fB\-\-crit\-count\fR=\fInumber\fR
Same as \-\-warn\-count, but for critical alarms.
.TP
\fB\-\-snet\-alarms
Suppress range alarms that are part of shared networks. Use of this option
will keep alarm criteria applied to ranges that are not part of shared-net
along with shared-net alarms. This option may help reducing alarm noise for
configurations that has lots of small ranges in big shared-networks.
.TP
\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 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
\fB\-h\fR, \fB\-\-help\fR
Print help to standard output and exit successfully.
.SH EXAMPLES
.TP
Print ranges header, and analysis.
$ dhcpd-pools \-L 11 \-c dhcpd.conf \-l dhcpd.leases
.br
Ranges:
.br
shared net name [...]
.TP
Print shared networks and totals, both headers and results
$ dhcpd-pools \-L 66 \-c dhcpd.conf \-l dhcpd.leases shared net name
.br
[...]
.TP
Alarming
$ dhcpd-pools \-c dhcpd.conf \-l dhcpd.leases \-\-critical 80.1 \-\-warning 75
.br
CRITICAL: dhcpd-pools: Ranges; crit: 14 warn: 22 ok: 220 Shared nets; crit: 1 warn: 0 ok: 4
.IP
$ dhcpd-pools \-c dhcpd.conf \-l dhcpd.leases \-L 22 \-\-critical 70 \-\-warning 50
.br
[no-output]
.br
Suppress printing OK, and make alarm only to go off if shared networks
exceed critial or warning levels.
.SH FILES
.TP
@DHCPDCONF_FILE@
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.
.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@
@PACKAGE_MAINTAINER@
.ME
.br
.UR @PACKAGE_URL@
Home page
.UE
.SH "SEE ALSO"
.BR dhcpd.leases (5),
.BR dhcpd.conf (5),
.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}}

5
snippet/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/_Noreturn.h
/arg-nonnull.h
/c++defs.h
/unused-parameter.h
/warn-on-use.h

12
src/.gitignore vendored
View file

@ -1,12 +0,0 @@
gmon.out
gmon.sum
*.c.gcov
*.gcda
*.gcno
*~
*.o
.deps/
dhcpd-pools
Makefile
Makefile.in
tags

16
src/.indent.pro vendored Normal file
View file

@ -0,0 +1,16 @@
-linux
-TFILE
-Tconf_t
-Tipaddr_t
-Tleases_t
-Toff_t
-Trange_t
-Tsize_t
-Ttime_t
-Tuintmax_t
--blank-lines-after-declarations
--format-all-comments
--line-length100
--preprocessor-indentation1
--start-left-side-of-comments
--swallow-optional-blank-lines

View file

@ -1,17 +0,0 @@
## Makefile.am -- Process this file with automake to produce Makefile.in
bin_PROGRAMS = dhcpd-pools
AC_PROG_RANLIB = resolv
dhcpd_pools_SOURCES = \
analyze.c \
defaults.h \
dhcpd-pools.c \
dhcpd-pools.h \
getdata.c \
hash.c \
other.c \
output.c \
sort.c
INCLUDES = -I. -I..

24
src/Makemodule.am Normal file
View file

@ -0,0 +1,24 @@
## Makefile.am -- Process this file with automake to produce Makefile.in
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 $(MATH_LIBS)
dhcpd_pools_SOURCES = \
src/analyze.c \
src/dhcpd-pools.c \
src/dhcpd-pools.h \
src/getdata.c \
src/hash.c \
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

@ -33,7 +33,11 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/* #include <config.h> */
/*! \file analyze.c
* \brief Data analysis functions.
*/
#include <config.h>
#include <stddef.h>
#include <stdint.h>
@ -41,93 +45,62 @@
#include "dhcpd-pools.h"
/* Clean up data */
int ip_sort(struct leases_t *a, struct leases_t *b)
{
if (a->ip < b->ip)
return -1;
if (a->ip > b->ip)
return 1;
return 0;
}
int prepare_data(void)
/*! \brief Prepare data for analysis. The function will sort leases and
* ranges. */
void prepare_data(struct conf_t *state)
{
/* Sort leases */
HASH_SORT(leases, ip_sort);
return 0;
HASH_SORT(state->leases, leasecomp);
/* Sort ranges */
qsort(state->ranges, state->num_ranges, sizeof(struct range_t), &rangecomp);
}
/* Join leases and ranges into couter structs */
int 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 *range_p;
struct leases_t *l;
unsigned long i, k, block_size;
range_p = ranges;
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 */
for (i = 0; i < num_ranges; i++) {
/* Count IPs in use */
for (l = leases; l != NULL && range_p->last_ip >= l->ip; l = l->hh.next) {
if (l->ip < range_p->first_ip) {
/* should not be necessary */
continue;
}
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 = state->leases;
for (; l != NULL && ipcomp(&l->ip, &range_p->last_ip) <= 0; l = l->hh.next) {
if (unlikely(ipcomp(&l->ip, &range_p->first_ip) < 0))
continue; /* cannot happen? */
/* IP in range */
switch (l->type) {
case ACTIVE:
range_p->count++;
break;
case FREE:
range_p->touched++;
break;
case ACTIVE:
range_p->count++;
break;
case BACKUP:
range_p->backups++;
break;
}
if (range_p->shared_net) {
switch (l->type) {
case ACTIVE:
range_p->shared_net->used++;
break;
case FREE:
range_p->shared_net->touched++;
break;
case BACKUP:
range_p->shared_net->backups++;
break;
}
default:
abort();
}
}
/* Size of range, shared net & all networks */
block_size =
(unsigned int)(range_p->last_ip - range_p->first_ip - 1);
if (range_p->shared_net) {
range_p->shared_net->available += block_size;
/* Size of range size. */
block_size = get_range_size(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;
}
range_p++;
}
/* FIXME: During count of other shared networks default network and
* all networks got mixed to gether semantically. This 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 +=
range_p->last_ip - range_p->first_ip - 1;
shared_networks->used += range_p->count;
shared_networks->touched += range_p->touched;
shared_networks->backups += range_p->backups;
range_p++;
}
return 0;
}

View file

@ -1,48 +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.
*/
#ifndef DEFAULTS_H
# define DEFAULTS_H 1
/* Maximum line length in dhcpd.conf and dhcpd.leases */
static const size_t MAXLEN = 1024;
/* Maximum number of shared networks */
static const unsigned int SHARED_NETWORKS = 8192;
/* Maximum number of ranges */
unsigned int RANGES;
#endif /* DEFAULTS_H */

View file

@ -33,133 +33,259 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file dhcpd-pools.c
* \brief The main(), and core initialization.
*/
#include <config.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
extern char *malloc();
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <limits.h>
#include "close-stream.h"
#include "closeout.h"
#include "error.h"
#include "progname.h"
#include "quote.h"
#include "xalloc.h"
#include "defaults.h"
#include "dhcpd-pools.h"
int main(int argc, char **argv)
{
int i, c, sorts = 0;
int option_index = 0;
char *tmp;
struct range_t *tmp_ranges;
/* Function pointers */
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) (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);
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';
error(EXIT_FAILURE, 0, "return_limit: output mask %s is illegal", quote(optarg));
return 0;
}
/*! \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)
{
enum {
OPT_SNET_ALARMS = CHAR_MAX + 1,
OPT_WARN,
OPT_CRIT,
OPT_MINSIZE,
OPT_WARN_COUNT,
OPT_CRIT_COUNT,
OPT_COLOR,
OPT_SKIP,
OPT_SET_IPV,
OPT_MUSTACH
};
/* Options for getopt_long */
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},
{"warning", required_argument, NULL, OPT_WARN},
{"critical", required_argument, NULL, OPT_CRIT},
{"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);
/* FIXME: make these allocations dynamic up on need. */
config.dhcpdconf_file = safe_malloc(sizeof(char) * MAXLEN);
config.dhcpdlease_file = safe_malloc(sizeof(char) * MAXLEN);
config.output_file = safe_malloc(sizeof(char) * MAXLEN);
/* Make sure string has zero lenght if there is no
* command line option */
config.output_file[0] = '\0';
/* File location defaults */
strncpy(config.dhcpdconf_file, DHCPDCONF_FILE, MAXLEN - 1);
strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE, MAXLEN - 1);
tmp = OUTPUT_LIMIT;
config.output_limit[0] = (*tmp - '0');
tmp++;
config.output_limit[1] = (*tmp - '0');
fullhtml = false;
/* Make sure some output format is selected by default */
strncpy(config.output_format, OUTPUT_FORMAT, (size_t) 1);
/* Default sort order is by IPs small to big */
config.reverse_order = false;
/* Parse command line options */
while (1) {
c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh",
long_options, &option_index);
int c;
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 */
strncpy(config.output_format, optarg, (size_t) 1);
state->output_format = optarg[0];
break;
case 's':
/* Output sorting option */
sorts = strlen(optarg);
if (5 < sorts) {
warnx
("main: only first 5 sort orders will be used");
strncpy(config.sort, optarg, (size_t) 5);
sorts = 5;
} else {
strncpy(config.sort, optarg, (size_t) sorts);
}
for (i = 0; i < sorts; i++) {
field_selector(config.sort[i]);
{
/* Output sorting option */
struct output_sort *p = state->sorts;
char *ptr = optarg;
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++);
}
}
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 */
for (i = 0; i < 2; i++) {
if (optarg[i] >= '0' && optarg[i] < '8') {
config.output_limit[i] =
optarg[i] - '0';
} else {
errx(EXIT_FAILURE,
"main: output mask `%s' is illegal",
optarg);
}
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:
state->snet_alarms = 1;
break;
case OPT_WARN:
alarming = 1;
state->warning = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT:
alarming = 1;
state->critical = strtod_or_err(optarg, "illegal argument");
break;
case OPT_WARN_COUNT:
alarming = 1;
state->warn_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT_COUNT:
alarming = 1;
state->crit_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_MINSIZE:
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 */
print_version();
@ -167,75 +293,76 @@ int main(int argc, char **argv)
/* Print help */
usage(EXIT_SUCCESS);
default:
errx(EXIT_FAILURE,
"Try `%s --help' for more information.",
program_invocation_short_name);
error(EXIT_FAILURE, 0, "Try %s --help for more information.", program_name);
}
}
/* Output function selection */
switch (config.output_format[0]) {
case 't':
output_analysis = output_txt;
break;
case 'h':
output_analysis = output_html;
break;
case 'H':
output_analysis = output_html;
fullhtml = true;
break;
case 'x':
output_analysis = output_xml;
break;
case 'X':
output_analysis = output_xml;
break;
case 'c':
output_analysis = output_csv;
break;
default:
errx(EXIT_FAILURE, "main: unknown output format `%c'",
config.output_format[0]);
/* 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;
}
}
/*!\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)
{
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 */
prepare_memory();
parse_config(true, config.dhcpdconf_file, shared_networks);
parse_leases();
prepare_data();
do_counting();
tmp_ranges = safe_malloc(sizeof(struct range_t) * num_ranges);
if (sorts != 0) {
mergesort_ranges(ranges, num_ranges, tmp_ranges);
}
if (config.reverse_order == true) {
flip_ranges(ranges, tmp_ranges);
}
free(tmp_ranges);
output_analysis();
clean_up();
return (EXIT_SUCCESS);
}
/* Global allocations, counter resets etc */
int prepare_memory(void)
{
RANGES = 64;
num_ranges = num_shared_networks = 0;
shared_networks =
safe_malloc(sizeof(struct shared_network_t) * SHARED_NETWORKS);
ranges = safe_malloc(sizeof(struct range_t) * RANGES);
macaddr = NULL;
/* First shared network entry is all networks */
shared_networks->name = safe_strdup("All networks");
shared_networks->used = 0;
shared_networks->touched = 0;
shared_networks->backups = 0;
return 0;
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

@ -33,186 +33,340 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file dhcpd-pools.h
* \brief Global definitions of structures, enums, and function prototypes.
*/
#ifndef DHCPD_POOLS_H
# define DHCPD_POOLS_H 1
#include <config.h>
#include <arpa/inet.h>
#include <stddef.h>
#include <stdio.h>
#include <uthash.h>
# include <config.h>
# include <arpa/inet.h>
# include <stddef.h>
# include <stdio.h>
# include <string.h>
# include <uthash.h>
/* Feature test switches */
#define _POSIX_SOURCE 1
#define POSIXLY_CORRECT 1
/*! \def likely(x)
* \brief Symbolic call to __builtin_expect'ed branch.
*/
/*! \def unlikely(x)
* \brief Symbolic call to not-__builtin_expect'ed branch.
*/
# ifdef HAVE_BUILTIN_EXPECT
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# else
# define likely(x) (x)
# define unlikely(x) (x)
# endif
#ifdef HAVE_STDLIB_H
#else
extern void exit();
extern char *malloc();
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#endif /* STDC_HEADERS */
/*! \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
# define _DP_ATTRIBUTE_HOT /* empty */
# endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
# ifdef HAVE___PROGNAME
extern char *__progname;
# define program_invocation_short_name __progname
# else /* HAVE___PROGNAME */
# ifdef HAVE_GETEXECNAME
# include <stdlib.h>
# define program_invocation_short_name \
prog_inv_sh_nm_from_file(getexecname(), 0)
# else /* HAVE_GETEXECNAME */
# define program_invocation_short_name \
prog_inv_sh_nm_from_file(__FILE__, 1)
# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
char prog_inv_sh_nm_buf[256];
inline char *prog_inv_sh_nm_from_file(char *f, char stripext)
{
char *t;
if ((t = strrchr(f, '/')) != NULL) {
t++;
} else {
t = f;
}
strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL) {
*t = '\0';
}
return prog_inv_sh_nm_buf;
}
# endif
#endif
/* Structures and unions */
struct configuration_t {
char *dhcpdconf_file;
char *dhcpdlease_file;
char output_format[2];
char sort[6];
int reverse_order;
char *output_file;
int output_limit[2];
/*! \union ipaddr_t
* \brief Memory space for a binary IP address saving. */
union ipaddr_t {
uint32_t v4;
unsigned char v6[16];
};
/*! \enum dhcp_version
* \brief The IP version, IPv4 or IPv6, served by the dhcpd.
*/
enum dhcp_version {
IPvUNKNOWN,
IPv4,
IPv6
};
/*! \enum prefix_t
* \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,
PREFIX_BINDING_STATE_FREE,
PREFIX_BINDING_STATE_ABANDONED,
PREFIX_BINDING_STATE_EXPIRED,
PREFIX_BINDING_STATE_RELEASED,
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. This data entry is
* also used for 'all networks' counting.
*/
struct shared_network_t {
char *name;
unsigned long int available;
unsigned long int used;
unsigned long int touched;
unsigned long int backups;
double available;
double used;
double touched;
double backups;
struct shared_network_t *next;
int netmask;
};
/*! \struct range_t
* \brief Counters for an individual range.
*/
struct range_t {
struct shared_network_t *shared_net;
uint32_t first_ip;
uint32_t last_ip;
unsigned long int count;
unsigned long int touched;
unsigned long int backups;
union ipaddr_t first_ip;
union ipaddr_t last_ip;
double count;
double touched;
double backups;
};
struct macaddr_t {
char *ethernet;
char *ip;
struct macaddr_t *next;
/*! \struct output_helper_t
* \brief Various per range and shared net temporary calculation results.
*/
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. These are the possible values in struct leases_t.
*/
enum ltype {
ACTIVE,
FREE,
BACKUP
};
/*! \struct leases_t
* \brief An individual lease. These leaases are hashed.
*/
struct leases_t {
uint32_t ip; /* ip as key */
enum ltype type;
union ipaddr_t ip; /* ip as key */
char *ethernet;
UT_hash_handle hh;
enum ltype type;
char *ends;
char *starts;
char *hostname;
};
/* Global variables */
struct configuration_t config;
static int const output_limit_bit_1 = 1;
static int const output_limit_bit_2 = 2;
static int const output_limit_bit_3 = 4;
unsigned int fullhtml;
struct shared_network_t *shared_networks;
unsigned int num_shared_networks;
struct range_t *ranges;
unsigned int num_ranges;
struct leases_t *leases;
unsigned long int num_leases;
unsigned long int num_touches;
unsigned long int num_backups;
struct macaddr_t *macaddr;
/*! \enum limbits
* \brief Output limit bits.
*/
enum limbits {
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 value.
*/
# define STATE_OK 0
# define STATE_WARNING 1
# define STATE_CRITICAL 2
/*! \var comparer_t
* \brief Function pointer holding sort algorithm.
*/
typedef int (*comparer_t) (struct range_t *r1, struct range_t *r2);
/*! \struct output_sort
* \brief Linked list of sort functions.
*/
struct output_sort {
comparer_t func;
struct output_sort *next;
};
/*! \struct conf_t
* \brief Runtime configuration state.
*/
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. */
};
/* Function prototypes */
int prepare_memory(void);
int parse_leases(void);
void parse_config(int, const char *__restrict, struct shared_network_t *__restrict)
__attribute__ ((nonnull(2, 3)));
int nth_field(int n, char *__restrict dest, const char *__restrict src)
__attribute__ ((nonnull(2, 3)))
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
__attribute__ ((__hot__))
#endif
;
int prepare_data(void);
int do_counting(void);
void flip_ranges(struct range_t *__restrict ranges, struct range_t *__restrict tmp_ranges)
__attribute__ ((nonnull(1, 2)));
/* support functions */
void *safe_malloc(const size_t size)
#if __GNUC__ >= 3
__attribute__ ((__malloc__))
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
__attribute__ ((__alloc_size__((1))))
#endif
#endif
;
void *safe_realloc(void *__restrict ptr, const size_t size);
char *safe_strdup(const char *__restrict str) __attribute__ ((nonnull(1)));
int xstrstr(char *__restrict a, char *__restrict b, int len);
int close_stream(FILE * stream);
void close_stdout(void);
void print_version(void) __attribute__ ((noreturn));
void usage(int status) __attribute__ ((noreturn));
/* qsort required functions... */
/* ...for ranges and... */
int intcomp(const void *__restrict x, const void *__restrict y) __attribute__ ((nonnull(1, 2)));
int rangecomp(const void *__restrict r1, const void *__restrict r2)
__attribute__ ((nonnull(1, 2)));
/* sort function pointer and functions */
int sort_name(void);
unsigned long int (*returner) (struct range_t r);
unsigned long int ret_ip(struct range_t r);
unsigned long int ret_cur(struct range_t r);
unsigned long int ret_max(struct range_t r);
unsigned long int ret_percent(struct range_t r);
unsigned long int ret_touched(struct range_t r);
unsigned long int ret_tc(struct range_t r);
unsigned long int ret_tcperc(struct range_t r);
void field_selector(char c);
int get_order(struct range_t *__restrict left, struct range_t *__restrict right)
__attribute__ ((nonnull(1, 2)));
void mergesort_ranges(struct range_t *__restrict orig, int size, struct range_t *__restrict temp)
__attribute__ ((nonnull(1, 3)));
/* output function pointer and functions */
int (*output_analysis) (void);
int output_txt(void);
int output_html(void);
int output_xml(void);
int output_csv(void);
/* Memory release, file closing etc */
void clean_up(void);
/* Hash functions */
void add_lease(int ip, enum ltype type);
struct leases_t * find_lease(int ip);
void delete_lease(struct leases_t * lease);
void delete_all_leases();
#endif /* DHCPD_POOLS_H */
/* 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);
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);
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);
extern double get_range_size_v4(const struct range_t *r);
extern double get_range_size_v6(const struct range_t *r);
/* 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);
/* 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
__attribute__ ((unused)),
const struct leases_t *restrict b __attribute__ ((unused)));
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 (*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);
extern int comp_tcperc(struct range_t *r1, struct range_t *r2);
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);
extern double ret_tcperc(struct range_t r);
#endif /* DHCPD_POOLS_H */

View file

@ -33,237 +33,244 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file getdata.c
* \brief Functions to read data from dhcpd.conf and dhcdp.leases files.
*/
#include <config.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else /* Not STDC_HEADERS */
extern char *malloc();
#define EXIT_FAILURE 1 /* Failing exit status. */
#define EXIT_SUCCESS 0 /* Successful exit status. */
#endif /* STDC_HEADERS */
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <err.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>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include "defaults.h"
#include "error.h"
#include "xalloc.h"
#include "dhcpd-pools.h"
/* Parse dhcpd.leases file. All performance boosts for this function are
* wellcome */
int parse_leases(void)
/*! \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(struct conf_t *state)
{
FILE *dhcpd_leases;
char *line, *ipstring, *macstring = NULL;
struct in_addr inp;
struct stat lease_file_stats;
struct macaddr_t *macaddr_p = NULL;
int sw_active_lease = 0;
struct leases_t * lease;
num_touches = num_leases = num_backups = 0;
dhcpd_leases = fopen(config.dhcpdlease_file, "r");
if (dhcpd_leases == NULL) {
err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file);
}
#ifdef POSIX_FADV_WILLNEED
posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_WILLNEED);
if (errno) {
err(EXIT_FAILURE, "parse_leases: fadvise %s",
config.dhcpdlease_file);
}
#endif /* POSIX_FADV_WILLNEED */
#ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL);
if (errno) {
err(EXIT_FAILURE, "parse_leases: fadvise %s",
config.dhcpdlease_file);
}
#endif /* POSIX_FADV_SEQUENTIAL */
/* 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)) {
err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file);
}
line = safe_malloc(sizeof(char) * MAXLEN);
ipstring = safe_malloc(sizeof(char) * MAXLEN);
if (config.output_format[0] == 'X') {
macstring = safe_malloc(sizeof(char) * 18);
macaddr = safe_malloc(sizeof(struct macaddr_t));
macaddr_p = macaddr;
macaddr_p->next = NULL;
}
char *line, *ipstring, macstring[20], *stop, endsstr[30], startsstr[30], hostnamestr[MAXLEN];
union ipaddr_t addr;
struct leases_t *lease;
dhcpd_leases = fopen(state->dhcpdlease_file, "r");
if (dhcpd_leases == NULL)
error(EXIT_FAILURE, errno, "parse_leases: %s", state->dhcpdlease_file);
#ifdef HAVE_POSIX_FADVISE
# ifdef POSIX_FADV_SEQUENTIAL
if (posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL) != 0)
error(EXIT_FAILURE, errno, "parse_leases: fadvise %s", state->dhcpdlease_file);
# endif /* POSIX_FADV_SEQUENTIAL */
#endif /* HAVE_POSIX_FADVISE */
line = xmalloc(sizeof(char) * MAXLEN);
line[0] = '\0';
ipstring = xmalloc(sizeof(char) * MAXLEN);
ipstring[0] = '\0';
endsstr[0] = '\0';
startsstr[0] = '\0';
hostnamestr[0] = '\0';
while (!feof(dhcpd_leases)) {
if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases)) {
err(EXIT_FAILURE, "parse_leases: %s",
config.dhcpdlease_file);
}
/* It's a lease, save IP */
if (xstrstr(line, "lease", 5)) {
strncpy(ipstring, line, MAXLEN);
nth_field(2, ipstring, ipstring);
inet_aton(ipstring, &inp);
sw_active_lease = 0;
}
/* Copy IP to correct array */
else if (xstrstr(line, " binding state active", 22)) {
if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases))
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 + (state->ip_version ==
IPv4 ? 6 : 9), ' ', strlen(line));
if (stop != NULL) {
--stop;
*stop = '\0';
}
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(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(htonl(inp.s_addr))) != NULL) {
delete_lease(lease);
}
add_lease(htonl(inp.s_addr),ACTIVE);
sw_active_lease = 1;
} else if (xstrstr(line, " binding state free", 20)) {
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(htonl(inp.s_addr))) != NULL) {
delete_lease(lease);
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 (state->print_mac_addreses == 0)
break;
memcpy(macstring, line + 20, 17);
macstring[17] = '\0';
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';
}
add_lease(htonl(inp.s_addr),FREE);
} else if (xstrstr(line, " binding state backup", 22)) {
/* remove old entry, if exists */
if ((lease = find_lease(htonl(inp.s_addr))) != NULL) {
delete_lease(lease);
}
add_lease(htonl(inp.s_addr),BACKUP);
}
if ((macaddr != NULL)
&& (sw_active_lease == 1)
&& (xstrstr(line, " hardware ethernet", 19))) {
nth_field(3, macstring, line);
if (macstring) {
macstring[17] = '\0';
macaddr_p->ethernet = safe_strdup(macstring);
macaddr_p->ip = safe_strdup(ipstring);
macaddr_p->next = safe_malloc(sizeof(struct macaddr_t));
macaddr_p = macaddr_p->next;
macaddr_p->next = NULL;
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 */ ;
}
}
#undef HAS_PREFIX
free(line);
free(ipstring);
if (macaddr != NULL) {
free(macstring);
}
fclose(dhcpd_leases);
return 0;
}
/* Like strcpy but for field which is separated by white spaces. Number of
* first field is 1 and not 0 like C programs should have. Question of
* semantics, send mail to author if this annoys. All performance boosts for
* this function are well come. */
int nth_field(int n, char *restrict dest, const char *restrict src)
/*! \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(struct conf_t *state, char const *restrict s)
{
int i, j = 0, wordn = 0, len;
len = strlen(src);
for (i = 0; i < len; i++) {
if (isspace(src[i])) {
if (!(wordn < n)) {
dest[j] = '\0';
break;
}
j = 0;
} else {
if (j == 0) {
wordn++;
}
if (wordn == n) {
dest[j] = src[i];
}
j++;
}
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;
}
return 0;
if (strstr(s, "include"))
return ITS_AN_INCLUDE;
return ITS_NOTHING_INTERESTING;
}
/* dhcpd.conf interesting words */
int is_interesting_config_clause(char *restrict s)
/*! \brief Flip first and last IP in range if they are in unusual order.
*/
static void reorder_last_first(struct range_t *range_p)
{
if (strstr(s, "range")) {
return 3;
} else if (strstr(s, "shared-network")) {
return 1;
} else if (strstr(s, "include")) {
return 4;
} else {
return 0;
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;
}
}
/* FIXME: This spagetti monster function need to be rewrote at least ones. */
void parse_config(int is_include, const char *restrict config_file,
/*! \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;
int quote = 0, braces = 0, argument = 0;
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, c;
char *word;
int braces_shared = 1000;
struct in_addr inp;
struct range_t *range_p;
union ipaddr_t addr;
struct range_t *range_p = NULL;
word = safe_malloc(sizeof(char) * MAXLEN);
if (is_include) {
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) {
err(EXIT_FAILURE, "parse_config: %s", config_file);
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 POSIX_FADV_WILLNEED
posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_WILLNEED);
if (errno) {
err(EXIT_FAILURE, "parse_config: fadvise %s", config_file);
}
#endif /* POSIX_FADV_WILLNEED */
#ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(fileno(dhcpd_config), 0, 0, POSIX_FADV_SEQUENTIAL);
if (errno) {
err(EXIT_FAILURE, "parse_config: fadvise %s", config_file);
}
#endif /* POSIX_FADV_SEQUENTIAL */
#ifdef HAVE_POSIX_FADVISE
# 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);
# endif /* POSIX_FADV_SEQUENTIAL */
#endif /* HAVE_POSIX_FADVISE */
/* Very hairy stuff begins. */
while (!feof(dhcpd_config)) {
while (unlikely(!feof(dhcpd_config))) {
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 == false) {
comment = true;
}
if (quote == 0)
comment = 1;
continue;
case '"':
if (comment == false) {
if (comment == 0) {
quote++;
/* Either one or zero */
quote = quote % 2;
@ -272,172 +279,201 @@ void parse_config(int is_include, const char *restrict config_file,
case '\n':
/* New line resets comment section, but
* not if quoted */
if (quote == false) {
comment = false;
}
if (quote == 0)
comment = 0;
break;
case ';':
/* Quoted colon does not mean new clause */
if (0 < quote) {
if (0 < quote)
break;
}
if (comment == false && argument != 2 && argument != 4) {
newclause = true;
if (comment == 0
&& argument != ITS_A_RANGE_FIRST_IP
&& argument != ITS_A_RANGE_SECOND_IP && argument != ITS_AN_INCLUDE) {
newclause = 1;
i = 0;
} else if (argument == 2) {
} 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) {
/* Range ends to ; and this hair in code
* make two ranges wrote to gether like...
* make two ranges wrote together like...
*
* range 10.20.30.40 10.20.30.41;range 10.20.30.42 10.20.30.43;
*
* ...to be interpreted correctly. */
c = ' ';
break;
} else if (argument == ITS_A_RANGE_SECOND_IP && i == 0) {
if (!range_p) {
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;
}
continue;
case '{':
if (0 < quote) {
if (0 < quote)
break;
}
if (comment == 0) {
if (comment == 0)
braces++;
}
/* i == 0 detects word that ends to brace like:
*
* shared-network DSL{ ... */
if (i == 0) {
newclause = true;
newclause = 1;
continue;
} else {
break;
}
break;
case '}':
if (0 < quote) {
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 == 0)) {
if (comment == 1 || (newclause == 0 && argument == ITS_NOTHING_INTERESTING))
continue;
}
/* Strip white spaces before new clause word. */
if ((newclause == true || argument != 0) && isspace(c)
&& i == 0) {
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 != 0)
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;
if (MAXLEN == i) {
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;
}
if (word[i - 1] != '{')
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 = 1;
}
/* words after range, shared-network or include */
else if (argument != 0) {
else if (argument != ITS_NOTHING_INTERESTING) {
word[i] = '\0';
newclause = false;
newclause = 0;
i = 0;
switch (argument) {
case 2:
case ITS_A_RANGE_SECOND_IP:
/* printf ("range 2nd ip: %s\n", word); */
range_p = ranges + num_ranges;
inet_aton(word, &inp);
argument = 0;
range_p->last_ip = htonl(inp.s_addr) + 1;
range_p = state->ranges + state->num_ranges;
argument = ITS_NOTHING_INTERESTING;
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);
}
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 =
safe_realloc(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 3:
/* printf ("range 1nd ip: %s\n", word); */
range_p = ranges + num_ranges;
if (!(inet_aton(word, &inp))) {
/* word was not ip, try
* again */
case ITS_A_RANGE_FIRST_IP:
/* 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 = 0;
argument = ITS_A_RANGE_SECOND_IP;
break;
case ITS_A_SHAREDNET:
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;
}
range_p->first_ip = htonl(inp.s_addr) - 1;
argument = 2;
break;
case 1:
/* printf ("shared-network named: %s\n", word); */
num_shared_networks++;
shared_p =
shared_networks + num_shared_networks;
shared_p->name = safe_strdup(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
* away by reallocationg
* more space. */
errx(EXIT_FAILURE,
"parse_config: increase default.h SHARED_NETWORKS and recompile");
}
argument = 0;
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->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 4:
/* printf ("include file: %s\n", word); */
argument = 0;
parse_config(false, word, shared_p);
newclause = true;
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 0:
case ITS_AN_INCLUDE:
/* printf ("include file: %s\n", word); */
argument = ITS_NOTHING_INTERESTING;
parse_config(state, 0, word, shared_p);
newclause = 1;
break;
case ITS_NOTHING_INTERESTING:
/* printf ("nothing interesting: %s\n", word); */
argument = 0;
argument = ITS_NOTHING_INTERESTING;
break;
default:
warnx("impossible occurred, report a bug");
assert(0);
puts("impossible occurred, report a bug");
abort();
}
}
}

View file

@ -33,48 +33,124 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file hash.c
* \brief The leases hash functions. The hash sorting is key to make
* analysis happen as quick as possible..
*/
#include <config.h>
#include <stdlib.h>
#include "xalloc.h"
#include "dhcpd-pools.h"
void add_lease(int ip, enum ltype type)
#define HASH_FIND_V6(head, findv6, out) HASH_FIND(hh, head, findv6, 16, out)
#define HASH_ADD_V6(head, v6field, add) HASH_ADD(hh, head, v6field, 16, add)
/*! \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(struct conf_t *state __attribute__ ((unused)), union ipaddr_t *addr
__attribute__ ((unused)), enum ltype type __attribute__ ((unused)))
{
struct leases_t *l;
l = safe_malloc(sizeof(struct leases_t));
l->ip = ip;
l->type = type;
HASH_ADD_INT(leases, ip, l);
}
struct leases_t *find_lease(int ip)
void add_lease_v4(struct conf_t *state, union ipaddr_t *addr, enum ltype type)
{
struct leases_t *l;
HASH_FIND_INT(leases, &ip, l);
l = xmalloc(sizeof(struct leases_t));
copy_ipaddr(&l->ip, addr);
l->type = type;
HASH_ADD_INT(state->leases, ip.v4, l);
l->ethernet = NULL;
l->ends = NULL;
l->starts = NULL;
l->hostname = NULL;
}
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(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(struct conf_t *state __attribute__ ((unused)), union ipaddr_t *addr
__attribute__ ((unused)))
{
return NULL;
}
struct leases_t *find_lease_v4(struct conf_t *state, union ipaddr_t *addr)
{
struct leases_t *l;
HASH_FIND_INT(state->leases, &addr->v4, l);
return l;
}
void delete_lease(struct leases_t *lease)
struct leases_t *find_lease_v6(struct conf_t *state, union ipaddr_t *addr)
{
HASH_DEL(leases, lease);
struct leases_t *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 conf_t *state, struct leases_t *lease)
{
free(lease->ethernet);
free(lease->ends);
free(lease->starts);
free(lease->hostname);
HASH_DEL(state->leases, lease);
free(lease);
}
/* uthash >= 1.9.2
void delete_all_leases()
/*! \brief Delete all leases from hash array. */
#ifdef HASH_ITER
void delete_all_leases(struct conf_t *state)
{
struct leases_t *l, *tmp;
HASH_ITER(hh, leases, l, tmp) {
HASH_DEL(leases, l);
free(l);
}
}
*/
void delete_all_leases()
{
struct leases_t *l;
while (leases) {
l = leases;
HASH_DEL(leases, l); /* leases advances to next on delete */
HASH_ITER(hh, state->leases, l, tmp) {
free(l->ethernet);
free(l->ends);
free(l->starts);
free(l->hostname);
HASH_DEL(state->leases, l);
free(l);
}
}
#else
void delete_all_leases(struct conf_t *state)
{
while (state->leases) {
struct leases_t *l;
l = state->leases;
free(l->ethernet);
free(l->ends);
free(l->starts);
free(l->hostname);
HASH_DEL(state->leases, l); /* leases advances to next on delete */
free(l);
}
}
#endif

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

@ -33,215 +33,627 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file other.c
* \brief Collection of various functions.
*/
#include <config.h>
#include <arpa/inet.h>
#include <errno.h>
#include <limits.h>
#include <netinet/in.h>
#include <stddef.h>
#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"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
extern void exit();
extern char *malloc();
extern void _exit();
#endif
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);
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <err.h>
#include <errno.h>
#ifdef HAVE_ERROR_H
#include <error.h>
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#ifdef HAVE_STDIO_EXT_H
#include <stdio_ext.h>
#endif
#include <unistd.h>
#ifndef HAVE_ERROR
#ifdef __FreeBSD__
#define error errc
#endif
#endif
#ifndef HAVE___FPENDING
static size_t __fpending(FILE * fp)
/*! \brief Set function pointers depending on IP version.
* \param ip IP version.
*/
void set_ipv_functions(struct conf_t *state, int version)
{
return (fp->_p - fp->_bf._base);
switch (version) {
case IPv4:
state->ip_version = version;
add_lease = add_lease_v4;
copy_ipaddr = copy_ipaddr_v4;
find_lease = find_lease_v4;
get_range_size = get_range_size_v4;
ipcomp = ipcomp_v4;
leasecomp = leasecomp_v4;
ntop_ipaddr = ntop_ipaddr_v4;
parse_ipaddr = parse_ipaddr_v4;
cidr_last = cidr_last_v4;
xstrstr = xstrstr_v4;
break;
case IPv6:
state->ip_version = version;
add_lease = add_lease_v6;
copy_ipaddr = copy_ipaddr_v6;
find_lease = find_lease_v6;
get_range_size = get_range_size_v6;
ipcomp = ipcomp_v6;
leasecomp = leasecomp_v6;
ntop_ipaddr = ntop_ipaddr_v6;
parse_ipaddr = parse_ipaddr_v6;
cidr_last = cidr_last_v6;
xstrstr = xstrstr_v6;
break;
case IPvUNKNOWN:
state->ip_version = version;
add_lease = add_lease_init;
copy_ipaddr = copy_ipaddr_init;
find_lease = find_lease_init;
get_range_size = get_range_size_init;
ipcomp = ipcomp_init;
leasecomp = leasecomp_init;
ntop_ipaddr = ntop_ipaddr_init;
parse_ipaddr = parse_ipaddr_init;
cidr_last = NULL;
xstrstr = xstrstr_init;
break;
default:
abort();
}
return;
}
#endif
/* Simple memory allocation wrapper */
void *safe_malloc(const size_t size)
/*! \brief Convert text string IP address from either IPv4 or IPv6 to an integer.
* \param src An IP string in either format.
* \param dst An union which will hold conversion result.
* \return Was parsing successful.
*/
int parse_ipaddr_init(struct conf_t *state, const char *restrict src, union ipaddr_t *restrict dst)
{
void *ret = malloc(size);
if (ret == NULL) {
err(EXIT_FAILURE,
"safe_malloc: cannot allocate %lu bytes: ", size);
struct in_addr addr;
struct in6_addr addr6;
if (inet_aton(src, &addr) == 1)
set_ipv_functions(state, IPv4);
else if (inet_pton(AF_INET6, src, &addr6) == 1)
set_ipv_functions(state, IPv6);
else
return 0;
return parse_ipaddr(state, src, 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;
rv = inet_aton(src, &addr);
dst->v4 = ntohl(addr.s_addr);
return rv == 1;
}
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;
rv = inet_pton(AF_INET6, src, &addr);
memcpy(&dst->v6, addr.s6_addr, sizeof(addr.s6_addr));
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);
}
return ret;
/* 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);
}
/* Simple memory reallocation wrapper */
void *safe_realloc(void *ptr, const size_t size)
/*! \brief Copy IP address to union.
*
* \param dst Destination for a binary IP address.
* \param src Sourse of an IP address. */
void copy_ipaddr_init(union ipaddr_t *restrict dst __attribute__ ((unused)),
const union ipaddr_t *restrict src __attribute__ ((unused)))
{
void *ret = realloc(ptr, size);
if (!ret && size)
err(EXIT_FAILURE,
"safe_realloc: cannot allocate %lu bytes", size);
return ret;
}
void copy_ipaddr_v4(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src)
{
dst->v4 = src->v4;
}
void copy_ipaddr_v6(union ipaddr_t *restrict dst, const union ipaddr_t *restrict src)
{
memcpy(&dst->v6, &src->v6, sizeof(src->v6));
}
/*! \brief Convert an address to string. This function will convert the
* IPv4 addresses to 123.45.65.78 format, and the IPv6 addresses to it's
* native format depending on which version of the addressing is found to
* be in use.
*
* \param ip Binary IP address.
* \return Printable address.
*/
const char *ntop_ipaddr_init(const union ipaddr_t *ip __attribute__ ((unused)))
{
static char buffer = '\0';
return &buffer;
}
const char *ntop_ipaddr_v4(const union ipaddr_t *ip)
{
static char buffer[INET_ADDRSTRLEN];
struct in_addr addr;
addr.s_addr = htonl(ip->v4);
return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
}
const char *ntop_ipaddr_v6(const union ipaddr_t *ip)
{
static char buffer[INET6_ADDRSTRLEN];
struct in6_addr addr;
memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr));
return inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer));
}
/*! \brief Calculate how many addresses there are in a range.
*
* \param r Pointer to range structure, which has information about first
* and last IP in the range.
* \return Size of a range.
*/
double get_range_size_init(const struct range_t *r __attribute__ ((unused)))
{
return 0;
}
double get_range_size_v4(const struct range_t *r)
{
return r->last_ip.v4 - r->first_ip.v4 + 1;
}
double get_range_size_v6(const struct range_t *r)
{
double size = 0;
int i;
/* When calculating the size of an IPv6 range overflow may occur.
* In that case only the last LONG_BIT bits are preserved, thus
* we just skip the first (16 - LONG_BIT) bits... */
for (i = 0; i < 16; i++) {
size *= 256;
size += (int)r->last_ip.v6[i] - (int)r->first_ip.v6[i];
}
return size + 1;
}
/*! \fn xstrstr_init(const char *restrict str)
* \brief Determine if the dhcpd is in IPv4 or IPv6 mode. This function
* may be needed when dhcpd.conf file has zero IP version hints.
*
* \param str A line from dhcpd.conf
* \return prefix_t enum value
*/
int xstrstr_init(struct conf_t *state, const char *restrict str)
{
if (!memcmp("lease ", str, 6)) {
set_ipv_functions(state, IPv4);
return PREFIX_LEASE;
}
if (!memcmp(" iaaddr ", str, 9)) {
set_ipv_functions(state, IPv6);
return PREFIX_LEASE;
}
return NUM_OF_PREFIX;
}
/*! \fn xstrstr_v4(const char *restrict str)
* \brief parse lease file in IPv4 mode
*
* \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(char *restrict a, char *restrict b, int len)
xstrstr_v4(struct conf_t *state __attribute__ ((unused)), const char *restrict str)
{
int i;
/* two spaces are very common in lease file, after them
* nearly everything differs */
if (a[2] != b[2]) {
return false;
}
/* " binding state " == 16 chars, this will skip right
* to first difering line. */
if (17 < len && a[17] != b[17]) {
return false;
}
/* looking good, double check the whole thing... */
for (i = 0; a[i] != '\0' && b[i] != '\0'; i++) {
if (a[i] != b[i]) {
return false;
size_t len;
if (str[2] == 'b' || str[2] == 'h')
len = strlen(str);
else
len = 0;
if (15 < len) {
switch (str[16]) {
case 'f':
if (!memcmp(" binding state free;", str, 21))
return PREFIX_BINDING_STATE_FREE;
break;
case 'a':
if (!memcmp(" binding state active;", str, 23))
return PREFIX_BINDING_STATE_ACTIVE;
if (!memcmp(" binding state abandoned;", str, 25))
return PREFIX_BINDING_STATE_ABANDONED;
break;
case 'e':
if (!memcmp(" binding state expired;", str, 24))
return PREFIX_BINDING_STATE_EXPIRED;
break;
case 'r':
if (!memcmp(" binding state released;", str, 25))
return PREFIX_BINDING_STATE_RELEASED;
break;
case 'b':
if (!memcmp(" binding state backup;", str, 23))
return PREFIX_BINDING_STATE_BACKUP;
break;
case 'n':
if (!memcmp(" hardware ethernet", str, 19))
return PREFIX_HARDWARE_ETHERNET;
break;
default:
break;
}
}
return true;
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;
}
/* Simple strdup wrapper */
char *safe_strdup(const char *restrict str)
/*! \fn xstrstr_v4(const char *restrict str)
* \brief parse lease file in IPv6 mode
*
* \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_v6(struct conf_t *state __attribute__ ((unused)), const char *restrict str)
{
char *ret = strdup(str);
size_t len;
if (!ret && str)
err(EXIT_FAILURE, "cannot duplicate string");
return ret;
if (str[4] == 'b' || str[2] == 'h')
len = strlen(str);
else
len = 0;
if (17 < len) {
switch (str[18]) {
case 'f':
if (!memcmp(" binding state free;", str, 23))
return PREFIX_BINDING_STATE_FREE;
break;
case 'a':
if (!memcmp(" binding state active;", str, 25))
return PREFIX_BINDING_STATE_ACTIVE;
if (!memcmp(" binding state abandoned;", str, 27))
return PREFIX_BINDING_STATE_ABANDONED;
break;
case 'e':
if (!memcmp(" binding state expired;", str, 26))
return PREFIX_BINDING_STATE_EXPIRED;
break;
case 'r':
if (!memcmp(" binding state released;", str, 27))
return PREFIX_BINDING_STATE_RELEASED;
break;
case 'b':
if (!memcmp(" binding state backup;", str, 25))
return PREFIX_BINDING_STATE_BACKUP;
break;
case 'n':
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;
}
void flip_ranges(struct range_t *restrict ranges, struct range_t *restrict tmp_ranges)
/*! \brief Parse option argument color mode.
*
* \param Color mode string.
* \return color mode enum.
*/
int parse_color_mode(const char *restrict arg)
{
unsigned int i = num_ranges - 1, j;
for (j = 0; j < num_ranges; j++) {
*(tmp_ranges + j) = *(ranges + i);
i--;
}
memcpy(ranges, tmp_ranges, num_ranges * sizeof(struct range_t));
if (!strcmp(arg, "always"))
return color_on;
if (!strcmp(arg, "auto"))
return color_auto;
if (!strcmp(arg, "never"))
return color_off;
return color_unknown;
}
/* Free memory, flush buffers etc */
void clean_up(void)
/*! \brief Return a double floating point value.
*
* \param str String to be converted to a double.
* \param errmesg Exit error message if conversion fails.
* \return Binary result of string to double conversion.
*/
double strtod_or_err(const char *restrict str, const char *restrict errmesg)
{
unsigned int i;
double num;
char *end = NULL;
/* Just in case there something in buffers */
if (fflush(NULL)) {
warn("clean_up: fflush");
}
num_shared_networks++;
for (i = 0; i < num_shared_networks; i++) {
free((shared_networks + i)->name);
}
free(config.dhcpdconf_file);
free(config.dhcpdlease_file);
free(config.output_file);
free(ranges);
delete_all_leases();
free(shared_networks);
}
int close_stream(FILE * stream)
{
const int some_pending = (__fpending(stream) != 0);
const int prev_fail = (ferror(stream) != 0);
const int fclose_fail = (fclose(stream) != 0);
if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
if (!fclose_fail)
errno = 0;
return EOF;
}
if (str == NULL || *str == '\0')
goto err;
errno = 0;
num = strtod(str, &end);
if (errno || str == end || (end && *end))
goto err;
return num;
err:
error(EXIT_FAILURE, errno, "%s: %s", errmesg, quote(str));
return 0;
}
/* Use atexit(); */
void close_stdout(void)
/*! \brief Reverse range.
* Used before output, if a caller has requested reverse sorting. */
void flip_ranges(struct conf_t *state)
{
if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
char const *write_error = "write error";
error(0, errno, "%s", write_error);
_exit(EXIT_FAILURE);
}
unsigned int i = state->num_ranges - 1, j;
struct range_t *tmp_ranges;
if (close_stream(stderr) != 0)
_exit(EXIT_FAILURE);
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(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(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"
"Written by Sami Kerola.\n"
"XML support by Dominic Germain, Sogetel inc.\n\n"
"The software has FreeBSD License.\n", PACKAGE_STRING);
"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"
"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);
}
/*! \brief Command line help screen. */
void __attribute__ ((__noreturn__)) usage(int status)
{
FILE *out;
out = status != 0 ? stderr : stdout;
FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
fprintf(out, "\
Usage: %s [OPTIONS]\n\n\
This is ISC dhcpd pools usage analyzer.\n\
\n", program_invocation_short_name);
fprintf(out, "\
-c, --config=FILE path to the dhcpd.conf file\n\
-l, --leases=FILE path to the dhcpd.leases file\n\
-f, --format=[thHcxX] output format\n\
t for text\n\
h for html table\n\
H for full html page\n\
x for xml\n\
X for xml with active lease details\n\
c for comma separated values\n");
fprintf(out, "\
-s, --sort=[nimcptTe] sort ranges by\n\
n name\n\
i IP\n\
m maxium\n\
c current\n\
p percent\n\
t touched\n\
T t+c\n\
e t+c perc\n\
-r, --reverse reverse order sort\n\
-o, --output=FILE output into a file\n\
-L, --limit=NR output limit mask 77 - 00\n");
fprintf(out, "\
-v, --version version information\n\
-h, --help this screen\n\
\n\
Report bugs to <%s>\n\
Homepage: %s\n", PACKAGE_BUGREPORT, PACKAGE_URL);
fprintf(out, "Usage: %s [OPTIONS]\n", program_name);
fputs( "\n", out);
fputs( "This is ISC dhcpd pools usage analyzer.\n", out);
fputs( "\n", out);
fputs( " -c, --config=FILE path to the dhcpd.conf file\n", out);
fputs( " -l, --leases=FILE path to the dhcpd.leases file\n", out);
fputs( " -f, --format=[thHcxXjJ] output format\n", out);
fputs( " t for text\n", out);
fputs( " H for full html page\n", out);
fputs( " x for xml\n", out);
fputs( " X for xml with active lease details\n", out);
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);
fputs( " m maximum\n", out);
fputs( " c current\n", out);
fputs( " p percent\n", out);
fputs( " t touched\n", out);
fputs( " T t+c\n", out);
fputs( " e t+c perc\n", out);
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( " --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);
fprintf(out, "Report bugs to <%s>\n", PACKAGE_BUGREPORT);
fprintf(out, "Homepage: %s\n", PACKAGE_URL);
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
exit(status);
}

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
* BSD License" or "FreeBSD License".
*
* Copyright 2006- Sami Kerola. All rights reserved.
* Copyright 2012 Cheer Xiao.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -33,186 +34,293 @@
* official policies, either expressed or implied, of Sami Kerola.
*/
/*! \file sort.c
* \brief Functions to sort output.
*/
#include <config.h>
#include <err.h>
#include <errno.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "progname.h"
#include "quote.h"
#include "xalloc.h"
#include "dhcpd-pools.h"
/* Sort functions for range sorting */
int intcomp(const void *restrict x, const void *restrict y)
/*! \brief Compare IP address, with IPv4/v6 determination.
* \param a Binary IP address.
* \param b Binary IP address.
* \return If a < b return -1, if a < b return 1, when they are equal return 0.
*/
int ipcomp_init(const union ipaddr_t *restrict a __attribute__ ((unused)),
const union ipaddr_t *restrict b __attribute__ ((unused)))
{
if (*(uint32_t *) x < *(uint32_t *) y)
return -1;
else if (*(uint32_t *) y < *(uint32_t *) x)
return 1;
else
return 0;
return 0;
}
int ipcomp_v4(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b)
{
if (a->v4 < b->v4)
return -1;
if (a->v4 > b->v4)
return 1;
return 0;
}
int ipcomp_v6(const union ipaddr_t *restrict a, const union ipaddr_t *restrict b)
{
return memcmp(&a->v6, &b->v6, sizeof(a->v6));
}
/*! \brief Compare IP address in leases_t structure, with IPv4/v6 determination.
* \param a Binary IP address.
* \param b Binary IP address.
* \return If a < b return -1, if a < b return 1, when they are equal return 0.
*/
int leasecomp_init(const struct leases_t *restrict a __attribute__ ((unused)),
const struct leases_t *restrict b __attribute__ ((unused)))
{
return 0;
}
int leasecomp_v4(const struct leases_t *restrict a, const struct leases_t *restrict b)
{
if (a->ip.v4 < b->ip.v4)
return -1;
if (a->ip.v4 > b->ip.v4)
return 1;
return 0;
}
int leasecomp_v6(const struct leases_t *restrict a, const struct leases_t *restrict b)
{
return memcmp(&a->ip.v6, &b->ip.v6, sizeof(a->ip.v6));
}
/*! \brief Compare IP address in leases. Suitable for sorting range table.
* \param r1 A range structure.
* \param r2 A range structure.
* \return Return pas through from ipcomp.
*/
int rangecomp(const void *restrict r1, const void *restrict r2)
{
if ((((struct range_t *)r1)->first_ip) <
(((struct range_t *)r2)->first_ip))
return -1;
else if ((((struct range_t *)r2)->first_ip) <
(((struct range_t *)r1)->first_ip))
return 1;
else
return 0;
return ipcomp(&((const struct range_t *)r1)->first_ip,
&((const struct range_t *)r2)->first_ip);
}
unsigned long int ret_ip(struct range_t r)
/*! \brief Compare two doubles.
* \param f1,f2 Data to compare.
* \return Like strcmp.
*/
int comp_double(double f1, double f2)
{
return (r.first_ip);
if (isless(f1, f2))
return -1;
else if (isless(f2, f1))
return 1;
return 0;
}
unsigned long int ret_cur(struct range_t r)
/*! \brief Compare two range_t by their first_ip.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_ip(struct range_t *r1, struct range_t *r2)
{
return (r.count);
return ipcomp(&r1->first_ip, &r2->first_ip);
}
unsigned long int ret_max(struct range_t r)
/*! \brief Compare two range_t by their capacity.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_max(struct range_t *r1, struct range_t *r2)
{
return (r.last_ip - r.first_ip);
return comp_double(get_range_size(r1), get_range_size(r2));
}
unsigned long int ret_percent(struct range_t r)
/*! \brief Compare two range_t by their current usage.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_cur(struct range_t *r1, struct range_t *r2)
{
float f;
f = (float)r.count / (r.last_ip - r.first_ip - 1);
return ((unsigned long int)(f * 100000));
return comp_double(r1->count, r2->count);
}
unsigned long int ret_touched(struct range_t r)
/*! \brief Compare two range_t by their current usage percentage.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_percent(struct range_t *r1, struct range_t *r2)
{
return (r.touched);
return comp_double(ret_percent(*r1), ret_percent(*r2));
}
unsigned long int ret_tc(struct range_t r)
/*! \brief Compare two range_t by their touched addresses.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_touched(struct range_t *r1, struct range_t *r2)
{
return comp_double(r1->touched, r2->touched);
}
/*! \brief Compare two range_t by their touched and in use addresses.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_tc(struct range_t *r1, struct range_t *r2)
{
return comp_double(ret_tc(*r1), ret_tc(*r2));
}
/*! \brief Compare two range_t by their touched and in use percentage.
* \param r1,r2 Pointers to data to compare.
* \return Like strcmp.
*/
int comp_tcperc(struct range_t *r1, struct range_t *r2)
{
return comp_double(ret_tcperc(*r1), ret_tcperc(*r2));
}
/*! \brief Percentage in use in range.
* \param r A range structure.
* \return Usage percentage of the given range.
*/
double ret_percent(struct range_t r)
{
return r.count / get_range_size(&r);
}
/*! \brief Touched and in use in range
* \param r A range structure.
* \return Number of touched or in use addresses in the given range.
*/
double ret_tc(struct range_t r)
{
return (r.count + r.touched);
}
unsigned long int ret_tcperc(struct range_t r)
/*! \brief Return percentage of addresses touched and in use in range.
* \param r A range structure.
* \return Percentage of touched or in use addresses in the given range.
*/
double ret_tcperc(struct range_t r)
{
float f;
f = (float)(r.count + r.touched) / (r.last_ip - r.first_ip - 1);
return ((unsigned long int)(f * 10000));
return ret_tc(r) / get_range_size(&r);
}
void field_selector(char c)
/*! \brief Sort field selector.
* \param c Symbolic name of a sort by character.
* The sort algorithms are stabile, which means multiple sorts can be
* specified and they do not mess the result of previous sort. The sort
* algorithms are used via function pointer, that gets to be reassigned.
* \return Return the selected compare function.
*/
comparer_t field_selector(char c)
{
switch (c) {
case 'n':
break;
return NULL;
case 'i':
returner = ret_ip;
break;
return comp_ip;
case 'm':
returner = ret_max;
break;
return comp_max;
case 'c':
returner = ret_cur;
break;
return comp_cur;
case 'p':
returner = ret_percent;
break;
return comp_percent;
case 't':
returner = ret_touched;
break;
return comp_touched;
case 'T':
returner = ret_tc;
break;
return comp_tc;
case 'e':
returner = ret_tcperc;
break;
return comp_tcperc;
default:
warnx("field_selector: unknown sort order `%c'", c);
errx(EXIT_FAILURE, "Try `%s --help' for more information.",
program_invocation_short_name);
{
char str[2] = { c, '\0' };
error(EXIT_FAILURE, 0, "field_selector: unknown sort order: %s",
quote(str));
}
}
return NULL;
}
/* Needed to support multiple key sorting. */
int get_order(struct range_t *restrict left, struct range_t *restrict right)
/*! \brief Perform requested sorting.
* \param left The left side of the merge sort.
* \param right The right side of the merge sort.
* \return Relevant for merge sort decision.
*/
static int merge(struct conf_t *state, struct range_t *restrict left, struct range_t *restrict right)
{
int i, len, ret;
unsigned long int lint, rint;
struct output_sort *p;
int ret;
len = strlen(config.sort);
for (i = 0; i < len; i++) {
/* Handling strings is case of it's own */
if (config.sort[i] == 'n') {
ret =
strcmp(left->shared_net->name,
right->shared_net->name);
if (0 < ret) {
return (0);
} else if (ret < 0) {
return (1);
} else {
continue;
}
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);
} else {
/* Range sorts are common. */
ret = p->func(left, right);
}
/* Select which function is pointed by returner */
field_selector(config.sort[i]);
lint = returner(*left);
rint = returner(*right);
/* If fields are equal use next sort method */
if (lint == rint) {
continue;
}
if (lint < rint) {
if (0 < ret)
return (0);
if (ret < 0)
return (1);
}
return (0);
}
/* If all returners where equal */
/* this is reached if nothing was sorted */
return (0);
}
void mergesort_ranges(struct range_t *restrict orig, int size, struct range_t *restrict temp)
/*! \brief Mergesort for range table.
*/
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 (get_order((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 (get_order((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++;
}
@ -221,11 +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);
}

59
tests/Makemodule.am Normal file
View file

@ -0,0 +1,59 @@
TESTS = \
tests/alarm-count-option \
tests/alarm-critical \
tests/alarm-critical-ranges \
tests/alarm-critical-snets \
tests/alarm-ignore \
tests/alarm-ok \
tests/alarm-shared-ok \
tests/alarm-warning \
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/statuses \
tests/v6 \
tests/v6-perfdata
if ENABLE_MUSTACH
TESTS += \
tests/mustach
endif
EXTRA_DIST += \
tests/confs \
tests/expected \
tests/leases \
tests/test.sh \
$(TESTS)
TESTS_ENVIRONMENT = top_srcdir=$(top_srcdir) PATH=$(top_builddir)$(PATH_SEPARATOR)$$PATH
check-local: $(SHELL) $(top_srcdir)/tests/test.sh
clean-local-tests:
rm -rf $(top_builddir)/tests/outputs
CLEAN_LOCALS += clean-local-tests

44
tests/alarm-count-option Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
#
# Alarm warning both ranges and shared networks.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
echo '== warn count ==' > tests/outputs/$IAM
dhcpd-pools --config $top_srcdir/tests/confs/complete --leases $top_srcdir/tests/leases/complete \
--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 \
--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 \
--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 \
--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
rm -f tests/outputs/$IAM-too
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-critical Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm critical both ranges & shared nets.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools --critical=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-critical-ranges Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm critical ranges only.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -L 11 --critical=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-critical-snets Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm critical shared networks only.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -L 22 --critical=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

15
tests/alarm-ignore 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 --warning 1 --critical 101 --min 2 \
-c $top_srcdir/tests/confs/one-ip \
-l $top_srcdir/tests/leases/one-ip -o tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-ok Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm warning both ranges and shared networks.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools --critical=100 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-shared-ok Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Shared network should be OK, and critical range ignored.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -L 66 --critical=54 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-warning Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm warning both ranges and shared networks.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools --warning=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-warning-ranges Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm warning ranges only.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -L 11 --warning=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

16
tests/alarm-warning-snets Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# Alarm warning shared networks only.
IAM=$(basename $0)
if [ ! -d tests/outputs ]; then
mkdir tests/outputs
fi
dhcpd-pools -L 22 --warning=50 -c $top_srcdir/tests/confs/complete \
-l $top_srcdir/tests/leases/complete -o tests/outputs/$IAM
echo $? >> tests/outputs/$IAM
diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM
exit $?

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/bootp Symbolic link
View file

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

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

1
tests/complete 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

5
tests/confs/bootp Normal file
View file

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

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;
}

31
tests/confs/complete 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;
}
}

1
tests/confs/formats Symbolic link
View file

@ -0,0 +1 @@
complete

5
tests/confs/leading0 Normal file
View file

@ -0,0 +1,5 @@
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
range dynamic-bootp 10.0.0.001 10.0.0.010;
}
}

1
tests/confs/one-ip Normal file
View file

@ -0,0 +1 @@
range 10.20.30.40;

1
tests/confs/one-line Normal file
View file

@ -0,0 +1 @@
pool {range 10.0.0.1 10.0.0.5;range 10.0.0.6 10.0.0.10;}

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;
}

1
tests/confs/same-twice Symbolic link
View file

@ -0,0 +1 @@
simple

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

5
tests/confs/simple Normal file
View file

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

1
tests/confs/statuses Symbolic link
View file

@ -0,0 +1 @@
complete

10
tests/confs/v6 Normal file
View file

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

1
tests/empty Symbolic link
View file

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

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