|
|
@@ -3,8 +3,7 @@
|
|
|
* written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
|
|
|
*/
|
|
|
|
|
|
-/*
|
|
|
- * Based on patches from Jon Smirl <jonsmirl@gmail.com>
|
|
|
+/* Based on patches from Jon Smirl <jonsmirl@gmail.com>
|
|
|
* Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
@@ -58,16 +57,15 @@
|
|
|
#include <net/ipv6.h>
|
|
|
#include <net/af_ieee802154.h>
|
|
|
|
|
|
-/*
|
|
|
- * Uncompress address function for source and
|
|
|
+/* Uncompress address function for source and
|
|
|
* destination address(non-multicast).
|
|
|
*
|
|
|
* address_mode is sam value or dam value.
|
|
|
*/
|
|
|
static int uncompress_addr(struct sk_buff *skb,
|
|
|
- struct in6_addr *ipaddr, const u8 address_mode,
|
|
|
- const u8 *lladdr, const u8 addr_type,
|
|
|
- const u8 addr_len)
|
|
|
+ struct in6_addr *ipaddr, const u8 address_mode,
|
|
|
+ const u8 *lladdr, const u8 addr_type,
|
|
|
+ const u8 addr_len)
|
|
|
{
|
|
|
bool fail;
|
|
|
|
|
|
@@ -140,13 +138,12 @@ static int uncompress_addr(struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Uncompress address function for source context
|
|
|
+/* Uncompress address function for source context
|
|
|
* based address(non-multicast).
|
|
|
*/
|
|
|
static int uncompress_context_based_src_addr(struct sk_buff *skb,
|
|
|
- struct in6_addr *ipaddr,
|
|
|
- const u8 sam)
|
|
|
+ struct in6_addr *ipaddr,
|
|
|
+ const u8 sam)
|
|
|
{
|
|
|
switch (sam) {
|
|
|
case LOWPAN_IPHC_ADDR_00:
|
|
|
@@ -175,13 +172,13 @@ static int uncompress_context_based_src_addr(struct sk_buff *skb,
|
|
|
}
|
|
|
|
|
|
static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
|
|
|
- struct net_device *dev, skb_delivery_cb deliver_skb)
|
|
|
+ struct net_device *dev, skb_delivery_cb deliver_skb)
|
|
|
{
|
|
|
struct sk_buff *new;
|
|
|
int stat;
|
|
|
|
|
|
- new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
|
|
|
- GFP_ATOMIC);
|
|
|
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr),
|
|
|
+ skb_tailroom(skb), GFP_ATOMIC);
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
if (!new)
|
|
|
@@ -196,7 +193,7 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
|
|
|
new->dev = dev;
|
|
|
|
|
|
raw_dump_table(__func__, "raw skb data dump before receiving",
|
|
|
- new->data, new->len);
|
|
|
+ new->data, new->len);
|
|
|
|
|
|
stat = deliver_skb(new, dev);
|
|
|
|
|
|
@@ -210,8 +207,8 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
|
|
|
*/
|
|
|
static int
|
|
|
lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
|
|
|
- struct in6_addr *ipaddr,
|
|
|
- const u8 dam)
|
|
|
+ struct in6_addr *ipaddr,
|
|
|
+ const u8 dam)
|
|
|
{
|
|
|
bool fail;
|
|
|
|
|
|
@@ -314,8 +311,7 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
|
|
|
fail |= lowpan_fetch_skb(skb, &uh->check, 2);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * UDP lenght needs to be infered from the lower layers
|
|
|
+ /* UDP lenght needs to be infered from the lower layers
|
|
|
* here, we obtain the hint from the remaining size of the
|
|
|
* frame
|
|
|
*/
|
|
|
@@ -338,16 +334,17 @@ err:
|
|
|
static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
|
|
|
|
|
|
int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
- const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
|
|
|
- const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
|
|
|
- u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
|
|
|
+ const u8 *saddr, const u8 saddr_type,
|
|
|
+ const u8 saddr_len, const u8 *daddr,
|
|
|
+ const u8 daddr_type, const u8 daddr_len,
|
|
|
+ u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
|
|
|
{
|
|
|
struct ipv6hdr hdr = {};
|
|
|
u8 tmp, num_context = 0;
|
|
|
int err;
|
|
|
|
|
|
raw_dump_table(__func__, "raw skb data dump uncompressed",
|
|
|
- skb->data, skb->len);
|
|
|
+ skb->data, skb->len);
|
|
|
|
|
|
/* another if the CID flag is set */
|
|
|
if (iphc1 & LOWPAN_IPHC_CID) {
|
|
|
@@ -360,8 +357,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
|
|
|
/* Traffic Class and Flow Label */
|
|
|
switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
|
|
|
- /*
|
|
|
- * Traffic Class and FLow Label carried in-line
|
|
|
+ /* Traffic Class and FLow Label carried in-line
|
|
|
* ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
|
|
|
*/
|
|
|
case 0: /* 00b */
|
|
|
@@ -374,8 +370,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
|
|
|
(hdr.flow_lbl[0] & 0x0f);
|
|
|
break;
|
|
|
- /*
|
|
|
- * Traffic class carried in-line
|
|
|
+ /* Traffic class carried in-line
|
|
|
* ECN + DSCP (1 byte), Flow Label is elided
|
|
|
*/
|
|
|
case 2: /* 10b */
|
|
|
@@ -385,8 +380,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
hdr.priority = ((tmp >> 2) & 0x0f);
|
|
|
hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
|
|
|
break;
|
|
|
- /*
|
|
|
- * Flow Label carried in-line
|
|
|
+ /* Flow Label carried in-line
|
|
|
* ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
|
|
|
*/
|
|
|
case 1: /* 01b */
|
|
|
@@ -415,9 +409,9 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
|
|
|
/* Hop Limit */
|
|
|
- if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
|
|
|
+ if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
|
|
|
hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
|
|
|
- else {
|
|
|
+ } else {
|
|
|
if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
|
|
|
goto drop;
|
|
|
}
|
|
|
@@ -429,12 +423,12 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
/* Source address context based uncompression */
|
|
|
pr_debug("SAC bit is set. Handle context based source address.\n");
|
|
|
err = uncompress_context_based_src_addr(
|
|
|
- skb, &hdr.saddr, tmp);
|
|
|
+ skb, &hdr.saddr, tmp);
|
|
|
} else {
|
|
|
/* Source address uncompression */
|
|
|
pr_debug("source address stateless compression\n");
|
|
|
err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
|
|
|
- saddr_type, saddr_len);
|
|
|
+ saddr_type, saddr_len);
|
|
|
}
|
|
|
|
|
|
/* Check on error of previous branch */
|
|
|
@@ -457,9 +451,9 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
} else {
|
|
|
err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
|
|
|
- daddr_type, daddr_len);
|
|
|
+ daddr_type, daddr_len);
|
|
|
pr_debug("dest: stateless compression mode %d dest %pI6c\n",
|
|
|
- tmp, &hdr.daddr);
|
|
|
+ tmp, &hdr.daddr);
|
|
|
if (err)
|
|
|
goto drop;
|
|
|
}
|
|
|
@@ -468,11 +462,11 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
if (iphc0 & LOWPAN_IPHC_NH_C) {
|
|
|
struct udphdr uh;
|
|
|
struct sk_buff *new;
|
|
|
+
|
|
|
if (uncompress_udp_header(skb, &uh))
|
|
|
goto drop;
|
|
|
|
|
|
- /*
|
|
|
- * replace the compressed UDP head by the uncompressed UDP
|
|
|
+ /* replace the compressed UDP head by the uncompressed UDP
|
|
|
* header
|
|
|
*/
|
|
|
new = skb_copy_expand(skb, sizeof(struct udphdr),
|
|
|
@@ -489,7 +483,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
|
|
|
|
|
|
raw_dump_table(__func__, "raw UDP header dump",
|
|
|
- (u8 *)&uh, sizeof(uh));
|
|
|
+ (u8 *)&uh, sizeof(uh));
|
|
|
|
|
|
hdr.nexthdr = UIP_PROTO_UDP;
|
|
|
}
|
|
|
@@ -504,8 +498,8 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
|
|
hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
|
|
|
hdr.hop_limit, &hdr.daddr);
|
|
|
|
|
|
- raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
|
|
|
- sizeof(hdr));
|
|
|
+ raw_dump_table(__func__, "raw header dump",
|
|
|
+ (u8 *)&hdr, sizeof(hdr));
|
|
|
|
|
|
return skb_deliver(skb, &hdr, dev, deliver_skb);
|
|
|
|
|
|
@@ -516,8 +510,8 @@ drop:
|
|
|
EXPORT_SYMBOL_GPL(lowpan_process_data);
|
|
|
|
|
|
static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
|
|
|
- const struct in6_addr *ipaddr,
|
|
|
- const unsigned char *lladdr)
|
|
|
+ const struct in6_addr *ipaddr,
|
|
|
+ const unsigned char *lladdr)
|
|
|
{
|
|
|
u8 val = 0;
|
|
|
|
|
|
@@ -530,14 +524,14 @@ static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
|
|
|
*hc06_ptr += 2;
|
|
|
val = 2; /* 16-bits */
|
|
|
raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
|
|
|
- *hc06_ptr - 2, 2);
|
|
|
+ *hc06_ptr - 2, 2);
|
|
|
} else {
|
|
|
/* do not compress IID => xxxx::IID */
|
|
|
memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
|
|
|
*hc06_ptr += 8;
|
|
|
val = 1; /* 64-bits */
|
|
|
raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
|
|
|
- *hc06_ptr - 8, 8);
|
|
|
+ *hc06_ptr - 8, 8);
|
|
|
}
|
|
|
|
|
|
return rol8(val, shift);
|
|
|
@@ -601,8 +595,8 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
|
|
|
}
|
|
|
|
|
|
int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
- unsigned short type, const void *_daddr,
|
|
|
- const void *_saddr, unsigned int len)
|
|
|
+ unsigned short type, const void *_daddr,
|
|
|
+ const void *_saddr, unsigned int len)
|
|
|
{
|
|
|
u8 tmp, iphc0, iphc1, *hc06_ptr;
|
|
|
struct ipv6hdr *hdr;
|
|
|
@@ -616,14 +610,13 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
|
|
|
pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
|
|
|
"\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
|
|
|
- hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
|
|
|
- hdr->hop_limit, &hdr->daddr);
|
|
|
+ hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
|
|
|
+ hdr->hop_limit, &hdr->daddr);
|
|
|
|
|
|
raw_dump_table(__func__, "raw skb network header dump",
|
|
|
- skb_network_header(skb), sizeof(struct ipv6hdr));
|
|
|
+ skb_network_header(skb), sizeof(struct ipv6hdr));
|
|
|
|
|
|
- /*
|
|
|
- * As we copy some bit-length fields, in the IPHC encoding bytes,
|
|
|
+ /* As we copy some bit-length fields, in the IPHC encoding bytes,
|
|
|
* we sometimes use |=
|
|
|
* If the field is 0, and the current bit value in memory is 1,
|
|
|
* this does not work. We therefore reset the IPHC encoding here
|
|
|
@@ -639,11 +632,10 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
(unsigned char *)_daddr, IEEE802154_ADDR_LEN);
|
|
|
|
|
|
raw_dump_table(__func__,
|
|
|
- "sending raw skb network uncompressed packet",
|
|
|
- skb->data, skb->len);
|
|
|
+ "sending raw skb network uncompressed packet",
|
|
|
+ skb->data, skb->len);
|
|
|
|
|
|
- /*
|
|
|
- * Traffic class, flow label
|
|
|
+ /* Traffic class, flow label
|
|
|
* If flow label is 0, compress it. If traffic class is 0, compress it
|
|
|
* We have to process both in the same time as the offset of traffic
|
|
|
* class depends on the presence of version and flow label
|
|
|
@@ -654,11 +646,11 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
|
|
|
|
|
|
if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
|
|
|
- (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
|
|
|
+ (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
|
|
|
/* flow label can be compressed */
|
|
|
iphc0 |= LOWPAN_IPHC_FL_C;
|
|
|
if ((hdr->priority == 0) &&
|
|
|
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
|
|
|
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
|
|
|
/* compress (elide) all */
|
|
|
iphc0 |= LOWPAN_IPHC_TC_C;
|
|
|
} else {
|
|
|
@@ -669,7 +661,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
} else {
|
|
|
/* Flow label cannot be compressed */
|
|
|
if ((hdr->priority == 0) &&
|
|
|
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
|
|
|
+ ((hdr->flow_lbl[0] & 0xF0) == 0)) {
|
|
|
/* compress only traffic class */
|
|
|
iphc0 |= LOWPAN_IPHC_TC_C;
|
|
|
*hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
|
|
|
@@ -695,8 +687,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
hc06_ptr += 1;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Hop limit
|
|
|
+ /* Hop limit
|
|
|
* if 1: compress, encoding is 01
|
|
|
* if 64: compress, encoding is 10
|
|
|
* if 255: compress, encoding is 11
|
|
|
@@ -793,7 +784,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
|
|
pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len);
|
|
|
|
|
|
raw_dump_table(__func__, "raw skb data dump compressed",
|
|
|
- skb->data, skb->len);
|
|
|
+ skb->data, skb->len);
|
|
|
return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(lowpan_header_compress);
|