6lowpan: iphc: fix handling of link-local compression
authorAlexander Aring <aar@pengutronix.de>
Wed, 16 Mar 2016 12:52:41 +0000 (13:52 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 8 Apr 2016 17:28:13 +0000 (19:28 +0200)
This patch fixes handling in case of link-local address compression. A
IPv6 link-local address is defined as fe80::/10 prefix which is also
what ipv6_addr_type checks for link-local addresses.

But IPHC compression for link-local addresses are for fe80::/64 types
only. This patch adds additional checks for zero padded bits in case of
link-local address compression to match on a fe80::/64 address only.

Signed-off-by: Alexander Aring <aar@pengutronix.de>
Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/6lowpan/iphc.c

index 99bb22a..68c80f3 100644 (file)
         (((a)->s6_addr16[6]) == 0) &&          \
         (((a)->s6_addr[14]) == 0))
 
+#define lowpan_is_linklocal_zero_padded(a)     \
+       (!(hdr->saddr.s6_addr[1] & 0x3f) &&     \
+        !hdr->saddr.s6_addr16[1] &&            \
+        !hdr->saddr.s6_addr32[1])
+
 #define LOWPAN_IPHC_CID_DCI(cid)       (cid & 0x0f)
 #define LOWPAN_IPHC_CID_SCI(cid)       ((cid & 0xf0) >> 4)
 
@@ -1101,7 +1106,8 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
                                                          true);
                        iphc1 |= LOWPAN_IPHC_SAC;
                } else {
-                       if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL) {
+                       if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL &&
+                           lowpan_is_linklocal_zero_padded(hdr->saddr)) {
                                iphc1 |= lowpan_compress_addr_64(&hc_ptr,
                                                                 &hdr->saddr,
                                                                 saddr, true);
@@ -1135,7 +1141,8 @@ int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
                                                          false);
                        iphc1 |= LOWPAN_IPHC_DAC;
                } else {
-                       if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL) {
+                       if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL &&
+                           lowpan_is_linklocal_zero_padded(hdr->daddr)) {
                                iphc1 |= lowpan_compress_addr_64(&hc_ptr,
                                                                 &hdr->daddr,
                                                                 daddr, false);