diff options
Diffstat (limited to 'src/settings/plugins/ifupdown/nms-ifupdown-plugin.c')
| -rw-r--r-- | src/settings/plugins/ifupdown/nms-ifupdown-plugin.c | 453 |
1 files changed, 315 insertions, 138 deletions
diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 88c651b8..8bd72d02 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -29,6 +29,7 @@ #include <string.h> #include <arpa/inet.h> #include <gmodule.h> +#include <libudev.h> #include "nm-setting-connection.h" #include "nm-dbus-interface.h" @@ -41,6 +42,7 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-config.h" +#include "nm-utils/nm-udev-utils.h" #include "nms-ifupdown-interface-parser.h" #include "nms-ifupdown-connection.h" @@ -50,27 +52,43 @@ #define IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT TRUE +/* #define ALWAYS_UNMANAGE TRUE */ +#ifndef ALWAYS_UNMANAGE +#define ALWAYS_UNMANAGE FALSE +#endif + /*****************************************************************************/ typedef struct { - /* Stores an entry for blocks/interfaces read from /e/n/i and (if exists) - * the NMIfupdownConnection associated with the block. + NMUdevClient *udev_client; + + GHashTable *connections; /* /e/n/i block name :: NMIfupdownConnection */ + + /* Stores all blocks/interfaces read from /e/n/i regardless of whether + * there is an NMIfupdownConnection for block. */ GHashTable *eni_ifaces; - bool ifupdown_managed; + /* Stores any network interfaces the kernel knows about */ + GHashTable *kernel_ifaces; + + gboolean unmanage_well_known; } SettingsPluginIfupdownPrivate; struct _SettingsPluginIfupdown { - NMSettingsPlugin parent; + GObject parent; SettingsPluginIfupdownPrivate _priv; }; struct _SettingsPluginIfupdownClass { - NMSettingsPluginClass parent; + GObjectClass parent; }; -G_DEFINE_TYPE (SettingsPluginIfupdown, settings_plugin_ifupdown, NM_TYPE_SETTINGS_PLUGIN) +static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); + +G_DEFINE_TYPE_EXTENDED (SettingsPluginIfupdown, settings_plugin_ifupdown, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, + settings_plugin_interface_init)) #define SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, SettingsPluginIfupdown, SETTINGS_IS_PLUGIN_IFUPDOWN) @@ -81,41 +99,169 @@ NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfupdown, settings_plugin_ifupdown_get /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "ifupdown" -#define _NMLOG_DOMAIN LOGD_SETTINGS -#define _NMLOG(level, ...) \ - nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ - "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME": " \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)) +static void +bind_device_to_connection (SettingsPluginIfupdown *self, + struct udev_device *device, + NMIfupdownConnection *exported) +{ + NMSettingWired *s_wired; + NMSettingWireless *s_wifi; + const char *iface, *address; + + iface = udev_device_get_sysname (device); + if (!iface) { + nm_log_warn (LOGD_SETTINGS, "failed to get ifname for device."); + return; + } + + address = udev_device_get_sysattr_value (device, "address"); + if (!address || !address[0]) { + nm_log_warn (LOGD_SETTINGS, "failed to get MAC address for %s", iface); + return; + } -/*****************************************************************************/ + if (!nm_utils_hwaddr_valid (address, ETH_ALEN)) { + nm_log_warn (LOGD_SETTINGS, "failed to parse MAC address '%s' for %s", + address, iface); + return; + } + + s_wired = nm_connection_get_setting_wired (NM_CONNECTION (exported)); + s_wifi = nm_connection_get_setting_wireless (NM_CONNECTION (exported)); + if (s_wired) { + nm_log_info (LOGD_SETTINGS, "locking wired connection setting"); + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, address, NULL); + } else if (s_wifi) { + nm_log_info (LOGD_SETTINGS, "locking wireless connection setting"); + g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, address, NULL); + } + + nm_settings_connection_update (NM_SETTINGS_CONNECTION (exported), + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "ifupdown-new", + NULL); +} + +static void +udev_device_added (SettingsPluginIfupdown *self, struct udev_device *device) +{ + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + const char *iface, *path; + NMIfupdownConnection *exported; + + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); + if (!iface || !path) + return; + + nm_log_info (LOGD_SETTINGS, "devices added (path: %s, iface: %s)", path, iface); + + /* if we have a configured connection for this particular iface + * we want to either unmanage the device or lock it + */ + exported = g_hash_table_lookup (priv->connections, iface); + if (!exported && !g_hash_table_lookup (priv->eni_ifaces, iface)) { + nm_log_info (LOGD_SETTINGS, "device added (path: %s, iface: %s): no ifupdown configuration found.", + path, iface); + return; + } + + g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), udev_device_ref (device)); + + if (exported) + bind_device_to_connection (self, device, exported); + + if (ALWAYS_UNMANAGE || priv->unmanage_well_known) + g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); +} + +static void +udev_device_removed (SettingsPluginIfupdown *self, struct udev_device *device) +{ + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + const char *iface, *path; + + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); + if (!iface || !path) + return; + + nm_log_info (LOGD_SETTINGS, "devices removed (path: %s, iface: %s)", path, iface); + + if (!g_hash_table_remove (priv->kernel_ifaces, iface)) + return; + + if (ALWAYS_UNMANAGE || priv->unmanage_well_known) + g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); +} + +static void +udev_device_changed (SettingsPluginIfupdown *self, struct udev_device *device) +{ + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + const char *iface, *path; + + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); + if (!iface || !path) + return; + + nm_log_info (LOGD_SETTINGS, "device changed (path: %s, iface: %s)", path, iface); + + if (!g_hash_table_lookup (priv->kernel_ifaces, iface)) + return; + + if (ALWAYS_UNMANAGE || priv->unmanage_well_known) + g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); +} + +static void +handle_uevent (NMUdevClient *client, + struct udev_device *device, + gpointer user_data) +{ + SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (user_data); + const char *subsys; + const char *action; + + action = udev_device_get_action (device); + + g_return_if_fail (action != NULL); + + /* A bit paranoid */ + subsys = udev_device_get_subsystem (device); + g_return_if_fail (nm_streq0 (subsys, "net")); + + if (!strcmp (action, "add")) + udev_device_added (self, device); + else if (!strcmp (action, "remove")) + udev_device_removed (self, device); + else if (!strcmp (action, "change")) + udev_device_changed (self, device); +} /* Returns the plugins currently known list of connections. The returned * list is freed by the system settings service. */ static GSList* -get_connections (NMSettingsPlugin *plugin) +get_connections (NMSettingsPlugin *config) { - SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - GSList *list = NULL; - GHashTableIter iter; - void *value; + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); + GSList *connections; + + nm_log_info (LOGD_SETTINGS, "(%d) ... get_connections.", GPOINTER_TO_UINT(config)); - if (!priv->ifupdown_managed) { - _LOGD ("get_connections: not connections due to managed=false"); + if(priv->unmanage_well_known) { + nm_log_info (LOGD_SETTINGS, "(%d) ... get_connections (managed=false): return empty list.", GPOINTER_TO_UINT(config)); return NULL; } - g_hash_table_iter_init (&iter, priv->eni_ifaces); - while (g_hash_table_iter_next (&iter, NULL, &value)) { - if (value) - list = g_slist_prepend (list, value); - } + connections = _nm_utils_hash_values_to_slist (priv->connections); - _LOGD ("get_connections: %u connections", g_slist_length (list)); - return list; + nm_log_info (LOGD_SETTINGS, "(%d) connections count: %d", GPOINTER_TO_UINT(config), g_slist_length(connections)); + return connections; } /* @@ -124,178 +270,202 @@ get_connections (NMSettingsPlugin *plugin) * each element must be allocated using g_malloc() or its variants. */ static GSList* -get_unmanaged_specs (NMSettingsPlugin *plugin) +get_unmanaged_specs (NMSettingsPlugin *config) { - SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); GSList *specs = NULL; GHashTableIter iter; + struct udev_device *device; const char *iface; - if (priv->ifupdown_managed) + if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) return NULL; - _LOGD ("unmanaged-specs: unmanaged devices count %u", - g_hash_table_size (priv->eni_ifaces)); + nm_log_info (LOGD_SETTINGS, "get unmanaged devices count: %d", + g_hash_table_size (priv->kernel_ifaces)); + + g_hash_table_iter_init (&iter, priv->kernel_ifaces); + while (g_hash_table_iter_next (&iter, (gpointer) &iface, (gpointer) &device)) { + const char *address; - g_hash_table_iter_init (&iter, priv->eni_ifaces); - while (g_hash_table_iter_next (&iter, (gpointer) &iface, NULL)) - specs = g_slist_append (specs, g_strdup_printf ("interface-name:=%s", iface)); + address = udev_device_get_sysattr_value (device, "address"); + if (address) + specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address)); + else + specs = g_slist_append (specs, g_strdup_printf ("interface-name:%s", iface)); + } return specs; } /*****************************************************************************/ static void -initialize (NMSettingsPlugin *plugin) +_udev_device_unref (gpointer ptr) { - SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); + udev_device_unref (ptr); +} + +static void +init (NMSettingsPlugin *config) +{ + SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (config); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - gs_unref_hashtable GHashTable *auto_ifaces = NULL; - nm_auto_ifparser if_parser *parser = NULL; - if_block *block; + GHashTable *auto_ifaces; + if_block *block = NULL; + struct udev_enumerate *enumerate; + struct udev_list_entry *keys; GHashTableIter con_iter; const char *block_name; - NMIfupdownConnection *conn; + NMIfupdownConnection *connection; - parser = ifparser_parse (ENI_INTERFACES_FILE, 0); + auto_ifaces = g_hash_table_new (nm_str_hash, g_str_equal); - c_list_for_each_entry (block, &parser->block_lst_head, block_lst) { + if(!priv->connections) + priv->connections = g_hash_table_new (nm_str_hash, g_str_equal); - if (NM_IN_STRSET (block->type, "auto", "allow-hotplug")) { - if (!auto_ifaces) - auto_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL); - g_hash_table_add (auto_ifaces, g_strdup (block->name)); - continue; - } + if(!priv->kernel_ifaces) + priv->kernel_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, _udev_device_unref); + + if(!priv->eni_ifaces) + priv->eni_ifaces = g_hash_table_new (nm_str_hash, g_str_equal); + + nm_log_info (LOGD_SETTINGS, "init!"); + + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + handle_uevent, self); + + /* Read in all the interfaces */ + ifparser_init (ENI_INTERFACES_FILE, 0); + block = ifparser_getfirst (); + while (block) { + if(!strcmp ("auto", block->type) || !strcmp ("allow-hotplug", block->type)) + g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1)); + else if (!strcmp ("iface", block->type)) { + NMIfupdownConnection *exported; - if (nm_streq (block->type, "iface")) { /* Bridge configuration */ - if (g_str_has_prefix (block_name, "br")) { + if(!strncmp ("br", block->name, 2)) { /* Try to find bridge ports */ const char *ports = ifparser_getkey (block, "bridge-ports"); - if (ports) { - guint i; + int i; int state = 0; - gs_strfreev char **port_ifaces = NULL; + char **port_ifaces; - _LOGD ("parse: found bridge ports %s for %s", ports, block->name); + nm_log_info (LOGD_SETTINGS, "found bridge ports %s for %s", ports, block->name); port_ifaces = g_strsplit_set (ports, " \t", -1); - for (i = 0; port_ifaces[i]; i++) { - const char *token = port_ifaces[i]; - + for (i = 0; i < g_strv_length (port_ifaces); i++) { + char *token = port_ifaces[i]; /* Skip crazy stuff like regex or all */ - if (nm_streq (token, "all")) + if (!strcmp ("all", token)) { continue; - + } /* Small SM to skip everything inside regex */ - if (nm_streq (token, "regex")) { + if (!strcmp ("regex", token)) { state++; continue; } - if (nm_streq (token, "noregex")) { + if (!strcmp ("noregex", token)) { state--; continue; } - if (nm_streq (token, "none")) - continue; if (state == 0 && strlen (token) > 0) { - conn = g_hash_table_lookup (priv->eni_ifaces, block->name); - if (!conn) { - _LOGD ("parse: adding bridge port \"%s\"", token); - g_hash_table_insert (priv->eni_ifaces, g_strdup (token), NULL); - } else { - _LOGD ("parse: adding bridge port \"%s\" (have connection %s)", token, - nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); - } + nm_log_info (LOGD_SETTINGS, "adding bridge port %s to eni_ifaces", token); + g_hash_table_insert (priv->eni_ifaces, g_strdup (token), "known"); } } + g_strfreev (port_ifaces); } - continue; + goto next; } /* Skip loopback configuration */ - if (nm_streq (block->name, "lo")) - continue; + if(!strcmp ("lo", block->name)) { + goto next; + } /* Remove any connection for this block that was previously found */ - conn = g_hash_table_lookup (priv->eni_ifaces, block->name); - if (conn) { - _LOGD ("parse: replace connection \"%s\" (%s)", - block->name, - nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); - nm_settings_connection_delete (NM_SETTINGS_CONNECTION (conn), NULL); - g_hash_table_remove (priv->eni_ifaces, block->name); + exported = g_hash_table_lookup (priv->connections, block->name); + if (exported) { + nm_log_info (LOGD_SETTINGS, "deleting %s from connections", block->name); + nm_settings_connection_delete (NM_SETTINGS_CONNECTION (exported), NULL); + g_hash_table_remove (priv->connections, block->name); } /* add the new connection */ - conn = nm_ifupdown_connection_new (block); - if (conn) { - _LOGD ("parse: adding connection \"%s\" (%s)", block->name, - nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); - } else - _LOGD ("parse: adding place holder for connection \"%s\"", block->name); - g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), conn); - continue; - } - - if (nm_streq (block->type, "mapping")) { - conn = g_hash_table_lookup (priv->eni_ifaces, block->name); - if (!conn) { - _LOGD ("parse: adding mapping \"%s\"", block->name); - g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), NULL); - } else { - _LOGD ("parse: adding mapping \"%s\" (have connection %s)", block->name, - nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); + exported = nm_ifupdown_connection_new (block); + if (exported) { + nm_log_info (LOGD_SETTINGS, "adding %s to connections", block->name); + g_hash_table_insert (priv->connections, block->name, exported); } - continue; + nm_log_info (LOGD_SETTINGS, "adding iface %s to eni_ifaces", block->name); + g_hash_table_insert (priv->eni_ifaces, block->name, "known"); + } else if (!strcmp ("mapping", block->type)) { + g_hash_table_insert (priv->eni_ifaces, block->name, "known"); + nm_log_info (LOGD_SETTINGS, "adding mapping %s to eni_ifaces", block->name); } + next: + block = block->next; } /* Make 'auto' interfaces autoconnect=TRUE */ - g_hash_table_iter_init (&con_iter, priv->eni_ifaces); - while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &conn)) { + g_hash_table_iter_init (&con_iter, priv->connections); + while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &connection)) { NMSettingConnection *setting; - if ( !conn - || !auto_ifaces - || !g_hash_table_contains (auto_ifaces, block_name)) - continue; - - /* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */ - setting = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (conn))); - g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); + if (g_hash_table_lookup (auto_ifaces, block_name)) { + setting = nm_connection_get_setting_connection (NM_CONNECTION (connection)); + g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); + nm_log_info (LOGD_SETTINGS, "autoconnect"); + } } + g_hash_table_destroy (auto_ifaces); /* Check the config file to find out whether to manage interfaces */ - priv->ifupdown_managed = nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG, - NM_CONFIG_KEYFILE_GROUP_IFUPDOWN, - NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED, - !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT); - _LOGI ("management mode: %s", priv->ifupdown_managed ? "managed" : "unmanaged"); + priv->unmanage_well_known = !nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG, + NM_CONFIG_KEYFILE_GROUP_IFUPDOWN, + NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED, + !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT); + nm_log_info (LOGD_SETTINGS, "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed"); + + /* Add well-known interfaces */ + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_scan_devices (enumerate); + keys = udev_enumerate_get_list_entry (enumerate); + for (; keys; keys = udev_list_entry_get_next (keys)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (keys)); + if (udevice) { + udev_device_added (self, udevice); + udev_device_unref (udevice); + } + } + udev_enumerate_unref (enumerate); /* Now if we're running in managed mode, let NM know there are new connections */ - if (priv->ifupdown_managed) { - GHashTableIter iter; - - g_hash_table_iter_init (&iter, priv->eni_ifaces); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) conn)) { - _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), - NM_SETTINGS_CONNECTION (conn)); + if (!priv->unmanage_well_known) { + GList *con_list = g_hash_table_get_values (priv->connections); + GList *cl_iter; + + for (cl_iter = con_list; cl_iter; cl_iter = g_list_next (cl_iter)) { + g_signal_emit_by_name (self, + NM_SETTINGS_PLUGIN_CONNECTION_ADDED, + NM_SETTINGS_CONNECTION (cl_iter->data)); } + g_list_free (con_list); } + + nm_log_info (LOGD_SETTINGS, "end _init."); } /*****************************************************************************/ static void -settings_plugin_ifupdown_init (SettingsPluginIfupdown *self) +settings_plugin_ifupdown_init (SettingsPluginIfupdown *plugin) { - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - - priv->eni_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref); } static void @@ -304,28 +474,35 @@ dispose (GObject *object) SettingsPluginIfupdown *plugin = SETTINGS_PLUGIN_IFUPDOWN (object); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin); + g_clear_pointer (&priv->kernel_ifaces, g_hash_table_destroy); g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); + priv->udev_client = nm_udev_client_unref (priv->udev_client); + G_OBJECT_CLASS (settings_plugin_ifupdown_parent_class)->dispose (object); } static void -settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *klass) +settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *req_class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (req_class); object_class->dispose = dispose; +} - plugin_class->initialize = initialize; - plugin_class->get_connections = get_connections; - plugin_class->get_unmanaged_specs = get_unmanaged_specs; +static void +settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) +{ + plugin_iface->init = init; + plugin_iface->get_connections = get_connections; + plugin_iface->get_unmanaged_specs = get_unmanaged_specs; } /*****************************************************************************/ -G_MODULE_EXPORT NMSettingsPlugin * +G_MODULE_EXPORT GObject * nm_settings_plugin_factory (void) { - return NM_SETTINGS_PLUGIN (g_object_ref (settings_plugin_ifupdown_get ())); + return G_OBJECT (g_object_ref (settings_plugin_ifupdown_get ())); } + |