core: allow marking a device unmanaged by its interface name

Virtual devices often don't have stable hardware addresses. So allow
for marking a device unmanaged via its interface name instead.

https://bugzilla.gnome.org/show_bug.cgi?id=693684
This commit is contained in:
Dan Winship
2013-02-12 18:00:48 -05:00
parent 611df342af
commit c308e75b92
8 changed files with 90 additions and 56 deletions

View File

@@ -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)) {
matched = nm_match_spec_string (specs, hwaddr_match);
g_free (hwaddr_match);
return TRUE;
}
}
return matched;
}
g_free (hwaddr_match);
return FALSE;
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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -33,6 +33,7 @@
#include <nm-connection.h>
#include <nm-setting.h>
#include <nm-setting-connection.h>
#include <nm-utils.h>
#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:

View File

@@ -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);

View File

@@ -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 *

View File

@@ -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;
}

View File

@@ -34,6 +34,7 @@
#include <nm-connection.h>
#include <nm-setting.h>
#include <nm-setting-connection.h>
#include <nm-utils.h>
#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]);