Skip to content

Commit

Permalink
Merge pull request #389 from ArnoStiefvater/smooth-progress-icmp
Browse files Browse the repository at this point in the history
Smooth progress icmp
  • Loading branch information
ArnoStiefvater authored Aug 26, 2020
2 parents b5c8eec + aa704c3 commit 97892cc
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 25 deletions.
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

0 comments on commit 97892cc

Please sign in to comment.