diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2018-05-23 11:21:51 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2018-06-26 16:21:55 +0200 |
commit | 49844ea55f1cdaec729b5e90c6dd8db6c890b044 (patch) | |
tree | 30e098dcf7d8ab71f6a358a7e1cd8c3e0e7ae9fd | |
parent | 1d396e9972218f52a7ddce1ba8b362eb9cfdf15e (diff) | |
download | NetworkManager-49844ea55f1cdaec729b5e90c6dd8db6c890b044.tar.gz |
device: generate pseudo 48-bit address from the WPAN short one
If an IEEE 802.15.4 WPAN device has a short address it is to be used to
get an interface identifier.
-rw-r--r-- | src/devices/nm-device.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 23c541d1b9..023a7676b0 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1736,7 +1736,11 @@ static gboolean get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMPlatform *platform = nm_device_get_platform (self); const NMPlatformLink *pllink; + const guint8 *hwaddr; + guint8 pseudo_hwaddr[ETH_ALEN]; + guint hwaddr_len; int ifindex; gboolean success; @@ -1744,7 +1748,7 @@ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) ifindex = nm_device_get_ip_ifindex (self); g_return_val_if_fail (ifindex > 0, FALSE); - pllink = nm_platform_link_get (nm_device_get_platform (self), ifindex); + pllink = nm_platform_link_get (platform, ifindex); if ( !pllink || NM_IN_SET (pllink->type, NM_LINK_TYPE_NONE, NM_LINK_TYPE_UNKNOWN)) return FALSE; @@ -1754,9 +1758,35 @@ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX) g_return_val_if_reached (FALSE); + hwaddr = pllink->addr.data; + hwaddr_len = pllink->addr.len; + + if (pllink->type == NM_LINK_TYPE_6LOWPAN) { + /* If the underlying IEEE 802.15.4 device has a short address we generate + * a "pseudo 48-bit address" that's to be used in the same fashion as a + * wired Ethernet address. The mechanism is specified in Section 6. of + * RFC 4944 */ + guint16 pan_id; + guint16 short_addr; + + short_addr = nm_platform_wpan_get_short_addr (platform, pllink->parent); + if (short_addr != G_MAXUINT16) { + pan_id = nm_platform_wpan_get_pan_id (platform, pllink->parent); + pseudo_hwaddr[0] = short_addr & 0xff; + pseudo_hwaddr[1] = (short_addr >> 8) & 0xff; + pseudo_hwaddr[2] = 0; + pseudo_hwaddr[3] = 0; + pseudo_hwaddr[4] = pan_id & 0xff; + pseudo_hwaddr[5] = (pan_id >> 8) & 0xff; + + hwaddr = pseudo_hwaddr; + hwaddr_len = G_N_ELEMENTS (pseudo_hwaddr); + } + } + success = nm_utils_get_ipv6_interface_identifier (pllink->type, - pllink->addr.data, - pllink->addr.len, + hwaddr, + hwaddr_len, priv->dev_id, out_iid); if (!success) { |