device: merge branch 'th/preserve-fake-perm-hwaddr-bgo772880'

https://bugzilla.gnome.org/show_bug.cgi?id=772880
https://bugzilla.redhat.com/show_bug.cgi?id=1388286
This commit is contained in:
Thomas Haller 2016-10-28 17:16:26 +02:00
commit e2b7da7b82
15 changed files with 516 additions and 286 deletions

View file

@ -124,7 +124,10 @@ guint32 _nm_setting_get_setting_priority (NMSetting *setting);
gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value);
guint _nm_utils_hwaddr_length (const char *asc);
#define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3)
guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length);
const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len);
char *_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case);

View file

@ -2995,17 +2995,64 @@ nm_utils_wifi_strength_bars (guint8 strength)
gsize
nm_utils_hwaddr_len (int type)
{
g_return_val_if_fail (type == ARPHRD_ETHER || type == ARPHRD_INFINIBAND, 0);
if (type == ARPHRD_ETHER)
return ETH_ALEN;
else if (type == ARPHRD_INFINIBAND)
return INFINIBAND_ALEN;
g_assert_not_reached ();
g_return_val_if_reached (0);
}
#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
static guint8 *
hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_len)
{
const char *in = asc;
guint8 *out = buffer;
guint8 delimiter = '\0';
nm_assert (asc);
nm_assert (buffer);
nm_assert (buffer_length);
nm_assert (out_len);
while (TRUE) {
const guint8 d1 = in[0];
guint8 d2;
if (!g_ascii_isxdigit (d1))
return NULL;
#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - ('A' - 10))
/* If there's no leading zero (ie "aa:b:cc") then fake it */
d2 = in[1];
if (d2 && g_ascii_isxdigit (d2)) {
*out++ = (HEXVAL (d1) << 4) + HEXVAL (d2);
d2 = in[2];
in += 3;
} else {
/* Fake leading zero */
*out++ = HEXVAL (d1);
in += 2;
}
if (!d2)
break;
if (--buffer_length == 0)
return NULL;
if (d2 != delimiter) {
if ( delimiter == '\0'
&& (d2 == ':' || d2 == '-'))
delimiter = d2;
else
return NULL;
}
}
*out_len = out - buffer;
return buffer;
}
/**
* nm_utils_hwaddr_atoba:
@ -3022,18 +3069,52 @@ GByteArray *
nm_utils_hwaddr_atoba (const char *asc, gsize length)
{
GByteArray *ba;
gsize l;
g_return_val_if_fail (asc != NULL, NULL);
g_return_val_if_fail (asc, NULL);
g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL);
ba = g_byte_array_sized_new (length);
g_byte_array_set_size (ba, length);
if (!nm_utils_hwaddr_aton (asc, ba->data, length)) {
g_byte_array_unref (ba);
return NULL;
}
if (!hwaddr_aton (asc, ba->data, length, &l))
goto fail;
if (length != l)
goto fail;
return ba;
fail:
g_byte_array_unref (ba);
return NULL;
}
/**
* _nm_utils_hwaddr_aton:
* @asc: the ASCII representation of a hardware address
* @buffer: buffer to store the result into. Must have
* at least a size of @buffer_length.
* @buffer_length: the length of the input buffer @buffer.
* The result must fit into that buffer, otherwise
* the function fails and returns %NULL.
* @out_length: the output length in case of success.
*
* Parses @asc and converts it to binary form in @buffer.
* Bytes in @asc can be sepatared by colons (:), or hyphens (-), but not mixed.
*
* It is like nm_utils_hwaddr_aton(), but contrary to that it
* can parse addresses of any length. That is, you don't need
* to know the length before-hand.
*
* Return value: @buffer, or %NULL if @asc couldn't be parsed.
*/
guint8 *
_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length)
{
g_return_val_if_fail (asc, NULL);
g_return_val_if_fail (buffer, NULL);
g_return_val_if_fail (buffer_length > 0, NULL);
g_return_val_if_fail (out_length, NULL);
return hwaddr_aton (asc, buffer, buffer_length, out_length);
}
/**
@ -3052,72 +3133,55 @@ nm_utils_hwaddr_atoba (const char *asc, gsize length)
guint8 *
nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length)
{
const char *in = asc;
guint8 *out = (guint8 *)buffer;
char delimiter = '\0';
gsize l;
g_return_val_if_fail (asc != NULL, NULL);
g_return_val_if_fail (buffer != NULL, NULL);
g_return_val_if_fail (asc, NULL);
g_return_val_if_fail (buffer, NULL);
g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL);
while (length && *in) {
guint8 d1 = in[0], d2 = in[1];
if (!hwaddr_aton (asc, buffer, length, &l))
return NULL;
if (length != l)
return NULL;
return buffer;
}
if (!g_ascii_isxdigit (d1))
return NULL;
static void
_bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out)
{
const guint8 *in = addr;
const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef";
/* If there's no leading zero (ie "aa:b:cc") then fake it */
if (d2 && g_ascii_isxdigit (d2)) {
*out++ = (HEXVAL (d1) << 4) + HEXVAL (d2);
in += 2;
} else {
/* Fake leading zero */
*out++ = (HEXVAL ('0') << 4) + HEXVAL (d1);
in += 1;
}
nm_assert (addr);
nm_assert (out);
nm_assert (length > 0);
/* @out must contain at least @length*3 bytes */
for (;;) {
const guint8 v = *in++;
*out++ = LOOKUP[v >> 4];
*out++ = LOOKUP[v & 0x0F];
length--;
if (*in) {
if (delimiter == '\0') {
if (*in == ':' || *in == '-')
delimiter = *in;
else
return NULL;
} else {
if (*in != delimiter)
return NULL;
}
in++;
}
if (!length)
break;
*out++ = ':';
}
if (length == 0 && !*in)
return buffer;
else
return NULL;
*out = 0;
}
static char *
_bin2str (gconstpointer addr, gsize length, gboolean upper_case)
{
const guint8 *in = addr;
char *out, *result;
const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef";
char *result;
g_return_val_if_fail (addr != NULL, g_strdup (""));
g_return_val_if_fail (length > 0, g_strdup (""));
nm_assert (addr);
nm_assert (length > 0);
result = out = g_malloc (length * 3);
while (length--) {
guint8 v = *in++;
*out++ = LOOKUP[v >> 4];
*out++ = LOOKUP[v & 0x0F];
if (length)
*out++ = ':';
}
*out = 0;
result = g_malloc (length * 3);
_bin2str_buf (addr, length, upper_case, result);
return result;
}
@ -3133,9 +3197,25 @@ _bin2str (gconstpointer addr, gsize length, gboolean upper_case)
char *
nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length)
{
g_return_val_if_fail (addr, g_strdup (""));
g_return_val_if_fail (length > 0, g_strdup (""));
return _bin2str (addr, length, TRUE);
}
const char *
nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len)
{
g_return_val_if_fail (addr, NULL);
g_return_val_if_fail (addr_len > 0, NULL);
g_return_val_if_fail (buf, NULL);
if (buf_len < addr_len * 3)
g_return_val_if_reached (NULL);
_bin2str_buf (addr, addr_len, TRUE, buf);
return buf;
}
/**
* _nm_utils_bin2str:
* @addr: (type guint8) (array length=length): a binary hardware address
@ -3149,51 +3229,12 @@ nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length)
char *
_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case)
{
g_return_val_if_fail (addr, g_strdup (""));
g_return_val_if_fail (length > 0, g_strdup (""));
return _bin2str (addr, length, upper_case);
}
static int
hwaddr_binary_len (const char *asc)
{
int octets = 1;
if (!*asc)
return 0;
for (; *asc; asc++) {
if (*asc == ':' || *asc == '-')
octets++;
}
return octets;
}
/**
* _nm_utils_hwaddr_length:
* @asc: the ASCII representation of the hardware address
*
* Validates that @asc is a valid representation of a hardware
* address up to (including) %NM_UTILS_HWADDR_LEN_MAX bytes.
*
* Returns: binary length of the hardware address @asc or
* 0 on error.
*/
guint
_nm_utils_hwaddr_length (const char *asc)
{
int l;
if (!asc)
return 0;
l = hwaddr_binary_len (asc);
if (l <= 0 || l > NM_UTILS_HWADDR_LEN_MAX)
return 0;
if (!nm_utils_hwaddr_valid (asc, l))
return 0;
return l;
}
/**
* nm_utils_hwaddr_valid:
* @asc: the ASCII representation of a hardware address
@ -3210,17 +3251,18 @@ gboolean
nm_utils_hwaddr_valid (const char *asc, gssize length)
{
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
gsize l;
g_return_val_if_fail (asc != NULL, FALSE);
g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), FALSE);
if (length == -1) {
length = hwaddr_binary_len (asc);
if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX)
if (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX) {
if (!hwaddr_aton (asc, buf, length, &l))
return FALSE;
}
return nm_utils_hwaddr_aton (asc, buf, length) != NULL;
return length == l;
} else if (length == -1) {
return !!hwaddr_aton (asc, buf, sizeof (buf), &l);
} else
g_return_val_if_reached (FALSE);
}
/**
@ -3240,20 +3282,23 @@ char *
nm_utils_hwaddr_canonical (const char *asc, gssize length)
{
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
gsize l;
g_return_val_if_fail (asc != NULL, NULL);
g_return_val_if_fail (asc, NULL);
g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), NULL);
if (length == -1) {
length = hwaddr_binary_len (asc);
if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX)
if (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX) {
if (!hwaddr_aton (asc, buf, length, &l))
return NULL;
}
if (l != length)
return NULL;
} else if (length == -1) {
if (!hwaddr_aton (asc, buf, NM_UTILS_HWADDR_LEN_MAX, &l))
return NULL;
} else
g_return_val_if_reached (NULL);
if (nm_utils_hwaddr_aton (asc, buf, length) == NULL)
return NULL;
return nm_utils_hwaddr_ntoa (buf, length);
return nm_utils_hwaddr_ntoa (buf, l);
}
/* This is used to possibly canonicalize values passed to MAC address property
@ -3317,17 +3362,17 @@ nm_utils_hwaddr_matches (gconstpointer hwaddr1,
gssize hwaddr2_len)
{
guint8 buf1[NM_UTILS_HWADDR_LEN_MAX], buf2[NM_UTILS_HWADDR_LEN_MAX];
gsize l;
if (hwaddr1_len == -1) {
g_return_val_if_fail (hwaddr1 != NULL, FALSE);
hwaddr1_len = hwaddr_binary_len (hwaddr1);
if (hwaddr1_len == 0 || hwaddr1_len > NM_UTILS_HWADDR_LEN_MAX)
if (!hwaddr_aton (hwaddr1, buf1, sizeof (buf1), &l)) {
g_return_val_if_fail ((hwaddr2_len == -1 && hwaddr2) || (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX), FALSE);
return FALSE;
if (!nm_utils_hwaddr_aton (hwaddr1, buf1, hwaddr1_len))
return FALSE;
}
hwaddr1 = buf1;
hwaddr1_len = l;
} else {
g_return_val_if_fail (hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE);
@ -3340,23 +3385,24 @@ nm_utils_hwaddr_matches (gconstpointer hwaddr1,
if (hwaddr2_len == -1) {
g_return_val_if_fail (hwaddr2 != NULL, FALSE);
if (!nm_utils_hwaddr_aton (hwaddr2, buf2, hwaddr1_len))
if (!hwaddr_aton (hwaddr2, buf2, sizeof (buf2), &l))
return FALSE;
if (l != hwaddr1_len)
return FALSE;
hwaddr2 = buf2;
hwaddr2_len = hwaddr1_len;
} else {
g_return_val_if_fail (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE);
if (hwaddr2_len != hwaddr1_len)
return FALSE;
if (!hwaddr2) {
memset (buf2, 0, hwaddr2_len);
hwaddr2 = buf2;
}
}
if (hwaddr1_len != hwaddr2_len)
return FALSE;
if (hwaddr1_len == INFINIBAND_ALEN) {
hwaddr1 = (guint8 *)hwaddr1 + INFINIBAND_ALEN - 8;
hwaddr2 = (guint8 *)hwaddr2 + INFINIBAND_ALEN - 8;
@ -3372,16 +3418,11 @@ static GVariant *
_nm_utils_hwaddr_to_dbus_impl (const char *str)
{
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
int len;
gsize len;
if (!str)
return NULL;
len = _nm_utils_hwaddr_length (str);
if (len == 0)
return NULL;
if (!nm_utils_hwaddr_aton (str, buf, len))
if (!hwaddr_aton (str, buf, sizeof (buf), &len))
return NULL;
return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, buf, len, 1);

View file

@ -305,9 +305,11 @@ nm_strdup_not_empty (const char *str)
#if NM_MORE_ASSERTS
#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END
#define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END
#else
#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END
#define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END
#endif

View file

@ -394,7 +394,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!match_subchans (self, s_wired, &try_mac))
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device, TRUE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wired_get_mac_address (s_wired);
if (perm_hw_addr) {
if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
@ -1344,6 +1344,7 @@ complete_connection (NMDevice *device,
NMSettingPppoe *s_pppoe;
const char *setting_mac;
const char *perm_hw_addr;
gboolean perm_hw_addr_is_fake;
s_pppoe = nm_connection_get_setting_pppoe (connection);
@ -1371,8 +1372,8 @@ complete_connection (NMDevice *device,
nm_connection_add_setting (connection, NM_SETTING (s_wired));
}
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
if (perm_hw_addr) {
perm_hw_addr = nm_device_get_permanent_hw_address_full (device, TRUE, &perm_hw_addr_is_fake);
if (perm_hw_addr && !perm_hw_addr_is_fake) {
setting_mac = nm_setting_wired_get_mac_address (s_wired);
if (setting_mac) {
/* Make sure the setting MAC (if any) matches the device's permanent MAC */
@ -1408,7 +1409,7 @@ new_default_connection (NMDevice *self)
if (nm_config_get_no_auto_default_for_device (nm_config_get (), self))
return NULL;
perm_hw_addr = nm_device_get_permanent_hw_address (self, TRUE);
perm_hw_addr = nm_device_get_permanent_hw_address (self);
if (!perm_hw_addr)
return NULL;
@ -1468,7 +1469,8 @@ update_connection (NMDevice *device, NMConnection *connection)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device);
NMSettingWired *s_wired = nm_connection_get_setting_wired (connection);
const char *perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
gboolean perm_hw_addr_is_fake;
const char *perm_hw_addr;
const char *mac = nm_device_get_hw_address (device);
const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS;
GHashTableIter iter;
@ -1487,7 +1489,8 @@ update_connection (NMDevice *device, NMConnection *connection)
/* If the device reports a permanent address, use that for the MAC address
* and the current MAC, if different, is the cloned MAC.
*/
if (perm_hw_addr) {
perm_hw_addr = nm_device_get_permanent_hw_address_full (device, TRUE, &perm_hw_addr_is_fake);
if (perm_hw_addr && !perm_hw_addr_is_fake) {
g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL);
mac_prop = NULL;

View file

@ -160,7 +160,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
if (mac) {
hw_addr = nm_device_get_permanent_hw_address (device, TRUE);
hw_addr = nm_device_get_permanent_hw_address (device);
if ( !hw_addr
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
return FALSE;
@ -197,7 +197,7 @@ complete_connection (NMDevice *device,
}
setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
hw_address = nm_device_get_permanent_hw_address (device, TRUE);
hw_address = nm_device_get_permanent_hw_address (device);
if (setting_mac) {
/* Make sure the setting MAC (if any) matches the device's MAC */
if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) {
@ -223,7 +223,7 @@ static void
update_connection (NMDevice *device, NMConnection *connection)
{
NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection);
const char *mac = nm_device_get_permanent_hw_address (device, TRUE);
const char *mac = nm_device_get_permanent_hw_address (device);
const char *transport_mode = "datagram";
int ifindex;

View file

@ -369,7 +369,7 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw
if (!priv->parent)
return !fail_if_no_hwaddr;
parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE);
parent_mac = nm_device_get_permanent_hw_address (priv->parent);
return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
}

View file

@ -384,7 +384,7 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw
if (!priv->parent)
return !fail_if_no_hwaddr;
parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE);
parent_mac = nm_device_get_permanent_hw_address (priv->parent);
return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
}

View file

@ -227,10 +227,18 @@ typedef struct _NMDevicePrivate {
char * iface; /* may change, could be renamed by user */
int ifindex;
guint hw_addr_len;
union {
const guint8 hw_addr_len; /* read-only */
guint8 hw_addr_len_;
};
guint8 /*HwAddrType*/ hw_addr_type;
bool real;
bool real:1;
/* there was a IP config change, but no idle action was scheduled because device
* is still not platform-init */
bool queued_ip4_config_pending:1;
bool queued_ip6_config_pending:1;
char * ip_iface;
int ip_ifindex;
@ -1859,7 +1867,7 @@ device_link_changed (NMDevice *self)
had_hw_addr = (priv->hw_addr != NULL);
nm_device_update_hw_address (self);
got_hw_addr = (!had_hw_addr && priv->hw_addr);
nm_device_update_permanent_hw_address (self);
nm_device_update_permanent_hw_address (self, FALSE);
if (info.name[0] && strcmp (priv->iface, info.name) != 0) {
_LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'",
@ -1871,7 +1879,7 @@ device_link_changed (NMDevice *self)
ip_ifname_changed = !priv->ip_iface;
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT))
nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings));
nm_device_set_unmanaged_by_user_settings (self);
else
update_unmanaged_specs = TRUE;
@ -1950,7 +1958,7 @@ device_link_changed (NMDevice *self)
}
if (update_unmanaged_specs)
nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings));
nm_device_set_unmanaged_by_user_settings (self);
if ( got_hw_addr
&& !priv->up
@ -2320,13 +2328,12 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
_notify (self, PROP_UDI);
}
/* trigger initial ip config change to initialize ip-config */
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
priv->queued_ip4_config_pending = TRUE;
priv->queued_ip6_config_pending = TRUE;
nm_device_update_hw_address (self);
nm_device_update_initial_hw_address (self);
nm_device_update_permanent_hw_address (self);
nm_device_update_permanent_hw_address (self, FALSE);
/* Note: initial hardware address must be read before calling get_ignore_carrier() */
config = nm_config_get ();
@ -2516,11 +2523,6 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
g_clear_pointer (&priv->udi, g_free);
_notify (self, PROP_UDI);
}
if (priv->hw_addr) {
priv->hw_addr_len = 0;
g_clear_pointer (&priv->hw_addr, g_free);
_notify (self, PROP_HW_ADDRESS);
}
if (priv->physical_port_id) {
g_clear_pointer (&priv->physical_port_id, g_free);
_notify (self, PROP_PHYSICAL_PORT_ID);
@ -2529,9 +2531,12 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
nm_clear_g_source (&priv->stats.timeout_id);
_stats_update_counters (self, 0, 0);
priv->hw_addr_len_ = 0;
if (nm_clear_g_free (&priv->hw_addr))
_notify (self, PROP_HW_ADDRESS);
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
g_clear_pointer (&priv->hw_addr_perm, g_free);
_notify (self, PROP_PERM_HW_ADDRESS);
if (nm_clear_g_free (&priv->hw_addr_perm))
_notify (self, PROP_PERM_HW_ADDRESS);
g_clear_pointer (&priv->hw_addr_initial, g_free);
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
@ -7697,6 +7702,7 @@ _cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type)
if (nm_clear_g_source (&priv->queued_ip4_config_id))
_LOGD (LOGD_DEVICE, "clearing queued IP4 config change");
priv->queued_ip4_config_pending = FALSE;
dhcp4_cleanup (self, cleanup_type, FALSE);
arp_cleanup (self);
@ -7713,6 +7719,7 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
if (nm_clear_g_source (&priv->queued_ip6_config_id))
_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
priv->queued_ip6_config_pending = FALSE;
g_clear_object (&priv->dad6_ip6_config);
dhcp6_cleanup (self, cleanup_type, FALSE);
@ -9408,6 +9415,7 @@ update_ip4_config (NMDevice *self, gboolean initial)
&& activation_source_is_scheduled (self,
activate_stage5_ip4_config_commit,
AF_INET)) {
priv->queued_ip4_config_pending = FALSE;
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
_LOGT (LOGD_DEVICE, "IP4 update was postponed");
return;
@ -9498,6 +9506,7 @@ update_ip6_config (NMDevice *self, gboolean initial)
&& activation_source_is_scheduled (self,
activate_stage5_ip6_config_commit,
AF_INET6)) {
priv->queued_ip6_config_pending = FALSE;
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
_LOGT (LOGD_DEVICE, "IP6 update was postponed");
return;
@ -9575,6 +9584,8 @@ queued_ip4_config_change (gpointer user_data)
priv = NM_DEVICE_GET_PRIVATE (self);
nm_assert (!priv->queued_ip4_config_pending);
/* Wait for any queued state changes */
if (priv->queued_state.id)
return TRUE;
@ -9599,6 +9610,8 @@ queued_ip6_config_change (gpointer user_data)
priv = NM_DEVICE_GET_PRIVATE (self);
nm_assert (!priv->queued_ip4_config_pending);
/* Wait for any queued state changes */
if (priv->queued_state.id)
return TRUE;
@ -9678,7 +9691,11 @@ device_ipx_changed (NMPlatform *platform,
switch (obj_type) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
case NMP_OBJECT_TYPE_IP4_ROUTE:
if (!priv->queued_ip4_config_id) {
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
priv->queued_ip4_config_pending = TRUE;
nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id));
} else if (!priv->queued_ip4_config_id) {
priv->queued_ip4_config_pending = FALSE;
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
_LOGD (LOGD_DEVICE, "queued IP4 config change");
}
@ -9695,7 +9712,11 @@ device_ipx_changed (NMPlatform *platform,
}
/* fallthrough */
case NMP_OBJECT_TYPE_IP6_ROUTE:
if (!priv->queued_ip6_config_id) {
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
priv->queued_ip6_config_pending = TRUE;
nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id));
} else if (!priv->queued_ip6_config_id) {
priv->queued_ip6_config_pending = FALSE;
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
_LOGD (LOGD_DEVICE, "queued IP6 config change");
}
@ -9937,6 +9958,33 @@ _set_unmanaged_flags (NMDevice *self,
allow_state_transition = FALSE;
was_managed = allow_state_transition && nm_device_get_managed (self, FALSE);
if ( NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_PLATFORM_INIT)
&& NM_FLAGS_HAS (flags, NM_UNMANAGED_PLATFORM_INIT)
&& NM_IN_SET (set_op, NM_UNMAN_FLAG_OP_SET_MANAGED)) {
/* we are clearing the platform-init flags. This triggers additional actions. */
if (!NM_FLAGS_HAS (flags, NM_UNMANAGED_USER_SETTINGS)) {
gboolean unmanaged;
unmanaged = nm_device_spec_match_list (self,
nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings));
nm_device_set_unmanaged_flags (self,
NM_UNMANAGED_USER_SETTINGS,
!!unmanaged);
}
if (priv->queued_ip4_config_pending) {
priv->queued_ip4_config_pending = FALSE;
nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id));
priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
}
if (priv->queued_ip6_config_pending) {
priv->queued_ip6_config_pending = FALSE;
nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id));
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
}
}
old_flags = priv->unmanaged_flags;
old_mask = priv->unmanaged_mask;
@ -10051,20 +10099,30 @@ nm_device_set_unmanaged_by_flags_queue (NMDevice *self,
}
void
nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs)
nm_device_set_unmanaged_by_user_settings (NMDevice *self)
{
NMDevicePrivate *priv;
gboolean unmanaged;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) {
/* the device is already unmanaged due to platform-init.
*
* We want to delay evaluating the device spec, because it will freeze
* the permanent MAC address. That should not be done, before the platform
* link is fully initialized (via UDEV).
*
* Note that when clearing NM_UNMANAGED_PLATFORM_INIT, we will re-evaluate
* whether the device is unmanaged by user-settings. */
return;
}
unmanaged = nm_device_spec_match_list (self, unmanaged_specs);
unmanaged = nm_device_spec_match_list (self,
nm_settings_get_unmanaged_specs (NM_DEVICE_GET_PRIVATE (self)->settings));
nm_device_set_unmanaged_by_flags (self,
NM_UNMANAGED_USER_SETTINGS,
unmanaged,
!!unmanaged,
unmanaged
? NM_DEVICE_STATE_REASON_NOW_UNMANAGED
: NM_DEVICE_STATE_REASON_NOW_MANAGED);
@ -11587,11 +11645,17 @@ const char *
nm_device_get_hw_address (NMDevice *self)
{
NMDevicePrivate *priv;
char buf[NM_UTILS_HWADDR_LEN_MAX];
gsize l;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
nm_assert ((!priv->hw_addr) ^ (priv->hw_addr_len > 0));
nm_assert ( (!priv->hw_addr && priv->hw_addr_len == 0)
|| ( priv->hw_addr
&& _nm_utils_hwaddr_aton (priv->hw_addr, buf, sizeof (buf), &l)
&& l == priv->hw_addr_len));
return priv->hw_addr;
}
@ -11602,7 +11666,6 @@ nm_device_update_hw_address (NMDevice *self)
NMDevicePrivate *priv;
const guint8 *hwaddr;
gsize hwaddrlen = 0;
gboolean changed = FALSE;
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->ifindex <= 0)
@ -11615,38 +11678,46 @@ nm_device_update_hw_address (NMDevice *self)
&& nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth)))
hwaddrlen = 0;
if (hwaddrlen) {
priv->hw_addr_len = hwaddrlen;
if (!priv->hw_addr || !nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen)) {
g_free (priv->hw_addr);
priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen);
if (!hwaddrlen)
return FALSE;
_LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr);
_notify (self, PROP_HW_ADDRESS);
if ( priv->hw_addr_len
&& priv->hw_addr_len != hwaddrlen) {
char s_buf[NM_UTILS_HWADDR_LEN_MAX_STR];
if ( !priv->hw_addr_initial
|| ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET
&& priv->state < NM_DEVICE_STATE_PREPARE
&& !nm_device_is_activating (self))) {
/* when we get a hw_addr the first time or while the device
* is not activated (with no explict hw address set), always
* update our inital hw-address as well. */
nm_device_update_initial_hw_address (self);
}
changed = TRUE;
}
} else {
/* Invalid or no hardware address */
if (priv->hw_addr_len != 0) {
_LOGD (LOGD_PLATFORM | LOGD_DEVICE,
"hw-addr: failed reading current MAC address (stay with %s)",
priv->hw_addr);
} else {
_LOGD (LOGD_PLATFORM | LOGD_DEVICE,
"hw-addr: failed reading current MAC address");
}
/* we cannot change the address length of a device once it is set (except
* unrealizing the device).
*
* The reason is that the permanent and initial MAC addresses also must have the
* same address length, so it's unclear what it would mean that the length changes. */
_LOGD (LOGD_PLATFORM | LOGD_DEVICE,
"hw-addr: read a MAC address with differing length (%s vs. %s)",
priv->hw_addr,
nm_utils_hwaddr_ntoa_buf (hwaddr, hwaddrlen, TRUE, s_buf, sizeof (s_buf)));
return FALSE;
}
return changed;
if ( priv->hw_addr
&& nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen))
return FALSE;
g_free (priv->hw_addr);
priv->hw_addr_len_ = hwaddrlen;
priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen);
_LOGD (LOGD_PLATFORM | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr);
_notify (self, PROP_HW_ADDRESS);
if ( !priv->hw_addr_initial
|| ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET
&& priv->state < NM_DEVICE_STATE_PREPARE
&& !nm_device_is_activating (self))) {
/* when we get a hw_addr the first time or while the device
* is not activated (with no explict hw address set), always
* update our inital hw-address as well. */
nm_device_update_initial_hw_address (self);
}
return TRUE;
}
void
@ -11670,12 +11741,14 @@ nm_device_update_initial_hw_address (NMDevice *self)
}
void
nm_device_update_permanent_hw_address (NMDevice *self)
nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
size_t len = 0;
gboolean success_read;
int ifindex;
const NMPlatformLink *pllink;
if (priv->hw_addr_perm) {
/* the permanent hardware address is only read once and not
@ -11686,35 +11759,82 @@ nm_device_update_permanent_hw_address (NMDevice *self)
return;
}
if (priv->ifindex <= 0)
ifindex = priv->ifindex;
if (ifindex <= 0)
return;
if (!priv->hw_addr_len) {
nm_device_update_hw_address (self);
if (!priv->hw_addr_len)
/* the user is advised to configure stable MAC addresses for software devices via
* UDEV. Thus, check whether the link is fully initialized. */
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
if ( !pllink
|| !pllink->initialized) {
if (!force_freeze) {
/* we can afford to wait. Back off and leave the permanent MAC address
* undecided for now. */
return;
}
/* try to refresh the link just to give UDEV a bit more time... */
nm_platform_link_refresh (NM_PLATFORM_GET, ifindex);
/* maybe the MAC address changed... */
nm_device_update_hw_address (self);
} else if (!priv->hw_addr_len)
nm_device_update_hw_address (self);
if (!priv->hw_addr_len) {
/* we need the current MAC address because we require the permanent MAC address
* to have the same length as the current address.
*
* Abort if there is no current MAC address. */
return;
}
success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len);
if (!success_read || len != priv->hw_addr_len) {
/* Fall back to current address. We use the fake address and keep it
* until the device unrealizes.
*
* In some cases it might be necessary to know whether this is a "real" or
* a temporary address (fake). */
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)",
success_read
? "read HW addr length of permanent MAC address differs"
: "unable to read permanent MAC address",
priv->hw_addr);
priv->hw_addr_perm_fake = TRUE;
priv->hw_addr_perm = g_strdup (priv->hw_addr);
} else {
success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, ifindex, buf, &len);
if (success_read && priv->hw_addr_len == len) {
priv->hw_addr_perm_fake = FALSE;
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len);
_LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'",
priv->hw_addr_perm);
goto notify_and_out;
}
/* we failed to read a permanent MAC address, thus we use a fake address,
* that is the current MAC address of the device.
*
* Note that the permanet MAC address of a NMDevice instance does not change
* after being set once. Thus, we use now a fake address and stick to that
* (until we unrealize the device). */
priv->hw_addr_perm_fake = TRUE;
/* We also persist our choice of the fake address to the device state
* file to use the same address on restart of NetworkManager.
* First, try to reload the address from the state file. */
{
gs_free NMConfigDeviceStateData *dev_state = NULL;
dev_state = nm_config_device_state_load (nm_config_get (), ifindex);
if ( dev_state
&& dev_state->perm_hw_addr_fake
&& nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len)
&& !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
success_read
? "read HW addr length of permanent MAC address differs"
: "unable to read permanent MAC address",
dev_state->perm_hw_addr_fake,
priv->hw_addr);
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
goto notify_and_out;
}
}
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)",
success_read
? "read HW addr length of permanent MAC address differs"
: "unable to read permanent MAC address",
priv->hw_addr);
priv->hw_addr_perm = g_strdup (priv->hw_addr);
notify_and_out:
_notify (self, PROP_PERM_HW_ADDRESS);
}
@ -11806,25 +11926,25 @@ nm_device_hw_addr_is_explict (NMDevice *self)
}
static gboolean
_hw_addr_matches (NMDevice *self, const char *addr)
_hw_addr_matches (NMDevice *self, const guint8 *addr, gsize addr_len)
{
const char *cur_addr;
cur_addr = nm_device_get_hw_address (self);
return cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1);
return cur_addr && nm_utils_hwaddr_matches (addr, addr_len, cur_addr, -1);
}
static gboolean
_hw_addr_set (NMDevice *self,
const char *addr,
const char *operation,
const char *detail)
const char *const addr,
const char *const operation,
const char *const detail)
{
NMDevicePrivate *priv;
gboolean success = FALSE;
NMPlatformError plerr;
guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
guint hw_addr_len;
gsize addr_len;
gboolean was_up;
nm_assert (NM_IS_DEVICE (self));
@ -11833,17 +11953,17 @@ _hw_addr_set (NMDevice *self,
priv = NM_DEVICE_GET_PRIVATE (self);
if (!_nm_utils_hwaddr_aton (addr, addr_bytes, sizeof (addr_bytes), &addr_len))
g_return_val_if_reached (FALSE);
/* Do nothing if current MAC is same */
if (_hw_addr_matches (self, addr)) {
if (_hw_addr_matches (self, addr_bytes, addr_len)) {
_LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", addr);
return TRUE;
}
hw_addr_len = priv->hw_addr_len;
if (!hw_addr_len)
hw_addr_len = _nm_utils_hwaddr_length (addr);
if ( !hw_addr_len
|| !nm_utils_hwaddr_aton (addr, addr_bytes, hw_addr_len))
if ( priv->hw_addr_len
&& priv->hw_addr_len != addr_len)
g_return_val_if_reached (FALSE);
_LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail);
@ -11854,12 +11974,12 @@ _hw_addr_set (NMDevice *self,
nm_device_take_down (self, FALSE);
}
plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, hw_addr_len);
plerr = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, addr_len);
success = (plerr == NM_PLATFORM_ERROR_SUCCESS);
if (success) {
/* MAC address succesfully changed; update the current MAC to match */
nm_device_update_hw_address (self);
if (_hw_addr_matches (self, addr)) {
if (_hw_addr_matches (self, addr_bytes, addr_len)) {
_LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
operation, addr, detail);
} else {
@ -11889,7 +12009,7 @@ _hw_addr_set (NMDevice *self,
goto handle_fail;
if (!nm_device_update_hw_address (self))
goto handle_wait;
if (!_hw_addr_matches (self, addr))
if (!_hw_addr_matches (self, addr_bytes, addr_len))
goto handle_fail;
break;
@ -11972,7 +12092,7 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean
}
if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) {
addr = nm_device_get_permanent_hw_address (self, TRUE);
addr = nm_device_get_permanent_hw_address (self);
if (!addr)
return FALSE;
priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT;
@ -12016,9 +12136,8 @@ nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean
addr = hw_addr_generated;
} else {
/* this must be a valid address. Otherwise, we shouldn't come here. */
if (_nm_utils_hwaddr_length (addr) <= 0) {
if (!nm_utils_hwaddr_valid (addr, -1))
g_return_val_if_reached (FALSE);
}
priv->hw_addr_type = HW_ADDR_TYPE_EXPLICIT;
}
@ -12050,21 +12169,32 @@ nm_device_hw_addr_reset (NMDevice *self, const char *detail)
}
const char *
nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake)
nm_device_get_permanent_hw_address_full (NMDevice *self, gboolean force_freeze, gboolean *out_is_fake)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
if (!priv->hw_addr_perm)
return NULL;
if ( priv->hw_addr_perm_fake
&& !fallback_fake)
return NULL;
if ( !priv->hw_addr_perm
&& force_freeze) {
/* somebody requests a permanent MAC address, but we don't have it set
* yet. We cannot delay it any longer and try to get it without waiting
* for UDEV. */
nm_device_update_permanent_hw_address (self, TRUE);
}
NM_SET_OUT (out_is_fake, priv->hw_addr_perm && priv->hw_addr_perm_fake);
return priv->hw_addr_perm;
}
const char *
nm_device_get_permanent_hw_address (NMDevice *self)
{
return nm_device_get_permanent_hw_address_full (self, TRUE, NULL);
}
const char *
nm_device_get_initial_hw_address (NMDevice *self)
{
@ -12119,7 +12249,7 @@ spec_match_list (NMDevice *self, const GSList *specs)
}
}
hw_addr_perm = nm_device_get_permanent_hw_address (self, TRUE);
hw_addr_perm = nm_device_get_permanent_hw_address (self);
if (hw_addr_perm) {
m = nm_match_spec_hwaddr (specs, hw_addr_perm);
matched = MAX (matched, m);
@ -12217,13 +12347,16 @@ constructor (GType type,
}
if (priv->hw_addr_perm) {
priv->hw_addr_len = _nm_utils_hwaddr_length (priv->hw_addr_perm);
if (!priv->hw_addr_len) {
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
gsize l;
if (!_nm_utils_hwaddr_aton (priv->hw_addr_perm, buf, sizeof (buf), &l)) {
g_clear_pointer (&priv->hw_addr_perm, g_free);
g_return_val_if_reached (object);
}
priv->hw_addr = g_strdup (priv->hw_addr_perm);
priv->hw_addr_len_ = l;
priv->hw_addr = nm_utils_hwaddr_ntoa (buf, l);
_LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm);
}
@ -12595,10 +12728,15 @@ get_property (GObject *object, guint prop_id,
case PROP_HW_ADDRESS:
g_value_set_string (value, priv->hw_addr);
break;
case PROP_PERM_HW_ADDRESS:
case PROP_PERM_HW_ADDRESS: {
const char *perm_hw_addr;
gboolean perm_hw_addr_is_fake;
perm_hw_addr = nm_device_get_permanent_hw_address_full (self, FALSE, &perm_hw_addr_is_fake);
/* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */
g_value_set_string (value, nm_device_get_permanent_hw_address (self, FALSE));
g_value_set_string (value, perm_hw_addr && !perm_hw_addr_is_fake ? perm_hw_addr : NULL);
break;
}
case PROP_HAS_PENDING_ACTION:
g_value_set_boolean (value, nm_device_has_pending_action (self));
break;

View file

@ -362,8 +362,10 @@ guint32 nm_device_get_ip4_route_metric (NMDevice *dev);
guint32 nm_device_get_ip6_route_metric (NMDevice *dev);
const char * nm_device_get_hw_address (NMDevice *dev);
const char * nm_device_get_permanent_hw_address (NMDevice *dev,
gboolean fallback_fake);
const char * nm_device_get_permanent_hw_address (NMDevice *self);
const char * nm_device_get_permanent_hw_address_full (NMDevice *self,
gboolean force_freeze,
gboolean *out_is_fake);
const char * nm_device_get_initial_hw_address (NMDevice *dev);
NMProxyConfig * nm_device_get_proxy_config (NMDevice *dev);
@ -506,7 +508,7 @@ void nm_device_set_unmanaged_by_flags_queue (NMDevice *self,
NMUnmanagedFlags flags,
NMUnmanFlagOp set_op,
NMDeviceStateReason reason);
void nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs);
void nm_device_set_unmanaged_by_user_settings (NMDevice *self);
void nm_device_set_unmanaged_by_user_udev (NMDevice *self);
void nm_device_set_unmanaged_by_quitting (NMDevice *device);
@ -586,7 +588,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device,
gboolean nm_device_update_hw_address (NMDevice *self);
void nm_device_update_initial_hw_address (NMDevice *self);
void nm_device_update_permanent_hw_address (NMDevice *self);
void nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze);
void nm_device_update_dynamic_ip_setup (NMDevice *self);
#endif /* __NETWORKMANAGER_DEVICE_H__ */

View file

@ -603,7 +603,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_wireless)
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
mac = nm_setting_wireless_get_mac_address (s_wireless);
if (perm_hw_addr) {
if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
@ -895,7 +895,7 @@ complete_connection (NMDevice *device,
if (hidden)
g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
if (perm_hw_addr) {
setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
if (setting_mac) {

View file

@ -400,7 +400,7 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
priv = NM_CONFIG_GET_PRIVATE (self);
hw_address = nm_device_get_permanent_hw_address (device, TRUE);
hw_address = nm_device_get_permanent_hw_address (device);
if (!hw_address)
return;
@ -1879,6 +1879,7 @@ _nm_config_state_set (NMConfig *self,
#define DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE "device"
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED "managed"
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE "perm-hw-addr-fake"
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID "connection-uuid"
static NMConfigDeviceStateData *
@ -1887,7 +1888,10 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
NMConfigDeviceStateData *device_state;
NMConfigDeviceStateManagedType managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN;
gs_free char *connection_uuid = NULL;
gsize len_plus_1;
gs_free char *perm_hw_addr_fake = NULL;
gsize connection_uuid_len;
gsize perm_hw_addr_fake_len;
char *p;
nm_assert (ifindex > 0);
@ -1908,21 +1912,42 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID,
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
}
perm_hw_addr_fake = nm_config_keyfile_get_value (kf,
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
if (perm_hw_addr_fake) {
char *normalized;
normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1);
g_free (perm_hw_addr_fake);
perm_hw_addr_fake = normalized;
}
}
len_plus_1 = connection_uuid ? strlen (connection_uuid) + 1 : 0;
connection_uuid_len = connection_uuid ? strlen (connection_uuid) + 1 : 0;
perm_hw_addr_fake_len = perm_hw_addr_fake ? strlen (perm_hw_addr_fake) + 1 : 0;
device_state = g_malloc (sizeof (NMConfigDeviceStateData) + len_plus_1);
device_state = g_malloc (sizeof (NMConfigDeviceStateData) +
connection_uuid_len +
perm_hw_addr_fake_len);
device_state->ifindex = ifindex;
device_state->managed = managed_type;
device_state->connection_uuid = NULL;
if (connection_uuid) {
char *device_state_data;
device_state->perm_hw_addr_fake = NULL;
device_state_data = (char *) (&device_state[1]);
memcpy (device_state_data, connection_uuid, len_plus_1);
device_state->connection_uuid = device_state_data;
p = (char *) (&device_state[1]);
if (connection_uuid) {
memcpy (p, connection_uuid, connection_uuid_len);
device_state->connection_uuid = p;
p += connection_uuid_len;
}
if (perm_hw_addr_fake) {
memcpy (p, perm_hw_addr_fake, perm_hw_addr_fake_len);
device_state->perm_hw_addr_fake = p;
p += perm_hw_addr_fake_len;
}
return device_state;
@ -1943,23 +1968,23 @@ nm_config_device_state_load (NMConfig *self,
NMConfigDeviceStateData *device_state;
char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
gs_unref_keyfile GKeyFile *kf = NULL;
gs_free_error GError *error = NULL;
g_return_val_if_fail (ifindex > 0, NULL);
nm_sprintf_buf (path, "%s/%d", NM_CONFIG_DEVICE_STATE_DIR, ifindex);
kf = nm_config_create_keyfile ();
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error))
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL))
g_clear_pointer (&kf, g_key_file_unref);
device_state = _config_device_state_data_new (ifindex, kf);
if (kf) {
_LOGT ("device-state: read #%d (%s); managed=%d, connection-uuid=%s%s%s",
_LOGT ("device-state: read #%d (%s); managed=%d%s%s%s%s%s%s",
ifindex, path,
device_state->managed,
NM_PRINT_FMT_QUOTE_STRING (device_state->connection_uuid));
NM_PRINT_FMT_QUOTED (device_state->connection_uuid, ", connection-uuid=", device_state->connection_uuid, "", ""),
NM_PRINT_FMT_QUOTED (device_state->perm_hw_addr_fake, ", perm-hw-addr-fake=", device_state->perm_hw_addr_fake, "", ""));
} else {
_LOGT ("device-state: read #%d (%s); no persistent state",
ifindex, path);
@ -1972,6 +1997,7 @@ gboolean
nm_config_device_state_write (NMConfig *self,
int ifindex,
gboolean managed,
const char *perm_hw_addr_fake,
const char *connection_uuid)
{
char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
@ -1983,6 +2009,8 @@ nm_config_device_state_write (NMConfig *self,
g_return_val_if_fail (!connection_uuid || *connection_uuid, FALSE);
g_return_val_if_fail (managed || !connection_uuid, FALSE);
nm_assert (!perm_hw_addr_fake || nm_utils_hwaddr_valid (perm_hw_addr_fake, -1));
nm_sprintf_buf (path, "%s/%d", NM_CONFIG_DEVICE_STATE_DIR, ifindex);
kf = nm_config_create_keyfile ();
@ -1990,6 +2018,12 @@ nm_config_device_state_write (NMConfig *self,
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED,
!!managed);
if (perm_hw_addr_fake) {
g_key_file_set_string (kf,
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
perm_hw_addr_fake);
}
if (connection_uuid) {
g_key_file_set_string (kf,
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
@ -2002,10 +2036,11 @@ nm_config_device_state_write (NMConfig *self,
g_error_free (local);
return FALSE;
}
_LOGT ("device-state: write #%d (%s); managed=%d, connection-uuid=%s%s%s",
_LOGT ("device-state: write #%d (%s); managed=%d%s%s%s%s%s%s",
ifindex, path,
(bool) managed,
NM_PRINT_FMT_QUOTE_STRING (connection_uuid));
NM_PRINT_FMT_QUOTED (connection_uuid, ", connection-uuid=", connection_uuid, "", ""),
NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""));
return TRUE;
}

View file

@ -199,6 +199,8 @@ struct _NMConfigDeviceStateData {
/* the UUID of the last settings-connection active
* on the device. */
const char *connection_uuid;
const char *perm_hw_addr_fake;
};
NMConfigDeviceStateData *nm_config_device_state_load (NMConfig *self,
@ -206,6 +208,7 @@ NMConfigDeviceStateData *nm_config_device_state_load (NMConfig *self,
gboolean nm_config_device_state_write (NMConfig *self,
int ifindex,
gboolean managed,
const char *perm_hw_addr_fake,
const char *connection_uuid);
void nm_config_device_state_prune_unseen (NMConfig *self, GHashTable *seen_ifindexes);

View file

@ -1272,7 +1272,7 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
guint hwaddr_len = 0;
gsize hwaddr_len = 0;
guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX];
nm_assert (nm_utils_hwaddr_valid (hwaddr, -1));
@ -1297,11 +1297,8 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
continue;
if (G_UNLIKELY (hwaddr_len == 0)) {
hwaddr_len = _nm_utils_hwaddr_length (hwaddr);
if (!hwaddr_len)
if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, sizeof (hwaddr_bin), &hwaddr_len))
g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH);
if (!nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, hwaddr_len))
nm_assert_not_reached ();
}
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len)) {

View file

@ -621,7 +621,7 @@ find_device_by_permanent_hw_addr (NMManager *manager, const char *hwaddr)
if (nm_utils_hwaddr_valid (hwaddr, -1)) {
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data), FALSE);
device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data));
if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1))
return NM_DEVICE (iter->data);
}
@ -1331,11 +1331,10 @@ system_unmanaged_devices_changed_cb (NMSettings *settings,
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
const GSList *unmanaged_specs, *iter;
const GSList *iter;
unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
for (iter = priv->devices; iter; iter = g_slist_next (iter))
nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data), unmanaged_specs);
nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data));
}
static void
@ -2004,7 +2003,7 @@ add_device (NMManager *self, NMDevice *device, GError **error)
type_desc = nm_device_get_type_desc (device);
g_assert (type_desc);
nm_device_set_unmanaged_by_user_settings (device, nm_settings_get_unmanaged_specs (priv->settings));
nm_device_set_unmanaged_by_user_settings (device);
nm_device_set_unmanaged_flags (device,
NM_UNMANAGED_SLEEPING,
@ -2880,15 +2879,15 @@ unmanaged_to_disconnected (NMDevice *device)
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)
&& (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
}
@ -4674,6 +4673,8 @@ nm_manager_write_device_state (NMManager *self)
gboolean managed;
NMConnection *settings_connection;
const char *uuid = NULL;
const char *perm_hw_addr_fake = NULL;
gboolean perm_hw_addr_is_fake;
ifindex = nm_device_get_ip_ifindex (device);
if (ifindex <= 0)
@ -4693,9 +4694,14 @@ nm_manager_write_device_state (NMManager *self)
uuid = nm_connection_get_uuid (settings_connection);
}
perm_hw_addr_fake = nm_device_get_permanent_hw_address_full (device, FALSE, &perm_hw_addr_is_fake);
if (perm_hw_addr_fake && !perm_hw_addr_is_fake)
perm_hw_addr_fake = NULL;
if (nm_config_device_state_write (priv->config,
ifindex,
managed,
perm_hw_addr_fake,
uuid))
g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex));
}

View file

@ -1883,7 +1883,7 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
/* Find a wired connection locked to the given MAC address, if any */
g_hash_table_iter_init (&iter, priv->connections);