summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2018-05-23 11:21:51 +0200
committerLubomir Rintel <lkundrak@v3.sk>2018-06-26 16:21:55 +0200
commit49844ea55f1cdaec729b5e90c6dd8db6c890b044 (patch)
tree30e098dcf7d8ab71f6a358a7e1cd8c3e0e7ae9fd
parent1d396e9972218f52a7ddce1ba8b362eb9cfdf15e (diff)
downloadNetworkManager-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.c36
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) {