diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index f2d72bd15..d9dad97e5 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -363,11 +363,24 @@ nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting) nm_ip6_config_set_never_default (ip6_config, TRUE); } +static gboolean +nm_match_spec_string (const GSList *specs, const char *match) +{ + const GSList *iter; + + for (iter = specs; iter; iter = g_slist_next (iter)) { + if (!strcmp ((const char *) iter->data, match)) + return TRUE; + } + + return FALSE; +} + gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) { - const GSList *iter; char *hwaddr_match, *p; + gboolean matched; g_return_val_if_fail (hwaddr != NULL, FALSE); @@ -378,15 +391,23 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) p++; } - for (iter = specs; iter; iter = g_slist_next (iter)) { - if (!strcmp ((const char *) iter->data, hwaddr_match)) { - g_free (hwaddr_match); - return TRUE; - } - } - + matched = nm_match_spec_string (specs, hwaddr_match); g_free (hwaddr_match); - return FALSE; + return matched; +} + +gboolean +nm_match_spec_interface_name (const GSList *specs, const char *interface_name) +{ + char *iface_match; + gboolean matched; + + g_return_val_if_fail (interface_name != NULL, FALSE); + + iface_match = g_strdup_printf ("interface-name:%s", interface_name); + matched = nm_match_spec_string (specs, iface_match); + g_free (iface_match); + return matched; } #define BUFSIZE 10 diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 057ad283f..1e6a4e287 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -41,6 +41,7 @@ void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *set gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr); gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels); +gboolean nm_match_spec_interface_name (const GSList *specs, const char *interface_name); const char *nm_utils_get_shared_wifi_permission (NMConnection *connection); diff --git a/src/nm-device.c b/src/nm-device.c index 1b52a573c..9d76e0c16 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -5504,6 +5504,9 @@ spec_match_list (NMDevice *device, const GSList *specs) matched = nm_match_spec_hwaddr (specs, hwaddr_str); g_free (hwaddr_str); + if (!matched) + matched = nm_match_spec_interface_name (specs, nm_device_get_iface (device)); + return matched; } diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c index 05ac9290a..9f99a4f44 100644 --- a/src/settings/plugins/example/plugin.c +++ b/src/settings/plugins/example/plugin.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "plugin.h" #include "nm-system-config-interface.h" @@ -521,8 +522,9 @@ add_connection (NMSystemConfigInterface *config, /* This function returns a list of "unmanaged device specs" which represent * a list of devices that NetworkManager should not manage. Each unmanaged * spec item has a specific format starting with a "tag" and followed by - * tag-specific data. The only currently specified item is "mac:" followed - * by the MAC address of the interface NM should not manage. This function + * tag-specific data. The only currently specified items are "mac:" followed + * by the MAC address of the interface NM should not manage, or "interface-name:" + * followed by the name of the interface NM should not manage. This function * reads the list of unmanaged devices from wherever the plugin wants to * store them and returns that list to NetworkManager. */ @@ -533,7 +535,7 @@ get_unmanaged_specs (NMSystemConfigInterface *config) GKeyFile *key_file; GSList *specs = NULL; GError *error = NULL; - char *str, **macs; + char *str, **ids; int i; if (!priv->conf_file) @@ -551,11 +553,11 @@ get_unmanaged_specs (NMSystemConfigInterface *config) if (!str) goto out; - macs = g_strsplit (str, ";", -1); - for (i = 0; macs[i] != NULL; i++) { + ids = g_strsplit (str, ";", -1); + for (i = 0; ids[i] != NULL; i++) { /* Verify unmanaged specification and add it to the list */ - if (strlen (macs[i]) > 4 && !strncmp (macs[i], "mac:", 4) && ether_aton (macs[i] + 4)) { - char *p = macs[i]; + if (!strncmp (ids[i], "mac:", 4) && ether_aton (ids[i] + 4)) { + char *p = ids[i]; /* To accept uppercase MACs in configuration file, we have to * convert values to lowercase here. Unmanaged MACs in specs are @@ -566,14 +568,16 @@ get_unmanaged_specs (NMSystemConfigInterface *config) p++; } - specs = g_slist_append (specs, macs[i]); + specs = g_slist_append (specs, ids[i]); + } else if (!strncmp (ids[i], "interface-name:", 10) && nm_utils_iface_valid_name (ids[i] + 10)) { + specs = g_slist_append (specs, ids[i]); } else { - g_warning ("Error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, macs[i]); - g_free (macs[i]); + g_warning ("Error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, ids[i]); + g_free (ids[i]); } } - g_free (macs); /* Yes, g_free, not g_strfreev because we need the strings in the list */ + g_free (ids); /* Yes, g_free, not g_strfreev because we need the strings in the list */ g_free (str); out: diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 567b90728..029c2f427 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -2971,7 +2971,6 @@ make_wireless_setting (shvarFile *ifcfg, if (array) { g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, array, NULL); - /* A connection can only be unmanaged if we know the MAC address */ if (!nm_controlled) { *unmanaged = g_strdup_printf ("mac:%02x:%02x:%02x:%02x:%02x:%02x", array->data[0], array->data[1], array->data[2], @@ -2979,11 +2978,6 @@ make_wireless_setting (shvarFile *ifcfg, } g_byte_array_free (array, TRUE); - } else if (!nm_controlled) { - /* If NM_CONTROLLED=no but there wasn't a MAC address, notify - * the user that the device cannot be unmanaged. - */ - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed"); } } else { g_object_unref (s_wireless); @@ -3296,7 +3290,6 @@ make_wired_setting (shvarFile *ifcfg, if (mac) { g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); - /* A connection can only be unmanaged if we know the MAC address */ if (!nm_controlled) { *unmanaged = g_strdup_printf ("mac:%02x:%02x:%02x:%02x:%02x:%02x", mac->data[0], mac->data[1], mac->data[2], @@ -3395,13 +3388,6 @@ make_wired_setting (shvarFile *ifcfg, } g_free (value); - if (!nm_controlled && !*unmanaged) { - /* If NM_CONTROLLED=no but there wasn't a MAC address or z/VM - * subchannels, notify the user that the device cannot be unmanaged. - */ - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR or SUBCHANNELS was missing; device will be managed"); - } - mac = NULL; if (read_mac_address (ifcfg, "MACADDR", ARPHRD_ETHER, &mac, error)) { if (mac) { @@ -3542,7 +3528,6 @@ make_infiniband_setting (shvarFile *ifcfg, if (mac) { g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); - /* A connection can only be unmanaged if we know the MAC address */ if (!nm_controlled) { char *mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND); *unmanaged = g_strdup_printf ("mac:%s", mac_str); @@ -3561,13 +3546,6 @@ make_infiniband_setting (shvarFile *ifcfg, else g_object_set (s_infiniband, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); - if (!nm_controlled && !*unmanaged) { - /* If NM_CONTROLLED=no but there wasn't a MAC address, notify - the user that the device cannot be unmanaged. - */ - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed"); - } - value = svGetValue(ifcfg, "CARRIER_DETECT", FALSE); if (!value || !strlen (value)) { g_free (value); @@ -4189,6 +4167,25 @@ vlan_connection_from_ifcfg (const char *file, return connection; } +static void +ensure_unmanaged (shvarFile *ifcfg, + char **unmanaged) +{ + char *value; + + if (*unmanaged) + return; + + value = svGetValue (ifcfg, "DEVICE", FALSE); + if (value) { + *unmanaged = g_strdup_printf ("interface-name:%s", value); + g_free (value); + return; + } + + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed"); +} + NMConnection * connection_from_file (const char *filename, const char *network_file, /* for unit tests only */ @@ -4325,10 +4322,8 @@ connection_from_file (const char *filename, "Unknown connection type '%s'", type); } - if (nm_controlled) { - g_free (*unmanaged); - *unmanaged = NULL; - } + if (!nm_controlled) + ensure_unmanaged (parsed, unmanaged); g_free (type); diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c index 81a4dbcdd..76bcb9757 100644 --- a/src/settings/plugins/ifnet/plugin.c +++ b/src/settings/plugins/ifnet/plugin.c @@ -374,25 +374,29 @@ check_unmanaged (gpointer key, gpointer data, gpointer user_data) { GSList **list = (GSList **) user_data; gchar *conn_name = (gchar *) key; - const char *unmanaged_spec; + const char *mac; + char *unmanaged_spec; GSList *iter; if (is_managed (conn_name)) return; PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Checking unmanaged: %s", conn_name); - unmanaged_spec = ifnet_get_data (conn_name, "mac"); - if (!unmanaged_spec) - return; + mac = ifnet_get_data (conn_name, "mac"); + if (mac) + unmanaged_spec = g_strdup_printf ("mac:%s", mac); + else + unmanaged_spec = g_strdup_printf ("interface-name:%s", conn_name); /* Just return if the unmanaged spec is already in the list */ for (iter = *list; iter; iter = g_slist_next (iter)) { - if (!strcmp ((char *) iter->data, unmanaged_spec)) + if (!strcmp ((char *) iter->data, unmanaged_spec)) { + g_free (unmanaged_spec); return; + } } PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Add unmanaged: %s", unmanaged_spec); - *list = - g_slist_prepend (*list, g_strdup_printf ("mac:%s", unmanaged_spec)); + *list = g_slist_prepend (*list, unmanaged_spec); } static GSList * diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c index 4979c7649..ebf14d25e 100644 --- a/src/settings/plugins/ifupdown/plugin.c +++ b/src/settings/plugins/ifupdown/plugin.c @@ -535,7 +535,7 @@ SCPluginIfupdown_get_unmanaged_specs (NMSystemConfigInterface *config) SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config); GSList *specs = NULL; GHashTableIter iter; - gpointer value; + gpointer key, value; if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) return NULL; @@ -544,13 +544,16 @@ SCPluginIfupdown_get_unmanaged_specs (NMSystemConfigInterface *config) g_hash_table_size (priv->well_known_ifaces)); g_hash_table_iter_init (&iter, priv->well_known_ifaces); - while (g_hash_table_iter_next (&iter, NULL, &value)) { + while (g_hash_table_iter_next (&iter, &key, &value)) { GUdevDevice *device = G_UDEV_DEVICE (value); + const char *iface = key; const char *address; address = g_udev_device_get_sysfs_attr (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; } diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 69c6a4232..21ff114ff 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "plugin.h" #include "nm-system-config-interface.h" @@ -455,7 +456,7 @@ get_unmanaged_specs (NMSystemConfigInterface *config) for (i = 0; udis[i] != NULL; i++) { /* Verify unmanaged specification and add it to the list */ - if (strlen (udis[i]) > 4 && !strncmp (udis[i], "mac:", 4) && ether_aton (udis[i] + 4)) { + if (!strncmp (udis[i], "mac:", 4) && ether_aton (udis[i] + 4)) { char *p = udis[i]; /* To accept uppercase MACs in configuration file, we have to convert values to lowercase here. @@ -465,6 +466,8 @@ get_unmanaged_specs (NMSystemConfigInterface *config) p++; } specs = g_slist_append (specs, udis[i]); + } else if (!strncmp (udis[i], "interface-name:", 10) && nm_utils_iface_valid_name (udis[i] + 10)) { + specs = g_slist_append (specs, udis[i]); } else { g_warning ("Error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, udis[i]); g_free (udis[i]);