diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d6ce2743..341faa44b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [9.0.1] (unreleased)
### Added
+- Add option --optimize migrate-relay-sensors [#827](https://github.com/greenbone/gvmd/pull/827)
### Changed
- Extend command line options for managing scanners [#815](https://github.com/greenbone/gvmd/pull/815)
diff --git a/INSTALL.md b/INSTALL.md
index ae4e8703d..5654708e1 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -419,6 +419,13 @@ supported values for `` are:
older versions, so this function can be used to correct missing severity
scores in older reports.
+- `migrate-relay-sensors`
+
+ If relays are active, this can be used to make sure all sensor type
+ scanners have a matching relay, i.e. OSP sensors have an OSP relay
+ and GMP scanners have a GMP relay.
+ GMP scanners are migrated to OSP sensors if an OSP relay is available.
+
- `rebuild-report-cache`
This clears the cache containing the unfiltered result counts of all reports
diff --git a/doc/gvmd.8 b/doc/gvmd.8
index b8383a974..d4329f36c 100644
--- a/doc/gvmd.8
+++ b/doc/gvmd.8
@@ -110,7 +110,7 @@ Modify user's password and exit.
Modify user's password and exit.
.TP
\fB--optimize=\fINAME\fB\f1
-Run an optimization: vacuum, analyze, cleanup-config-prefs, cleanup-port-names, cleanup-report-formats, cleanup-result-severities, cleanup-schedule-times, rebuild-report-cache or update-report-cache.
+Run an optimization: vacuum, analyze, cleanup-config-prefs, cleanup-port-names, cleanup-report-formats, cleanup-result-severities, cleanup-schedule-times, migrate-relay-sensors, rebuild-report-cache or update-report-cache.
.TP
\fB--osp-vt-update=\fISCANNER-SOCKET\fB\f1
Unix socket for OSP NVT update. Defaults to the path of the 'OpenVAS Default' scanner if it is an absolute path.
diff --git a/doc/gvmd.8.xml b/doc/gvmd.8.xml
index 17c9aa89b..33f51df0c 100644
--- a/doc/gvmd.8.xml
+++ b/doc/gvmd.8.xml
@@ -253,7 +253,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Run an optimization: vacuum, analyze, cleanup-config-prefs,
cleanup-port-names, cleanup-report-formats,
cleanup-result-severities, cleanup-schedule-times,
- rebuild-report-cache or update-report-cache.
+ migrate-relay-sensors, rebuild-report-cache
+ or update-report-cache.
diff --git a/doc/gvmd.html b/doc/gvmd.html
index cccea7fca..844864c87 100644
--- a/doc/gvmd.html
+++ b/doc/gvmd.html
@@ -236,7 +236,8 @@ Options
Run an optimization: vacuum, analyze, cleanup-config-prefs,
cleanup-port-names, cleanup-report-formats,
cleanup-result-severities, cleanup-schedule-times,
- rebuild-report-cache or update-report-cache.
+ migrate-relay-sensors, rebuild-report-cache
+ or update-report-cache.
diff --git a/src/gvmd.c b/src/gvmd.c
index 4178acab5..56f7d0eff 100644
--- a/src/gvmd.c
+++ b/src/gvmd.c
@@ -1779,7 +1779,8 @@ gvmd (int argc, char** argv)
"Run an optimization: vacuum, analyze, cleanup-config-prefs,"
" cleanup-port-names, cleanup-report-formats,"
" cleanup-result-severities, cleanup-schedule-times,"
- " rebuild-report-cache or update-report-cache.",
+ " migrate-relay-sensors, rebuild-report-cache or"
+ " update-report-cache.",
"" },
{ "osp-vt-update", '\0', 0, G_OPTION_ARG_STRING,
&osp_vt_update,
diff --git a/src/manage.c b/src/manage.c
index a98a0c15d..e7c4066af 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -169,6 +169,11 @@ extern volatile int termination_signal;
*/
static gchar *relay_mapper_path = NULL;
+/**
+ * @brief Whether to migrate sensors if relays do not match.
+ */
+static int relay_migrate_sensors = 0;
+
/**
* @brief Number of minutes before overdue tasks timeout.
*/
@@ -4907,6 +4912,158 @@ set_relay_mapper_path (const char *new_path)
relay_mapper_path = new_path ? g_strdup (new_path) : NULL;
}
+/**
+ * @brief Gets whether to migrate sensors if relays do not match.
+ *
+ * @return Whether to migrate sensors if relays do not match.
+ */
+int
+get_relay_migrate_sensors ()
+{
+ return relay_migrate_sensors;
+}
+
+/**
+ * @brief Sets whether to migrate sensors if relays do not match.
+ *
+ * @param[in] new_value The new value.
+ */
+void
+set_relay_migrate_sensors (int new_value)
+{
+ relay_migrate_sensors = new_value;
+}
+
+/**
+ * @brief Gets the info about a scanner relay as an XML entity_t.
+ *
+ * @param[in] original_host The original hostname or IP address.
+ * @param[in] original_port The original port number.
+ * @param[in] protocol The protocol to look for, e.g. "GMP" or "OSP".
+ * @param[out] ret_entity Return location for the parsed XML.
+ *
+ * @return 0: success, -1 error.
+ */
+static int
+get_relay_info_entity (const char *original_host, int original_port,
+ const char *protocol, entity_t *ret_entity)
+{
+ gchar **cmd, *stdout_str, *stderr_str;
+ int ret, exit_code;
+ GError *err;
+ entity_t relay_entity;
+
+ if (ret_entity == NULL)
+ return -1;
+
+ *ret_entity = NULL;
+ stdout_str = NULL;
+ stderr_str = NULL;
+ ret = -1;
+ exit_code = -1;
+ err = NULL;
+
+ cmd = (gchar **) g_malloc (8 * sizeof (gchar *));
+ cmd[0] = g_strdup (relay_mapper_path);
+ cmd[1] = g_strdup ("--host");
+ cmd[2] = g_strdup (original_host);
+ cmd[3] = g_strdup ("--port");
+ cmd[4] = g_strdup_printf ("%d", original_port);
+ cmd[5] = g_strdup ("--protocol");
+ cmd[6] = g_strdup (protocol);
+ cmd[7] = NULL;
+
+ if (g_spawn_sync (NULL,
+ cmd,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ &stdout_str,
+ &stderr_str,
+ &exit_code,
+ &err) == FALSE)
+ {
+ g_warning ("%s: g_spawn_sync failed: %s",
+ __FUNCTION__, err ? err->message : "");
+ g_strfreev (cmd);
+ g_free (stdout_str);
+ g_free (stderr_str);
+ return -1;
+ }
+ else if (exit_code)
+ {
+ g_warning ("%s: mapper exited with code %d",
+ __FUNCTION__, exit_code);
+ g_message ("%s: mapper stderr:\n%s", __FUNCTION__, stderr_str);
+ g_debug ("%s: mapper stdout:\n%s", __FUNCTION__, stdout_str);
+ g_strfreev (cmd);
+ g_free (stdout_str);
+ g_free (stderr_str);
+ return -1;
+ }
+
+ relay_entity = NULL;
+ if (parse_entity (stdout_str, &relay_entity))
+ {
+ g_warning ("%s: failed to parse mapper output",
+ __FUNCTION__);
+ g_message ("%s: mapper stdout:\n%s", __FUNCTION__, stdout_str);
+ g_message ("%s: mapper stderr:\n%s", __FUNCTION__, stderr_str);
+ }
+ else
+ {
+ ret = 0;
+ *ret_entity = relay_entity;
+ }
+
+ g_strfreev (cmd);
+ g_free (stdout_str);
+ g_free (stderr_str);
+
+ return ret;
+}
+
+/**
+ * @brief Gets whether there is a relay supporting the scanner type.
+ *
+ * @param[in] original_host The original hostname or IP address.
+ * @param[in] original_port The original port number.
+ * @param[in] type The scanner type to check.
+ *
+ * @return Whether there is a relay supporting the scanner type.
+ */
+gboolean
+relay_supports_scanner_type (const char *original_host, int original_port,
+ scanner_type_t type)
+{
+ entity_t relay_entity = NULL;
+ const char *protocol;
+ gboolean ret = FALSE;
+
+ if (type == SCANNER_TYPE_GMP)
+ protocol = "GMP";
+ else if (type == SCANNER_TYPE_OSP_SENSOR)
+ protocol = "OSP";
+ else
+ return FALSE;
+
+ if (get_relay_info_entity (original_host, original_port,
+ protocol, &relay_entity) == 0)
+ {
+ entity_t host_entity;
+ host_entity = entity_child (relay_entity, "host");
+
+ if (host_entity
+ && strcmp (entity_text (host_entity), ""))
+ {
+ ret = TRUE;
+ }
+ }
+ free_entity (relay_entity);
+ return ret;
+}
+
/**
* @brief Gets a relay hostname and port for a sensor scanner.
*
@@ -4948,65 +5105,10 @@ slave_get_relay (const char *original_host,
}
else
{
- gchar **cmd, *stdout_str, *stderr_str;
- int exit_code;
- GError *err;
- entity_t relay_entity;
-
- stdout_str = NULL;
- stderr_str = NULL;
- exit_code = -1;
- err = NULL;
-
- cmd = (gchar **) g_malloc (8 * sizeof (gchar *));
- cmd[0] = g_strdup (relay_mapper_path);
- cmd[1] = g_strdup ("--host");
- cmd[2] = g_strdup (original_host);
- cmd[3] = g_strdup ("--port");
- cmd[4] = g_strdup_printf ("%d", original_port);
- cmd[5] = g_strdup ("--protocol");
- cmd[6] = g_strdup (protocol);
- cmd[7] = NULL;
-
- if (g_spawn_sync (NULL,
- cmd,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- &stdout_str,
- &stderr_str,
- &exit_code,
- &err) == FALSE)
- {
- g_warning ("%s: g_spawn_sync failed: %s",
- __FUNCTION__, err ? err->message : "");
- g_strfreev (cmd);
- g_free (stdout_str);
- g_free (stderr_str);
- return -1;
- }
- else if (exit_code)
- {
- g_warning ("%s: mapper exited with code %d",
- __FUNCTION__, exit_code);
- g_message ("%s: mapper stderr:\n%s", __FUNCTION__, stderr_str);
- g_debug ("%s: mapper stdout:\n%s", __FUNCTION__, stdout_str);
- g_strfreev (cmd);
- g_free (stdout_str);
- g_free (stderr_str);
- return -1;
- }
+ entity_t relay_entity = NULL;
- relay_entity = NULL;
- if (parse_entity (stdout_str, &relay_entity))
- {
- g_warning ("%s: failed to parse mapper output",
- __FUNCTION__);
- g_message ("%s: mapper stdout:\n%s", __FUNCTION__, stdout_str);
- g_message ("%s: mapper stderr:\n%s", __FUNCTION__, stderr_str);
- }
- else
+ if (get_relay_info_entity (original_host, original_port,
+ protocol, &relay_entity) == 0)
{
entity_t host_entity, port_entity, ca_cert_entity;
@@ -5049,9 +5151,6 @@ slave_get_relay (const char *original_host,
}
free_entity (relay_entity);
}
- g_strfreev (cmd);
- g_free (stdout_str);
- g_free (stderr_str);
}
return ret;
diff --git a/src/manage.h b/src/manage.h
index 174385cd7..e7bceac18 100644
--- a/src/manage.h
+++ b/src/manage.h
@@ -2856,6 +2856,15 @@ get_relay_mapper_path ();
void
set_relay_mapper_path (const char *);
+int
+get_relay_migrate_sensors ();
+
+void
+set_relay_migrate_sensors (int);
+
+gboolean
+relay_supports_scanner_type (const char *, int, scanner_type_t);
+
int
slave_get_relay (const char *,
int,
diff --git a/src/manage_sql.c b/src/manage_sql.c
index 94b905ded..cbd1bfde7 100644
--- a/src/manage_sql.c
+++ b/src/manage_sql.c
@@ -17932,6 +17932,108 @@ clean_auth_cache ()
sql ("DELETE FROM auth_cache;");
}
+/**
+ * @brief Tries to migrate sensor type scanners to match the relays.
+ *
+ * @return A string describing the results or NULL on error.
+ */
+static gchar *
+manage_migrate_relay_sensors ()
+{
+ iterator_t scanners;
+ int gmp_successes, gmp_failures, osp_failures;
+
+ gmp_successes = gmp_failures = osp_failures = 0;
+
+ if (get_relay_mapper_path () == NULL)
+ {
+ g_warning ("%s: No relay mapper set", __FUNCTION__);
+ return NULL;
+ }
+
+ init_iterator (&scanners,
+ "SELECT id, uuid, type, host, port FROM scanners"
+ " WHERE type in (%d, %d)",
+ SCANNER_TYPE_GMP,
+ SCANNER_TYPE_OSP_SENSOR);
+
+ while (next (&scanners))
+ {
+ scanner_t scanner;
+ scanner_type_t type;
+ const char *scanner_id, *host;
+ int port;
+
+ scanner = iterator_int64 (&scanners, 0);
+ scanner_id = iterator_string (&scanners, 1);
+ type = iterator_int (&scanners, 2);
+ host = iterator_string (&scanners, 3);
+ port = iterator_int (&scanners, 4);
+
+ if (relay_supports_scanner_type (host, port, type) == FALSE)
+ {
+ if (type == SCANNER_TYPE_GMP)
+ {
+ if (relay_supports_scanner_type (host, port,
+ SCANNER_TYPE_OSP_SENSOR))
+ {
+ g_message ("%s: No GMP relay found for scanner %s (%s:%d)."
+ " Changing into OSP Sensor",
+ __FUNCTION__, scanner_id, host, port);
+
+ sql ("UPDATE scanners"
+ " SET credential = NULL, type = %d"
+ " WHERE id = %llu",
+ SCANNER_TYPE_OSP_SENSOR,
+ scanner);
+
+ gmp_successes++;
+ }
+ else
+ {
+ g_message ("%s: No relay found for GMP scanner %s (%s:%d).",
+ __FUNCTION__, scanner_id, host, port);
+ gmp_failures++;
+ }
+ }
+ else if (type == SCANNER_TYPE_OSP_SENSOR)
+ {
+ g_message ("%s: No relay found for OSP Sensor %s (%s:%d).",
+ __FUNCTION__, scanner_id, host, port);
+ osp_failures++;
+ }
+ else
+ g_warning ("%s: Unexpected type for scanner %s: %d",
+ __FUNCTION__, scanner_id, type);
+ }
+ }
+ cleanup_iterator (&scanners);
+
+ if (gmp_successes == 0 && gmp_failures == 0 && osp_failures == 0)
+ return g_strdup ("All GMP or OSP sensors up to date.");
+ else
+ {
+ GString *message = g_string_new ("");
+ g_string_append_printf (message,
+ "%d sensors(s) not matching:",
+ gmp_successes + gmp_failures + osp_failures);
+ if (gmp_successes)
+ g_string_append_printf (message,
+ " %d GMP scanner(s) migrated to OSP.",
+ gmp_successes);
+ if (gmp_failures)
+ g_string_append_printf (message,
+ " %d GMP scanner(s) not migrated.",
+ gmp_failures);
+ if (osp_failures)
+ g_string_append_printf (message,
+ " %d OSP sensor(s) not migrated.",
+ osp_failures);
+
+ return g_string_free (message, FALSE);
+ }
+}
+
/**
* @brief Ensure that the database is in order.
*
@@ -65010,6 +65112,25 @@ manage_optimize (GSList *log_config, const gchar *database, const gchar *name)
" Due date updated for %d tasks.",
changes);
}
+ else if (strcasecmp (name, "migrate-relay-sensors") == 0)
+ {
+ if (get_relay_mapper_path ())
+ {
+ sql_begin_immediate ();
+
+ success_text = manage_migrate_relay_sensors ();
+
+ sql_commit ();
+ }
+ else
+ {
+ fprintf (stderr,
+ "No relay mapper found."
+ " Please check your $PATH or the --relay-mapper option.\n");
+ success_text = NULL;
+ ret = -1;
+ }
+ }
else if (strcasecmp (name, "rebuild-permissions-cache") == 0)
{
sql_begin_immediate ();