// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2007 - 2018 Red Hat, Inc.
* Copyright (C) 2008 Novell, Inc.
*/
#include "nm-default.h"
#include "nm-settings-plugin.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "nm-settings-connection.h"
/*****************************************************************************/
enum {
UNMANAGED_SPECS_CHANGED,
UNRECOGNIZED_SPECS_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (NMSettingsPlugin, nm_settings_plugin, G_TYPE_OBJECT)
/*****************************************************************************/
int
nm_settings_plugin_cmp_by_priority (const NMSettingsPlugin *a,
const NMSettingsPlugin *b,
const GSList *plugin_list)
{
nm_assert (NM_IS_SETTINGS_PLUGIN (a));
nm_assert (NM_IS_SETTINGS_PLUGIN (b));
if (a != b) {
int idx_a = g_slist_index ((GSList *) plugin_list, a);
int idx_b = g_slist_index ((GSList *) plugin_list, b);
/* the plugins must be found in the list. */
nm_assert (idx_a >= 0);
nm_assert (idx_b >= 0);
/* plugins that appear first in @plugin_list have higher priority.
* That means: smaller index -> higher priority. Reverse sort. */
NM_CMP_DIRECT (idx_b, idx_a);
}
return 0;
}
/*****************************************************************************/
GSList *
nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->get_unmanaged_specs)
return NULL;
return klass->get_unmanaged_specs (self);
}
GSList *
nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->get_unrecognized_specs)
return NULL;
return klass->get_unrecognized_specs (self);
}
void
nm_settings_plugin_reload_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
g_return_if_fail (callback);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->reload_connections)
klass->reload_connections (self, callback, user_data);
}
NMSettingsPluginConnectionLoadEntry *
nm_settings_plugin_create_connection_load_entries (const char *const*filenames,
gsize *out_len)
{
NMSettingsPluginConnectionLoadEntry *entries;
gsize len;
gsize i;
len = NM_PTRARRAY_LEN (filenames);
if (len == 0) {
*out_len = 0;
return NULL;
}
entries = g_new (NMSettingsPluginConnectionLoadEntry, len);
for (i = 0; i < len; i++) {
entries[i] = (NMSettingsPluginConnectionLoadEntry) {
.filename = filenames[i],
.error = NULL,
.handled = FALSE,
};
}
*out_len = len;
return entries;
}
void
nm_settings_plugin_load_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadEntry *entries,
gsize n_entries,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->load_connections)
klass->load_connections (self, entries, n_entries, callback, user_data);
}
void
nm_settings_plugin_load_connections_done (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->load_connections_done)
klass->load_connections_done (self);
}
gboolean
nm_settings_plugin_add_connection (NMSettingsPlugin *self,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
#if NM_MORE_ASSERTS > 5
nm_assert (nm_connection_verify (connection, NULL));
#endif
NM_SET_OUT (out_storage, NULL);
NM_SET_OUT (out_connection, NULL);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->add_connection) {
g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_SUPPORTED,
"settings plugin does not support adding connections");
return FALSE;
}
return klass->add_connection (self,
connection,
out_storage,
out_connection,
error);
}
gboolean
nm_settings_plugin_update_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error)
{
NMSettingsPluginClass *klass = NULL;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
#if NM_MORE_ASSERTS > 5
nm_assert (nm_connection_verify (connection, NULL));
nm_assert (nm_streq (nm_connection_get_uuid (connection), nm_settings_storage_get_uuid (storage)));
#endif
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
NM_SET_OUT (out_storage, NULL);
NM_SET_OUT (out_connection, NULL);
if (!klass->update_connection) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_SUPPORTED,
"settings plugin does not support modifying connections");
return FALSE;
}
return klass->update_connection (self,
storage,
connection,
out_storage,
out_connection,
error);
}
gboolean
nm_settings_plugin_delete_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
GError **error)
{
NMSettingsPluginClass *klass = NULL;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->delete_connection) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_SUPPORTED,
"settings plugin does not support deleting connections");
return FALSE;
}
return klass->delete_connection (self,
storage,
error);
}
/*****************************************************************************/
void
_nm_settings_plugin_emit_signal_unmanaged_specs_changed (NMSettingsPlugin *self)
{
nm_assert (NM_IS_SETTINGS_PLUGIN (self));
g_signal_emit (self, signals[UNMANAGED_SPECS_CHANGED], 0);
}
void
_nm_settings_plugin_emit_signal_unrecognized_specs_changed (NMSettingsPlugin *self)
{
nm_assert (NM_IS_SETTINGS_PLUGIN (self));
g_signal_emit (self, signals[UNRECOGNIZED_SPECS_CHANGED], 0);
}
/*****************************************************************************/
static void
nm_settings_plugin_init (NMSettingsPlugin *self)
{
}
static void
nm_settings_plugin_class_init (NMSettingsPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
signals[UNMANAGED_SPECS_CHANGED] =
g_signal_new (NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[UNRECOGNIZED_SPECS_CHANGED] =
g_signal_new (NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}