diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 68c0dac303..505a77d166 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -2313,6 +2313,7 @@ get_gre_eui64_u_bit (guint32 addr) * @link_type: the hardware link type * @hwaddr: the hardware address of the interface * @hwaddr_len: the length (in bytes) of @hwaddr + * @dev_id: the device identifier, if any * @out_iid: on success, filled with the interface identifier; on failure * zeroed out * @@ -2327,6 +2328,7 @@ gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, const guint8 *hwaddr, guint hwaddr_len, + guint dev_id, NMUtilsIPv6IfaceId *out_iid) { guint32 addr; @@ -2361,13 +2363,20 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, default: if (hwaddr_len == ETH_ALEN) { /* Translate 48-bit MAC address to a 64-bit Modified EUI-64. See - * http://tools.ietf.org/html/rfc4291#appendix-A + * http://tools.ietf.org/html/rfc4291#appendix-A and the Linux + * kernel's net/ipv6/addrconf.c::ipv6_generate_eui64() function. */ - out_iid->id_u8[0] = hwaddr[0] ^ 0x02; + out_iid->id_u8[0] = hwaddr[0]; out_iid->id_u8[1] = hwaddr[1]; out_iid->id_u8[2] = hwaddr[2]; - out_iid->id_u8[3] = 0xff; - out_iid->id_u8[4] = 0xfe; + if (dev_id) { + out_iid->id_u8[3] = (dev_id >> 8) & 0xff; + out_iid->id_u8[4] = dev_id & 0xff; + } else { + out_iid->id_u8[0] ^= 0x02; + out_iid->id_u8[3] = 0xff; + out_iid->id_u8[4] = 0xfe; + } out_iid->id_u8[5] = hwaddr[3]; out_iid->id_u8[6] = hwaddr[4]; out_iid->id_u8[7] = hwaddr[5]; diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 40315c6efc..b309b5067a 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -196,6 +196,7 @@ typedef struct { gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, const guint8 *hwaddr, guint len, + guint dev_id, NMUtilsIPv6IfaceId *out_iid); void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr, diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 88debebfc8..d8bb2247a9 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -201,6 +201,7 @@ typedef struct { char * hw_addr; guint hw_addr_len; char * physical_port_id; + guint dev_id; NMUnmanagedFlags unmanaged_flags; gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ @@ -593,6 +594,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) static gboolean get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) { + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMLinkType link_type; const guint8 *hwaddr = NULL; size_t hwaddr_len = 0; @@ -613,6 +615,7 @@ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) success = nm_utils_get_ipv6_interface_identifier (link_type, hwaddr, hwaddr_len, + priv->dev_id, out_iid); if (!success) { _LOGW (LOGD_HW, "failed to generate interface identifier " @@ -8304,6 +8307,7 @@ constructed (GObject *object) if (priv->ifindex > 0) { priv->is_software = nm_platform_link_is_software (priv->ifindex); priv->physical_port_id = nm_platform_link_get_physical_port_id (priv->ifindex); + priv->dev_id = nm_platform_link_get_dev_id (priv->ifindex); priv->mtu = nm_platform_link_get_mtu (priv->ifindex); } /* Indicate software device in capabilities. */