diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index b5afbd71ab..e930815335 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -115,6 +115,7 @@ static void impl_settings_save_hostname (NMSettings *self, #include "nm-settings-glue.h" static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); +static void unrecognized_specs_changed (NMSystemConfigInterface *config, gpointer user_data); static void connection_provider_init (NMConnectionProvider *cp_class); @@ -136,6 +137,7 @@ typedef struct { gboolean connections_loaded; GHashTable *connections; GSList *unmanaged_specs; + GSList *unrecognized_specs; GSList *get_connections_cache; } NMSettingsPrivate; @@ -201,11 +203,14 @@ load_connections (NMSettings *self) G_CALLBACK (plugin_connection_added), self); g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED, G_CALLBACK (unmanaged_specs_changed), self); + g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED, + G_CALLBACK (unrecognized_specs_changed), self); } priv->connections_loaded = TRUE; unmanaged_specs_changed (NULL, self); + unrecognized_specs_changed (NULL, self); g_signal_emit (self, signals[CONNECTIONS_LOADED], 0); g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTIONS_LOADED); @@ -356,15 +361,6 @@ nm_settings_get_connection_by_path (NMSettings *self, const char *path) return (NMSettingsConnection *) g_hash_table_lookup (priv->connections, path); } -static void -clear_unmanaged_specs (NMSettings *self) -{ - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - - g_slist_free_full (priv->unmanaged_specs, g_free); - priv->unmanaged_specs = NULL; -} - static char* uscore_to_wincaps (const char *uscore) { @@ -466,16 +462,40 @@ nm_settings_get_hostname (NMSettings *self) } static gboolean -find_unmanaged_device (NMSettings *self, const char *needle) +find_spec (GSList *spec_list, const char *spec) +{ + GSList *iter; + + for (iter = spec_list; iter; iter = g_slist_next (iter)) { + if (!strcmp ((const char *) iter->data, spec)) + return TRUE; + } + return FALSE; +} + +static void +update_specs (NMSettings *self, GSList **specs_ptr, + GSList * (*get_specs_func) (NMSystemConfigInterface *)) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); GSList *iter; - for (iter = priv->unmanaged_specs; iter; iter = g_slist_next (iter)) { - if (!strcmp ((const char *) iter->data, needle)) - return TRUE; + g_slist_free_full (*specs_ptr, g_free); + *specs_ptr = NULL; + + for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { + GSList *specs, *specs_iter; + + specs = get_specs_func (NM_SYSTEM_CONFIG_INTERFACE (iter->data)); + for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) { + if (!find_spec (*specs_ptr, (const char *) specs_iter->data)) { + *specs_ptr = g_slist_prepend (*specs_ptr, specs_iter->data); + } else + g_free (specs_iter->data); + } + + g_slist_free (specs); } - return FALSE; } static void @@ -484,28 +504,23 @@ unmanaged_specs_changed (NMSystemConfigInterface *config, { NMSettings *self = NM_SETTINGS (user_data); NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - clear_unmanaged_specs (self); - - /* Ask all the plugins for their unmanaged specs */ - for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { - GSList *specs, *specs_iter; - - specs = nm_system_config_interface_get_unmanaged_specs (NM_SYSTEM_CONFIG_INTERFACE (iter->data)); - for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) { - if (!find_unmanaged_device (self, (const char *) specs_iter->data)) { - priv->unmanaged_specs = g_slist_prepend (priv->unmanaged_specs, specs_iter->data); - } else - g_free (specs_iter->data); - } - - g_slist_free (specs); - } + update_specs (self, &priv->unmanaged_specs, + nm_system_config_interface_get_unmanaged_specs); g_object_notify (G_OBJECT (self), NM_SETTINGS_UNMANAGED_SPECS); } +static void +unrecognized_specs_changed (NMSystemConfigInterface *config, + gpointer user_data) +{ + NMSettings *self = NM_SETTINGS (user_data); + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + + update_specs (self, &priv->unrecognized_specs, + nm_system_config_interface_get_unrecognized_specs); +} + static void hostname_changed (NMSystemConfigInterface *config, GParamSpec *pspec, @@ -1430,6 +1445,10 @@ have_connection_for_device (NMSettings *self, NMDevice *device) } } + /* See if there's a known non-NetworkManager configuration for the device */ + if (nm_device_spec_match_list (device, priv->unrecognized_specs)) + return TRUE; + return FALSE; } @@ -1698,6 +1717,7 @@ nm_settings_new (GError **error) } unmanaged_specs_changed (NULL, self); + unrecognized_specs_changed (NULL, self); nm_dbus_manager_register_object (priv->dbus_mgr, NM_DBUS_PATH_SETTINGS, self); return self; @@ -1757,7 +1777,8 @@ finalize (GObject *object) g_hash_table_destroy (priv->connections); g_slist_free (priv->get_connections_cache); - clear_unmanaged_specs (self); + g_slist_free_full (priv->unmanaged_specs, g_free); + g_slist_free_full (priv->unrecognized_specs, g_free); g_slist_free_full (priv->plugins, g_object_unref); diff --git a/src/settings/nm-system-config-interface.c b/src/settings/nm-system-config-interface.c index 65c85b0520..20e52c7d05 100644 --- a/src/settings/nm-system-config-interface.c +++ b/src/settings/nm-system-config-interface.c @@ -84,6 +84,14 @@ interface_init (gpointer g_iface) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSystemConfigInterface, unrecognized_specs_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + initialized = TRUE; } @@ -156,6 +164,16 @@ nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config) return NULL; } +GSList * +nm_system_config_interface_get_unrecognized_specs (NMSystemConfigInterface *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unrecognized_specs) + return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unrecognized_specs (config); + return NULL; +} + /** * nm_system_config_interface_add_connection: * @config: the #NMSystemConfigInterface diff --git a/src/settings/nm-system-config-interface.h b/src/settings/nm-system-config-interface.h index ad40f9cf0c..55643ef9f1 100644 --- a/src/settings/nm-system-config-interface.h +++ b/src/settings/nm-system-config-interface.h @@ -53,6 +53,7 @@ GObject * nm_system_config_factory (void); #define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname" #define NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed" +#define NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED "unrecognized-specs-changed" #define NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED "connection-added" typedef enum { @@ -100,20 +101,23 @@ struct _NMSystemConfigInterface { * service, and each element must be allocated using g_malloc() or its * variants (g_strdup, g_strdup_printf, etc). * - * Each string in the list must follow the format :, where - * the method and data are one of the following: - * - * Method: mac Data: device MAC address formatted with leading zeros and - * lowercase letters, like 00:0a:0b:0c:0d:0e - * - * Method: s390-subchannels Data: string of 2 or 3 s390 subchannels - * separated by commas (,) that identify the - * device, like "0.0.09a0,0.0.09a1,0.0.09a2". - * The string may contain only the following - * characters: [a-fA-F0-9,.] + * Each string in the list must be in one of the formats recognized by + * nm_device_spec_match_list(). */ GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config); + /* + * Return a string list of specifications of devices for which at least + * one non-NetworkManager-based configuration is defined. Returned list + * will be freed by the system settings service, and each element must be + * allocated using g_malloc() or its variants (g_strdup, g_strdup_printf, + * etc). + * + * Each string in the list must be in one of the formats recognized by + * nm_device_spec_match_list(). + */ + GSList * (*get_unrecognized_specs) (NMSystemConfigInterface *config); + /* * Initialize the plugin-specific connection and return a new * NMSettingsConnection subclass that contains the same settings as the @@ -134,6 +138,9 @@ struct _NMSystemConfigInterface { /* Emitted when the list of unmanaged device specifications changes */ void (*unmanaged_specs_changed) (NMSystemConfigInterface *config); + + /* Emitted when the list of devices with unrecognized connections changes */ + void (*unrecognized_specs_changed) (NMSystemConfigInterface *config); }; GType nm_system_config_interface_get_type (void); @@ -146,6 +153,7 @@ GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *con void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config); GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config); +GSList *nm_system_config_interface_get_unrecognized_specs (NMSystemConfigInterface *config); NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config, NMConnection *connection, diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 91dc7c8370..3db06f17dd 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -61,12 +61,14 @@ typedef struct { char *route6file; int route6file_wd; - char *unmanaged; + char *unmanaged_spec; + char *unrecognized_spec; } NMIfcfgConnectionPrivate; enum { PROP_0, - PROP_UNMANAGED, + PROP_UNMANAGED_SPEC, + PROP_UNRECOGNIZED_SPEC, LAST_PROP }; @@ -105,7 +107,8 @@ nm_ifcfg_connection_new (NMConnection *source, { GObject *object; NMConnection *tmp; - char *unmanaged = NULL; + char *unhandled_spec = NULL; + const char *unmanaged_spec = NULL, *unrecognized_spec = NULL; gboolean update_unsaved = TRUE; g_assert (source || full_path); @@ -117,7 +120,7 @@ nm_ifcfg_connection_new (NMConnection *source, char *keyfile = NULL, *routefile = NULL, *route6file = NULL; tmp = connection_from_file (full_path, NULL, NULL, NULL, - &unmanaged, + &unhandled_spec, &keyfile, &routefile, &route6file, @@ -133,8 +136,14 @@ nm_ifcfg_connection_new (NMConnection *source, update_unsaved = FALSE; } + if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:")) + unmanaged_spec = unhandled_spec + strlen ("unmanaged:"); + else if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unrecognized:")) + unrecognized_spec = unhandled_spec + strlen ("unrecognized:"); + object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION, - NM_IFCFG_CONNECTION_UNMANAGED, unmanaged, + NM_IFCFG_CONNECTION_UNMANAGED_SPEC, unmanaged_spec, + NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec, NULL); if (object) { /* Update our settings with what was read from the file */ @@ -152,6 +161,7 @@ nm_ifcfg_connection_new (NMConnection *source, } g_object_unref (tmp); + g_free (unhandled_spec); return (NMIfcfgConnection *) object; } @@ -234,7 +244,15 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self) { g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL); - return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged; + return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged_spec; +} + +const char * +nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self) +{ + g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL); + + return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec; } static void @@ -344,8 +362,11 @@ set_property (GObject *object, guint prop_id, NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_UNMANAGED: - priv->unmanaged = g_value_dup_string (value); + case PROP_UNMANAGED_SPEC: + priv->unmanaged_spec = g_value_dup_string (value); + break; + case PROP_UNRECOGNIZED_SPEC: + priv->unrecognized_spec = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -360,8 +381,11 @@ get_property (GObject *object, guint prop_id, NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_UNMANAGED: - g_value_set_string (value, priv->unmanaged); + case PROP_UNMANAGED_SPEC: + g_value_set_string (value, priv->unmanaged_spec); + break; + case PROP_UNRECOGNIZED_SPEC: + g_value_set_string (value, priv->unrecognized_spec); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -386,12 +410,19 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class) /* Properties */ g_object_class_install_property - (object_class, PROP_UNMANAGED, - g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED, - "Unmanaged", - "Unmanaged", + (object_class, PROP_UNMANAGED_SPEC, + g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED_SPEC, + "Unmanaged spec", + "Unmanaged spec", NULL, G_PARAM_READWRITE)); + g_object_class_install_property + (object_class, PROP_UNRECOGNIZED_SPEC, + g_param_spec_string (NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, + "Unrecognized spec", + "Unrecognized spec", + NULL, + G_PARAM_READWRITE)); signals[IFCFG_CHANGED] = g_signal_new ("ifcfg-changed", diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h index 7c21ffb85e..47422b5dba 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h @@ -33,7 +33,8 @@ G_BEGIN_DECLS #define NM_IS_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFCFG_CONNECTION)) #define NM_IFCFG_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass)) -#define NM_IFCFG_CONNECTION_UNMANAGED "unmanaged" +#define NM_IFCFG_CONNECTION_UNMANAGED_SPEC "unmanaged-spec" +#define NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC "unrecognized-spec" typedef struct { NMSettingsConnection parent; @@ -56,6 +57,7 @@ void nm_ifcfg_connection_set_path (NMIfcfgConnection *self, const char *ifcfg_path); const char *nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self); +const char *nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self); gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self, GHashTable *new_settings, diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 64591e01ce..c51afbee39 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -163,6 +163,9 @@ _internal_new_connection (SCPluginIfcfg *self, device_id = spec; PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' / device '%s' " "due to NM_CONTROLLED=no.", cid, device_id); + } else if (nm_ifcfg_connection_get_unrecognized_spec (connection)) { + PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' " + "of unrecognized type.", cid); } /* watch changes of ifcfg hardlinks */ @@ -178,21 +181,24 @@ static void remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); - gboolean managed = FALSE; + gboolean unmanaged, unrecognized; g_return_if_fail (self != NULL); g_return_if_fail (connection != NULL); - managed = !nm_ifcfg_connection_get_unmanaged_spec (connection); + unmanaged = !!nm_ifcfg_connection_get_unmanaged_spec (connection); + unrecognized = !!nm_ifcfg_connection_get_unrecognized_spec (connection); g_object_ref (connection); g_hash_table_remove (priv->connections, nm_connection_get_uuid (NM_CONNECTION (connection))); nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); - /* Emit unmanaged changes _after_ removing the connection */ - if (managed == FALSE) + /* Emit changes _after_ removing the connection */ + if (unmanaged) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + if (unrecognized) + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); } static NMIfcfgConnection * @@ -238,6 +244,8 @@ connection_new_or_changed (SCPluginIfcfg *self, GError *error = NULL; gboolean ignore_error = FALSE; const char *new_unmanaged = NULL, *old_unmanaged = NULL; + const char *new_unrecognized = NULL, *old_unrecognized = NULL; + gboolean unmanaged_changed, unrecognized_changed; g_return_if_fail (self != NULL); g_return_if_fail (path != NULL); @@ -261,12 +269,12 @@ connection_new_or_changed (SCPluginIfcfg *self, /* New connection */ new = _internal_new_connection (self, path, NULL, NULL); if (new) { - if (nm_ifcfg_connection_get_unmanaged_spec (new)) { + if (nm_ifcfg_connection_get_unmanaged_spec (new)) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); - } else { - /* Only managed connections are announced to the settings service */ + else if (nm_ifcfg_connection_get_unrecognized_spec (new)) + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); + else g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new); - } } return; } @@ -289,25 +297,30 @@ connection_new_or_changed (SCPluginIfcfg *self, old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing)); new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new)); + unmanaged_changed = g_strcmp0 (old_unmanaged, new_unmanaged); - /* When interface is unmanaged or the connections and unmanaged specs are the same - * there's nothing to do */ - if ( (g_strcmp0 (old_unmanaged, new_unmanaged) == 0 && new_unmanaged != NULL) - || ( nm_connection_compare (NM_CONNECTION (existing), - NM_CONNECTION (new), - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) - && g_strcmp0 (old_unmanaged, new_unmanaged) == 0)) { + old_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (existing)); + new_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (new)); + unrecognized_changed = g_strcmp0 (old_unrecognized, new_unrecognized); + if ( !unmanaged_changed + && !unrecognized_changed + && nm_connection_compare (NM_CONNECTION (existing), + NM_CONNECTION (new), + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { g_object_unref (new); return; } PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path); - g_object_set (existing, NM_IFCFG_CONNECTION_UNMANAGED, new_unmanaged, NULL); + g_object_set (existing, + NM_IFCFG_CONNECTION_UNMANAGED_SPEC, new_unmanaged, + NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized, + NULL); - if (new_unmanaged) { - if (!old_unmanaged) { + if (new_unmanaged || new_unrecognized) { + if (!old_unmanaged && !old_unrecognized) { g_object_ref (existing); /* Unexport the connection by telling the settings service it's * been removed. @@ -325,12 +338,16 @@ connection_new_or_changed (SCPluginIfcfg *self, existing); } } else { - if (old_unmanaged) { /* now managed */ - const char *cid = nm_connection_get_id (NM_CONNECTION (new)); + const char *cid = nm_connection_get_id (NM_CONNECTION (new)); + if (old_unmanaged /* && !new_unmanaged */) { PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' and its " "device because NM_CONTROLLED was true.", cid); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing); + } else if (old_unrecognized /* && !new_unrecognized */) { + PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' " + "because it is now a recognized type.", cid); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing); } if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (existing), @@ -343,8 +360,10 @@ connection_new_or_changed (SCPluginIfcfg *self, } g_object_unref (new); - if (g_strcmp0 (old_unmanaged, new_unmanaged)) + if (unmanaged_changed) g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + if (unrecognized_changed) + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); } static void @@ -482,7 +501,8 @@ get_connections (NMSystemConfigInterface *config) g_hash_table_iter_init (&iter, priv->connections); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) { - if (!nm_ifcfg_connection_get_unmanaged_spec (connection)) + if ( !nm_ifcfg_connection_get_unmanaged_spec (connection) + && !nm_ifcfg_connection_get_unrecognized_spec (connection)) list = g_slist_prepend (list, connection); } @@ -498,18 +518,19 @@ reload_connections (NMSystemConfigInterface *config) } static GSList * -get_unmanaged_specs (NMSystemConfigInterface *config) +get_unhandled_specs (NMSystemConfigInterface *config, + const char *property) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config); GSList *list = NULL, *list_iter; GHashTableIter iter; - NMIfcfgConnection *connection; - const char *spec; + gpointer connection; + char *spec; gboolean found; g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) { - spec = nm_ifcfg_connection_get_unmanaged_spec (connection); + while (g_hash_table_iter_next (&iter, NULL, &connection)) { + g_object_get (connection, property, &spec, NULL); if (spec) { /* Ignore duplicates */ for (list_iter = list, found = FALSE; list_iter; list_iter = g_slist_next (list_iter)) { @@ -518,13 +539,27 @@ get_unmanaged_specs (NMSystemConfigInterface *config) break; } } - if (!found) - list = g_slist_prepend (list, g_strdup (spec)); + if (found) + g_free (spec); + else + list = g_slist_prepend (list, spec); } } return list; } +static GSList * +get_unmanaged_specs (NMSystemConfigInterface *config) +{ + return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNMANAGED_SPEC); +} + +static GSList * +get_unrecognized_specs (NMSystemConfigInterface *config) +{ + return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC); +} + static NMSettingsConnection * add_connection (NMSystemConfigInterface *config, NMConnection *connection, @@ -678,7 +713,9 @@ impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin, } connection = find_by_path (plugin, in_ifcfg); - if (!connection || nm_ifcfg_connection_get_unmanaged_spec (connection)) { + if ( !connection + || nm_ifcfg_connection_get_unmanaged_spec (connection) + || nm_ifcfg_connection_get_unrecognized_spec (connection)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -930,6 +967,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c system_config_interface_class->add_connection = add_connection; system_config_interface_class->reload_connections = reload_connections; system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs; + system_config_interface_class->get_unrecognized_specs = get_unrecognized_specs; system_config_interface_class->init = init; } diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index bf85246e5f..272f9b4252 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -4739,34 +4739,53 @@ vlan_connection_from_ifcfg (const char *file, return connection; } -static char * -get_unmanaged_spec (shvarFile *ifcfg) +static NMConnection * +create_unhandled_connection (const char *filename, shvarFile *ifcfg, + const char *type, char **out_spec) { - char *value, *unmanaged; + NMConnection *connection; + NMSetting *s_con; + char *value; + g_assert (out_spec != NULL); + + connection = nm_connection_new (); + + /* Get NAME, UUID, etc. We need to set a connection type (generic) and add + * an empty type-specific setting as well, to make sure it passes + * nm_connection_verify() later. + */ + s_con = make_connection_setting (filename, ifcfg, NM_SETTING_GENERIC_SETTING_NAME, + NULL, NULL); + nm_connection_add_setting (connection, s_con); + + nm_connection_add_setting (connection, nm_setting_generic_new ()); + + /* Get a spec */ value = svGetValue (ifcfg, "HWADDR", FALSE); if (value) { char *lower = g_ascii_strdown (value, -1); - unmanaged = g_strdup_printf ("mac:%s", lower); + *out_spec = g_strdup_printf ("%s:mac:%s", type, lower); g_free (lower); g_free (value); - return unmanaged; + return connection; } value = svGetValue (ifcfg, "SUBCHANNELS", FALSE); if (value) { - unmanaged = g_strdup_printf ("s390-subchannels:%s", value); + *out_spec = g_strdup_printf ("%s:s390-subchannels:%s", type, value); g_free (value); - return unmanaged; + return connection; } value = svGetValue (ifcfg, "DEVICE", FALSE); if (value) { - unmanaged = g_strdup_printf ("interface-name:%s", value); + *out_spec = g_strdup_printf ("%s:interface-name:%s", type, value); g_free (value); - return unmanaged; + return connection; } + g_object_unref (connection); return NULL; } @@ -4832,7 +4851,7 @@ connection_from_file (const char *filename, const char *network_file, /* for unit tests only */ const char *test_type, /* for unit tests only */ const char *iscsiadm_path, /* for unit tests only */ - char **out_unmanaged, + char **out_unhandled, char **out_keyfile, char **out_routefile, char **out_route6file, @@ -4846,8 +4865,8 @@ connection_from_file (const char *filename, const char *ifcfg_name = NULL; g_return_val_if_fail (filename != NULL, NULL); - if (out_unmanaged) - g_return_val_if_fail (*out_unmanaged == NULL, NULL); + if (out_unhandled) + g_return_val_if_fail (*out_unhandled == NULL, NULL); if (out_keyfile) g_return_val_if_fail (*out_keyfile == NULL, NULL); if (out_routefile) @@ -4877,22 +4896,11 @@ connection_from_file (const char *filename, } if (!svTrueValue (parsed, "NM_CONTROLLED", TRUE)) { - NMSetting *s_con; + g_assert (out_unhandled != NULL); - g_assert (out_unmanaged != NULL); - - connection = nm_connection_new (); - - /* Get NAME, UUID, etc. We need to set a connection type (generic) and add - * an empty type-specific setting as well, to make sure it passes - * nm_connection_verify() later. - */ - s_con = make_connection_setting (filename, parsed, NM_SETTING_GENERIC_SETTING_NAME, - NULL, NULL); - nm_connection_add_setting (connection, s_con); - nm_connection_add_setting (connection, nm_setting_generic_new ()); - - *out_unmanaged = get_unmanaged_spec (parsed); + connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); + if (!connection) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed"); goto done; } @@ -4977,7 +4985,12 @@ connection_from_file (const char *filename, else if (!strcasecmp (type, TYPE_BRIDGE)) connection = bridge_connection_from_ifcfg (filename, parsed, error); else { - g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Unknown connection type '%s'", type); + g_assert (out_unhandled != NULL); + + connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled); + if (!connection) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: connection type was unrecognized but device was not uniquely identified; device may be managed"); + goto done; } g_free (type); diff --git a/src/settings/plugins/ifcfg-rh/reader.h b/src/settings/plugins/ifcfg-rh/reader.h index 7305f96ca3..371f4504f8 100644 --- a/src/settings/plugins/ifcfg-rh/reader.h +++ b/src/settings/plugins/ifcfg-rh/reader.h @@ -30,7 +30,7 @@ NMConnection *connection_from_file (const char *filename, const char *network_file, /* for unit tests only */ const char *test_type, /* for unit tests only */ const char *iscsiadm_path, /* for unit tests only */ - char **out_unmanaged, + char **out_unhandled, char **out_keyfile, char **out_routefile, char **out_route6file, diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index 43352ec1a5..a7d009eeb6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -3,6 +3,7 @@ EXTRA_DIST = \ ifcfg-test-variables-corner-cases-1 \ ifcfg-test-nm-controlled \ ifcfg-test-nm-controlled-unrecognized \ + ifcfg-test-unrecognized \ ifcfg-test-wired-static \ ifcfg-test-wired-static-bootproto \ ifcfg-test-wired-dhcp \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized new file mode 100644 index 0000000000..18da66c1d7 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized @@ -0,0 +1,7 @@ +TYPE=PPP-over-InfiniBand +NAME=U Can't Touch This +DEVICE=pppoipoib0 +HWADDR=00:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes + diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 195bbe3b17..14c4fb9f72 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -293,7 +293,7 @@ test_read_unmanaged (void) { NMConnection *connection; NMSettingConnection *s_con; - char *unmanaged = NULL; + char *unhandled_spec = NULL; GError *error = NULL; const char *expected_id = "System test-nm-controlled"; guint64 expected_timestamp = 0; @@ -301,14 +301,14 @@ test_read_unmanaged (void) connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled", NULL, TYPE_ETHERNET, NULL, - &unmanaged, + &unhandled_spec, NULL, NULL, NULL, &error, NULL); g_assert_no_error (error); g_assert (connection); success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - g_assert_cmpstr (unmanaged, ==, "mac:00:11:22:33:f8:9f"); + g_assert_cmpstr (unhandled_spec, ==, "unmanaged:mac:00:11:22:33:f8:9f"); /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); @@ -317,7 +317,7 @@ test_read_unmanaged (void) g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp); g_assert (nm_setting_connection_get_autoconnect (s_con)); - g_free (unmanaged); + g_free (unhandled_spec); g_object_unref (connection); } @@ -326,7 +326,7 @@ test_read_unmanaged_unrecognized (void) { NMConnection *connection; NMSettingConnection *s_con; - char *unmanaged = NULL; + char *unhandled_spec = NULL; GError *error = NULL; const char *expected_id = "PigeonNet"; guint64 expected_timestamp = 0; @@ -334,14 +334,45 @@ test_read_unmanaged_unrecognized (void) connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled-unrecognized", NULL, NULL, NULL, - &unmanaged, + &unhandled_spec, NULL, NULL, NULL, &error, NULL); g_assert_no_error (error); g_assert (connection); success = nm_connection_verify (connection, &error); g_assert_no_error (error); g_assert (success); - g_assert_cmpstr (unmanaged, ==, "interface-name:ipoac0"); + g_assert_cmpstr (unhandled_spec, ==, "unmanaged:interface-name:ipoac0"); + + /* ===== CONNECTION SETTING ===== */ + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id); + g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp); + + g_object_unref (connection); +} + +static void +test_read_unrecognized (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + char *unhandled_spec = NULL; + GError *error = NULL; + const char *expected_id = "U Can't Touch This"; + guint64 expected_timestamp = 0; + gboolean success; + + connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-unrecognized", + NULL, NULL, NULL, + &unhandled_spec, + NULL, NULL, NULL, &error, NULL); + g_assert_no_error (error); + g_assert (connection); + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + g_assert_cmpstr (unhandled_spec, ==, "unrecognized:mac:00:11:22:33"); /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); @@ -13169,6 +13200,7 @@ int main (int argc, char **argv) g_test_add_func (TPATH "unmanaged", test_read_unmanaged); g_test_add_func (TPATH "unmanaged-unrecognized", test_read_unmanaged_unrecognized); + g_test_add_func (TPATH "unrecognized", test_read_unrecognized); g_test_add_func (TPATH "basic", test_read_basic); g_test_add_func (TPATH "variables-corner-cases", test_read_variables_corner_cases); g_test_add_data_func (TPATH "no-prefix/8", GUINT_TO_POINTER (8), test_read_wired_static_no_prefix);