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:
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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 *
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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]);
|
||||
|
Reference in New Issue
Block a user