6lowpan: add function to uncompress multicast addr
authorAlexander Aring <alex.aring@gmail.com>
Fri, 16 Aug 2013 19:59:57 +0000 (21:59 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Aug 2013 20:23:12 +0000 (13:23 -0700)
Add function to uncompress multicast address.
This function split the uncompress function for a multicast address
in a seperate function.

To uncompress a multicast address is different than a other
non-multicasts addresses according to rfc6282.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Reviewed-by: Werner Almesberger <werner@almesberger.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ieee802154/6lowpan.c

index 632b3fdf46a4f9813d93bd27b2ae55f8c387df27..9aea7ce8b83d9820d6fdb36ee17b86f35dbf17d8 100644 (file)
@@ -88,15 +88,6 @@ static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
  */
 static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
 
-/*
- * Uncompression of ctx-base
- *   0 -> 0 bits from packet
- *   1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
- *   2 -> 2 bytes from prefix - zeroes + 3 from packet
- *   3 -> 2 bytes from prefix - infer 1 bytes from lladdr
- */
-static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
-
 /* Link local prefix */
 static const u8 lowpan_llprefix[] = {0xfe, 0x80};
 
@@ -240,6 +231,63 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
        return 0;
 }
 
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+               struct in6_addr *ipaddr,
+               const u8 dam)
+{
+       bool fail;
+
+       switch (dam) {
+       case LOWPAN_IPHC_DAM_00:
+               /* 00:  128 bits.  The full address
+                * is carried in-line.
+                */
+               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+               break;
+       case LOWPAN_IPHC_DAM_01:
+               /* 01:  48 bits.  The address takes
+                * the form ffXX::00XX:XXXX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+               break;
+       case LOWPAN_IPHC_DAM_10:
+               /* 10:  32 bits.  The address takes
+                * the form ffXX::00XX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+               break;
+       case LOWPAN_IPHC_DAM_11:
+               /* 11:  8 bits.  The address takes
+                * the form ff02::00XX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               ipaddr->s6_addr[1] = 0x02;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+               break;
+       default:
+               pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+               return -EINVAL;
+       }
+
+       if (fail) {
+               pr_debug("Failed to fetch skb data\n");
+               return -EIO;
+       }
+
+       lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n",
+                       ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
 static void
 lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 {
@@ -927,16 +975,8 @@ lowpan_process_data(struct sk_buff *skb)
                        pr_debug("dest: context-based mcast compression\n");
                        /* TODO: implement this */
                } else {
-                       u8 prefix[] = {0xff, 0x02};
-
-                       pr_debug("dest: non context-based mcast compression\n");
-                       if (0 < tmp && tmp < 3) {
-                               if (lowpan_fetch_skb_u8(skb, &prefix[1]))
-                                       goto drop;
-                       }
-
-                       err = lowpan_uncompress_addr(skb, &hdr.daddr, prefix,
-                                       lowpan_unc_mxconf[tmp], NULL);
+                       err = lowpan_uncompress_multicast_daddr(
+                                       skb, &hdr.daddr, tmp);
                        if (err)
                                goto drop;
                }