Skip to content

Commit

Permalink
Merge pull request #2520 from jimklimov/issue-2511
Browse files Browse the repository at this point in the history
Teach `nut-scanner` to parallelize scans across many IP address ranges
  • Loading branch information
jimklimov authored Jul 9, 2024
2 parents 4a71a9b + 808e3d3 commit 3bfdb74
Show file tree
Hide file tree
Showing 23 changed files with 1,233 additions and 376 deletions.
5 changes: 4 additions & 1 deletion NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ installed.
with the same call, by repeating command-line options; also `-m auto{,4,6}`
can be specified (once) to select IP (all, IPv4, IPv6) address ranges of
configured local network interfaces (currently not implemented for WIN32).
[issue #2244, PR #2509, PR #2513]
An `/ADDRLEN` suffix can be added to the option, to filter out discovered
subnets with too many bits available for the host address part (avoiding
millions of scans in the extreme cases).
[issue #2244, issue #2511, PR #2509, PR #2513, PR #2517]
* bumped version of `libnutscan` to 2.5.2, it now includes a few more
methods and symbols from `libcommon`. [issue #2244, PR #2509]
Expand Down
56 changes: 55 additions & 1 deletion docs/man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ SRC_DEV_PAGES = \
nutscan_display_ups_conf_with_sanity_check.txt \
nutscan_display_ups_conf.txt \
nutscan_display_parsable.txt \
nutscan_init_ip_ranges.txt \
nutscan_free_ip_ranges.txt \
nutscan_stringify_ip_ranges.txt \
nutscan_add_ip_range.txt \
nutscan_ip_ranges_iter_init.txt \
nutscan_ip_ranges_iter_inc.txt \
nutscan_cidr_to_ip.txt \
nutscan_new_device.txt \
nutscan_free_device.txt \
Expand Down Expand Up @@ -316,6 +322,12 @@ MAN3_DEV_PAGES = \
nutscan_display_ups_conf_with_sanity_check.3 \
nutscan_display_ups_conf.3 \
nutscan_display_parsable.3 \
nutscan_init_ip_ranges.3 \
nutscan_free_ip_ranges.3 \
nutscan_stringify_ip_ranges.3 \
nutscan_add_ip_range.3 \
nutscan_ip_ranges_iter_init.3 \
nutscan_ip_ranges_iter_inc.3 \
nutscan_cidr_to_ip.3 \
nutscan_new_device.3 \
nutscan_free_device.3 \
Expand All @@ -325,13 +337,25 @@ MAN3_DEV_PAGES = \
nutscan_get_serial_ports_list.3 \
nutscan_init.3

# Alias page for one text describing two commands:
upscli_readline_timeout.3: upscli_readline.3
touch $@

upscli_sendline_timeout.3: upscli_sendline.3
touch $@

# Alias page for one text describing two commands:
nutscan_scan_ip_range_snmp.3: nutscan_scan_snmp.3
touch $@

nutscan_scan_ip_range_xml_http.3: nutscan_scan_xml_http_range.3
touch $@

nutscan_scan_ip_range_nut.3: nutscan_scan_nut.3
touch $@

nutscan_scan_ip_range_ipmi.3: nutscan_scan_ipmi.3
touch $@

nutscan_add_commented_option_to_device.3: nutscan_add_option_to_device.3
touch $@

Expand Down Expand Up @@ -391,6 +415,12 @@ HTML_DEV_MANS = \
nutscan_display_ups_conf_with_sanity_check.html \
nutscan_display_ups_conf.html \
nutscan_display_parsable.html \
nutscan_init_ip_ranges.html \
nutscan_free_ip_ranges.html \
nutscan_stringify_ip_ranges.html \
nutscan_add_ip_range.html \
nutscan_ip_ranges_iter_init.html \
nutscan_ip_ranges_iter_inc.html \
nutscan_cidr_to_ip.html \
nutscan_new_device.html \
nutscan_free_device.html \
Expand All @@ -405,8 +435,32 @@ HTML_DEV_MANS = \
# Can't make this work on all make implementations at once, so disabled for now
# Anyway it would be the same man-like page for several functions
HTML_DEV_MANS_FICTION = \
upscli_readline_timeout.html \
upscli_sendline_timeout.html \
nutscan_scan_ip_range_snmp.html \
nutscan_scan_ip_range_xml_http.html \
nutscan_scan_ip_range_nut.html \
nutscan_scan_ip_range_ipmi.html \
nutscan_add_commented_option_to_device.html

upscli_readline_timeout.html: upscli_readline.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

upscli_sendline_timeout.html: upscli_sendline.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

nutscan_scan_ip_range_snmp.html: nutscan_scan_snmp.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

nutscan_scan_ip_range_xml_http.html: nutscan_scan_xml_http_range.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

nutscan_scan_ip_range_nut.html: nutscan_scan_nut.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

nutscan_scan_ip_range_ipmi.html: nutscan_scan_ipmi.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

nutscan_add_commented_option_to_device.html: nutscan_add_option_to_device.html
test -n "$?" -a -s "$@" && rm -f $@ && ln -s $? $@

Expand Down
13 changes: 13 additions & 0 deletions docs/man/nut-scanner.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ Also note that some buses require IP address(es) to scan, and others have a
different behavior when exactly no addresses are specified (it is not currently
possible to mix the two behaviors in one invocation of the `nut-scanner` tool).
+
A single-address range may be a host name which would be resolved into one IP
address by the system resolver. A CIDR using a host name and netmask length
would be resolved into an IP address and subjected to the mask application,
to query hosts "near" the named one.
+
Finally note that currently even if multi-threaded support is available, each
range specification is a separate fan-out of queries constrained by the timeout.
Requests to scan many single IP addresses will take a while to complete, much
Expand All @@ -151,6 +156,14 @@ A special form `-m auto` allows `nut-scanner` to detect local IP address(es)
and scan corresponding subnet(s) on supported platforms, and `-m auto4` or
`-m auto6` limits the selected addresses to IPv4 and IPv6 respectively. Only
the first "auto*" request would be honoured, others ignored with a warning.
+
An `/ADDRLEN` suffix can be added to the option, to filter out discovered
subnets with too many bits available for the host address part (avoiding
millions of scans in the extreme cases). For example, if your IPv4 LAN's
network range is `10.2.3.0/24`, its address part is `(32-24)=8`. Note that
while this is applied to IPv6 networks also, their typical `/64` subnets
are not likely to have a NUT/SNMP/NetXML/... server *that* close nearby
(in addressing terms), for a tight filter to find them. Default is `8`.

NUT DEVICE OPTION
-----------------
Expand Down
3 changes: 3 additions & 0 deletions docs/man/nutscan.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ linkman:nutscan_display_parsable[3], linkman:nutscan_display_ups_conf[3],
linkman:nutscan_new_device[3], linkman:nutscan_free_device[3],
linkman:nutscan_add_device_to_device[3],
linkman:nutscan_add_option_to_device[3],
linkman:nutscan_init_ip_ranges[3],
linkman:nutscan_free_ip_ranges[3],
linkman:nutscan_add_ip_range[3],
linkman:nutscan_cidr_to_ip[3]

Internet resources:
Expand Down
77 changes: 77 additions & 0 deletions docs/man/nutscan_add_ip_range.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
NUTSCAN_ADD_IP_RANGE(3)
=======================

NAME
----

nutscan_add_ip_range - Add an entry with IP address range (starting
and ending addresses) to a `nutscan_ip_range_list_t` structure.

SYNOPSIS
--------

#include <nut-scan.h>

/* One IP address range: */
typedef struct nutscan_ip_range_s {
char * start_ip;
char * end_ip;
struct nutscan_ip_range_s * next;
} nutscan_ip_range_t;

/* List of IP address ranges and helper data: */
typedef struct nutscan_ip_range_list_s {
nutscan_ip_range_t * ip_ranges; /* Actual linked list of entries, first entry */
nutscan_ip_range_t * ip_ranges_last; /* Pointer to end of list for quicker additions */
size_t ip_ranges_count; /* Counter of added entries */
} nutscan_ip_range_list_t;


size_t nutscan_add_ip_range(
nutscan_ip_range_list_t *irl,
char * start_ip,
char * end_ip);

DESCRIPTION
-----------

The *nutscan_add_ip_range()* function can create and add a `nutscan_ip_range_t`
entry based on provided inputs to the specified `nutscan_ip_range_list_t`
structure. The resulting amount of entries in the structure is returned,
or 0 in case of non-fatal errors.

This function skips work if:

* the structure pointer is `NULL` (0 is returned);
* neither `start_ip` nor `end_ip` were provided, i.e. they have `NULL` values
(current list length from the structure is returned);
* failed to allocate the entry (fatal).

If only one of `start_ip` or `end_ip` values was provided (not `NULL`), a
single-address range is created with both addresses set to the same pointer
value.

The structure should be initialized before use by `nutscan_init_ip_ranges()`.

The caller must free the contents of the structure after completing its use
by calling `nutscan_free_ip_ranges()` (after which the structure can be
re-used for a new list), and explicitly `free()` the structure object itself if
it was allocated dynamically (e.g. by calling `nutscan_init_ip_ranges(NULL)`).

NOTES
-----

Technically, the function is currently defined in 'nutscan-ip.h' file.

Currently there are no checks for duplicate or overlapping entries, so the
same IP addresses and whole IP address ranges can be added to the list (and
would eventually be scanned) many times.

SEE ALSO
--------

linkman:nutscan_init_ip_ranges[3], linkman:nutscan_free_ip_ranges[3],
linkman:nutscan_stringify_ip_ranges[3],
linkman:nutscan_cidr_to_ip[3],
linkman:nutscan_ip_ranges_iter_init[3],
linkman:nutscan_ip_ranges_iter_inc[3]
43 changes: 43 additions & 0 deletions docs/man/nutscan_free_ip_ranges.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
NUTSCAN_FREE_IP_RANGES(3)
=========================

NAME
----

nutscan_free_ip_ranges - Free contents of a `nutscan_ip_range_list_t`
structure populated (and optionally created) by `nutscan_init_ip_ranges()`
and, more importantly, filled by a series of `nutscan_add_ip_range()` calls.

SYNOPSIS
--------

#include <nut-scan.h>

void nutscan_free_ip_ranges(nutscan_ip_range_list_t *irl);

DESCRIPTION
-----------

The *nutscan_free_ip_ranges()* function can free a `nutscan_ip_range_list_t`
structure. Doing so, it frees the whole linked list of `nutscan_ip_range_t`
entries, and zeroes out helper properties.

The structure itself is not freed (as it can be a statically allocated
variable on the stack), and can be re-used for a new list if needed.

The caller must free the structure object if it was allocated dynamically
(e.g. by calling `nutscan_init_ip_ranges(NULL)`).

NOTES
-----

Technically, the function is currently defined in 'nutscan-ip.h' file.

SEE ALSO
--------

linkman:nutscan_init_ip_ranges[3], linkman:nutscan_add_ip_range[3],
linkman:nutscan_stringify_ip_ranges[3],
linkman:nutscan_cidr_to_ip[3],
linkman:nutscan_ip_ranges_iter_init[3],
linkman:nutscan_ip_ranges_iter_inc[3]
44 changes: 44 additions & 0 deletions docs/man/nutscan_init_ip_ranges.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
NUTSCAN_INIT_IP_RANGES(3)
=========================

NAME
----

nutscan_init_ip_ranges - Initialize contents of a `nutscan_ip_range_list_t`
structure (and optionally create one in the first place).

SYNOPSIS
--------

#include <nut-scan.h>

nutscan_ip_range_list_t * nutscan_init_ip_ranges(nutscan_ip_range_list_t *irl);

DESCRIPTION
-----------

The *nutscan_init_ip_ranges()* function can prepare a `nutscan_ip_range_list_t`
structure by zeroing out its fields. If the argument is `NULL`, the structure
is dynamically allocated. Either way, a pointer to it is returned.

A structure passed by caller is not assumed to have any valid contents to free,
as it may have garbage from stack after allocation.

The caller must free the contents of the structure after completing its use
by calling `nutscan_free_ip_ranges` (after which the structure can be re-used),
and explicitly `free()` the structure object itself if it was allocated
dynamically (e.g. by calling `nutscan_init_ip_ranges(NULL)`).

NOTES
-----

Technically, the function is currently defined in 'nutscan-ip.h' file.

SEE ALSO
--------

linkman:nutscan_free_ip_ranges[3], linkman:nutscan_add_ip_range[3],
linkman:nutscan_stringify_ip_ranges[3],
linkman:nutscan_cidr_to_ip[3],
linkman:nutscan_ip_ranges_iter_init[3],
linkman:nutscan_ip_ranges_iter_inc[3]
44 changes: 44 additions & 0 deletions docs/man/nutscan_ip_ranges_iter_inc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
NUTSCAN_IP_RANGES_ITER_INC(3)
=============================

NAME
----

nutscan_ip_ranges_iter_inc - Proceed with iteration of an IP address range
using a `nutscan_ip_range_list_iter_t` structure.

SYNOPSIS
--------

#include <nut-scan.h>

char * nutscan_ip_ranges_iter_inc(nutscan_ip_range_list_iter_t *irliter);

DESCRIPTION
-----------

The *nutscan_ip_ranges_iter_inc()* function can prepare an iterator from
the specified `nutscan_ip_range_list_t` structure.

This function skips work if:

* the structure pointer is `NULL` (`NULL` is returned);
* the structure pointer's `ip_range` list is `NULL` (`NULL` is returned),
* the structure pointer's `ip_range_iter` pointer is `NULL` (`NULL` is
returned).

Returns the next IP address from the currently iterated registered IP
address range, or switches iteration to the next range if no addresses
remained in the current one.

NOTES
-----

Technically, the function is currently defined in 'nutscan-ip.h' file.

SEE ALSO
--------

linkman:nutscan_init_ip_ranges[3], linkman:nutscan_free_ip_ranges[3],
linkman:nutscan_cidr_to_ip[3],
linkman:nutscan_ip_ranges_iter_init[3]
Loading

0 comments on commit 3bfdb74

Please sign in to comment.