Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth progress icmp #389

Merged
merged 5 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Changed
- Add separators for a new (ip address) field in ERRMSG and DEADHOST messages. [#376](https://github.com/greenbone/gvm-libs/pull/376)
- Continuously send dead hosts to ospd-openvas to enable a smooth progess bar if only ICMP is chosen as alive test. [#389](https://github.com/greenbone/gvm-libs/pull/389)

### Removed
- Remove version from the nvticache name. [#386](https://github.com/greenbone/gvm-libs/pull/386)
Expand Down
134 changes: 123 additions & 11 deletions boreas/alivedetection.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ scan (alive_test_t alive_test)
struct timeval start_time, end_time;
int scandb_id;
gchar *scan_id;
/* Following variables are only relevant if only ICMP was chosen. */
int remaining_batch;
int prev_alive;
gboolean limit_reached_handled = FALSE; /* Scan restrictions related. */

gettimeofday (&start_time, NULL);
number_of_targets = g_hash_table_size (scanner.hosts_data->targethosts);
Expand All @@ -89,7 +93,82 @@ scan (alive_test_t alive_test)
sniffer_thread_id = 0;
start_sniffer_thread (&scanner, &sniffer_thread_id);

if (alive_test & ALIVE_TEST_ICMP)
/* Continuously send dead hosts to ospd if only ICMP was chosen instead of
* sending all at once at the end. This is done for displaying a progressbar
* that increases gradually. */
if (alive_test == ALIVE_TEST_ICMP)
{
g_hash_table_iter_init (&target_hosts_iter,
scanner.hosts_data->targethosts);
int batch = 1000;
int curr_alive = 0;
prev_alive = 0;
/* Number of hosts in last batch. Depending on the total number of hosts
* the last batch size maybe be double the normal size. Info about the
* last batch is send after all hosts were checked and we waited for last
* packets to arrive.*/
remaining_batch = number_of_targets;
for (int packets_send = 0;
g_hash_table_iter_next (&target_hosts_iter, &key, &value);)
{
send_icmp (key, value, &scanner);
packets_send++;
/* Send dead hosts update after batch number of packets were send and
* we still have more than batch size packets remaining. */
if (packets_send % batch == 0
&& (number_of_targets - packets_send) > batch)
{
/* The number of dead hosts we have to send to ospd is the batch
* size minus the newly found alive hosts. The newly found alive
* hosts is the diff between the current total of alive hosts and
* the total of the last batch. */
curr_alive = g_hash_table_size (scanner.hosts_data->alivehosts);
number_of_dead_hosts = batch - (curr_alive - prev_alive);

/* If the max_scan_hosts limit was reached we can not tell ospd
* the true number of dead hosts. The number of alive hosts which
* are above the max_scan_hosts limit are not to be substracted
* form the dead hosts to send. They are considered as dead hosts
* for the progress bar.*/
if (scanner.scan_restrictions->max_scan_hosts_reached)
{
/* Handle the case where we reach the max_scan_hosts for the
* first time. We may have to considere some of the new alive
* hosts as dead because of the restriction. E.g
* curr_alive=110 prev_alive=90 max_scan_hosts=100 batch=100.
* Normally we would send 80 as dead in this batch (20 new
* alive hosts) but because of the restriction we send 90 as
* dead. The 10 hosts which are over the limit are considered
* as dead.
* After this limit case was handled we just always send the
* complete batch as dead hosts.*/
if (!limit_reached_handled)
{
/* Number of alive hosts until limit was reached. */
int last_hosts_considered_as_alive =
scanner.scan_restrictions->max_scan_hosts - prev_alive;
number_of_dead_hosts =
batch - last_hosts_considered_as_alive;
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
remaining_batch -= batch;
limit_reached_handled = TRUE;
}
else
{
send_dead_hosts_to_ospd_openvas (batch);
remaining_batch -= batch;
}
}
else
{
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
remaining_batch -= batch;
}
prev_alive = curr_alive;
}
}
}
else if (alive_test & ALIVE_TEST_ICMP)
{
g_debug ("%s: ICMP Ping", __func__);
g_hash_table_foreach (scanner.hosts_data->targethosts, send_icmp,
Expand Down Expand Up @@ -137,26 +216,59 @@ scan (alive_test_t alive_test)

stop_sniffer_thread (&scanner, sniffer_thread_id);

number_of_dead_hosts = count_difference (scanner.hosts_data->targethosts,
scanner.hosts_data->alivehosts);

/* Send number of dead hosts to ospd-openvas. We need to consider the scan
* restrictions.*/
if (scanner.scan_restrictions->max_scan_hosts_reached)
/* If only ICMP was specified we continously sent updates about dead hosts to
* ospd while checking the hosts. We now only have to send the dead hosts of
* the last batch. This is done here to catch the last alive hosts which may
* have arrived after all packets were already sent.
* Else send total number of dead host at once.*/
if (alive_test == ALIVE_TEST_ICMP)
{
send_dead_hosts_to_ospd_openvas (
number_of_targets - scanner.scan_restrictions->max_scan_hosts);
if (scanner.scan_restrictions->max_scan_hosts_reached)
{
/* We reached the max_scan_host limit in the last batch. For detailed
* description look at the first time where limit_reached_handled is
* used.*/
if (!limit_reached_handled)
{
/* Number of alive hosts until limit was reached. */
int last_hosts_considered_as_alive =
scanner.scan_restrictions->max_scan_hosts - prev_alive;
number_of_dead_hosts =
remaining_batch - last_hosts_considered_as_alive;
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
}
else
{
send_dead_hosts_to_ospd_openvas (remaining_batch);
}
}
else
{
int curr_alive = g_hash_table_size (scanner.hosts_data->alivehosts);
number_of_dead_hosts = remaining_batch - (curr_alive - prev_alive);
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
}
}
else
{
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
number_of_dead_hosts =
number_of_targets - g_hash_table_size (scanner.hosts_data->alivehosts);

/* Send number of dead hosts to ospd-openvas. We need to consider the scan
* restrictions.*/
if (scanner.scan_restrictions->max_scan_hosts_reached)
send_dead_hosts_to_ospd_openvas (
number_of_targets - scanner.scan_restrictions->max_scan_hosts);
else
send_dead_hosts_to_ospd_openvas (number_of_dead_hosts);
}

gettimeofday (&end_time, NULL);

g_message ("Alive scan %s finished in %ld seconds: %d alive hosts of %d.",
scan_id, end_time.tv_sec - start_time.tv_sec,
number_of_targets - number_of_dead_hosts, number_of_targets);
g_hash_table_size (scanner.hosts_data->alivehosts),
number_of_targets);
g_free (scan_id);

return 0;
Expand Down
3 changes: 1 addition & 2 deletions boreas/alivedetection.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ struct scanner
struct hosts_data
{
/* Set of the form (ip_str, ip_str).
* Hosts which passed our pcap filter. May include hosts which are alive but
* are not in the targethosts list */
* Target hosts which were detected as alive. */
GHashTable *alivehosts;
/* Hashtable of the form (ip_str, gvm_host_t *). The gvm_host_t pointers point
* to hosts which are to be freed by the caller of start_alive_detection(). */
Expand Down
27 changes: 15 additions & 12 deletions boreas/sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,11 @@ got_packet (u_char *user_data,
"%s: Failed to transform IPv4 address into string representation: %s",
__func__, strerror (errno));

/* Do not put already found host on Queue and only put hosts on Queue we
* are searching for. */
if (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))
&& g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
/* Only put unique hosts on queue and in hash table. Use short circuit
* evaluation to not add hosts to the hash table which are not in our
* target list.*/
if ((g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
&& (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))
{
/* handle max_scan_hosts related restrictions. */
handle_scan_restrictions (scanner, addr_str);
Expand All @@ -174,10 +175,11 @@ got_packet (u_char *user_data,
g_debug ("%s: Failed to transform IPv6 into string representation: %s",
__func__, strerror (errno));

/* Do not put already found host on Queue and only put hosts on Queue we
* are searching for. */
if (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))
&& g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
/* Only put unique hosts on queue and in hash table. Use short circuit
* evaluation to not add hosts to the hash table which are not in our
* target list.*/
if ((g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
&& (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))
{
/* handle max_scan_hosts related restrictions. */
handle_scan_restrictions (scanner, addr_str);
Expand All @@ -201,10 +203,11 @@ got_packet (u_char *user_data,
g_debug ("%s: Failed to transform IP into string representation: %s",
__func__, strerror (errno));

/* Do not put already found host on Queue and only put hosts on Queue
we are searching for. */
if (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))
&& g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
/* Only put unique hosts on queue and in hash table. Use short circuit
* evaluation to not add hosts to the hash table which are not in our
* target list.*/
if ((g_hash_table_contains (hosts_data->targethosts, addr_str) == TRUE)
&& (g_hash_table_add (hosts_data->alivehosts, g_strdup (addr_str))))
{
/* handle max_scan_hosts related restrictions. */
handle_scan_restrictions (scanner, addr_str);
Expand Down