6lowpan: modify udp compression/uncompression to match the standard

The previous code would just compress the UDP header and send the compressed
UDP header along with the uncompressed one.

Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Tony Cheneau 2013-03-25 17:59:32 +00:00 committed by David S. Miller
parent 43de7aa6ac
commit 24363b6732

View file

@ -284,6 +284,9 @@ lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
/* checksum is always inline */ /* checksum is always inline */
memcpy(*hc06_ptr, &uh->check, 2); memcpy(*hc06_ptr, &uh->check, 2);
*hc06_ptr += 2; *hc06_ptr += 2;
/* skip the UDP header */
skb_pull(skb, sizeof(struct udphdr));
} }
static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
@ -309,9 +312,8 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
} }
static int static int
lowpan_uncompress_udp_header(struct sk_buff *skb) lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
{ {
struct udphdr *uh = udp_hdr(skb);
u8 tmp; u8 tmp;
if (!uh) if (!uh)
@ -358,6 +360,14 @@ lowpan_uncompress_udp_header(struct sk_buff *skb)
/* copy checksum */ /* copy checksum */
memcpy(&uh->check, &skb->data[0], 2); memcpy(&uh->check, &skb->data[0], 2);
skb_pull(skb, 2); skb_pull(skb, 2);
/*
* UDP lenght needs to be infered from the lower layers
* here, we obtain the hint from the remaining size of the
* frame
*/
uh->len = htons(skb->len + sizeof(struct udphdr));
pr_debug("uncompressed UDP length: src = %d", uh->len);
} else { } else {
pr_debug("ERROR: unsupported NH format\n"); pr_debug("ERROR: unsupported NH format\n");
goto err; goto err;
@ -944,8 +954,31 @@ lowpan_process_data(struct sk_buff *skb)
/* UDP data uncompression */ /* UDP data uncompression */
if (iphc0 & LOWPAN_IPHC_NH_C) { if (iphc0 & LOWPAN_IPHC_NH_C) {
if (lowpan_uncompress_udp_header(skb)) struct udphdr uh;
struct sk_buff *new;
if (lowpan_uncompress_udp_header(skb, &uh))
goto drop; goto drop;
/*
* replace the compressed UDP head by the uncompressed UDP
* header
*/
new = skb_copy_expand(skb, sizeof(struct udphdr),
skb_tailroom(skb), GFP_ATOMIC);
kfree_skb(skb);
if (!new)
return -ENOMEM;
skb = new;
skb_push(skb, sizeof(struct udphdr));
skb_reset_transport_header(skb);
skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
lowpan_raw_dump_table(__func__, "raw UDP header dump",
(u8 *)&uh, sizeof(uh));
hdr.nexthdr = UIP_PROTO_UDP; hdr.nexthdr = UIP_PROTO_UDP;
} }