aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorTony Cheneau <tony.cheneau@amnesiak.org>2013-03-25 13:59:26 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:37:57 -0400
commitd991b98f5006e36b7ee9f8ef89ed3a8636692d69 (patch)
tree2ef77fb92782bf1b5e7dfe1f11e83488e3c473d6 /net/ieee802154
parent58ef67c318ac1e83a7a333f66403d777e7447461 (diff)
6lowpan: fix first fragment (FRAG1) handling
The first fragment, FRAG1, must contain some payload according to the specs. However, as it is currently written, the first fragment will remain empty and only contain the 6lowpan headers. This patch also extracts the transport layer information from the first fragment. This information is used later on when uncompressing UDP header. Thanks to Wolf-Bastian Pöttner for noticing that the offset value was not properly initialized. Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/6lowpan.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 0eebb960e11d..4a62289669b1 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -661,7 +661,7 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
661} 661}
662 662
663static struct lowpan_fragment * 663static struct lowpan_fragment *
664lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag) 664lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
665{ 665{
666 struct lowpan_fragment *frame; 666 struct lowpan_fragment *frame;
667 667
@@ -731,7 +731,7 @@ lowpan_process_data(struct sk_buff *skb)
731 { 731 {
732 struct lowpan_fragment *frame; 732 struct lowpan_fragment *frame;
733 /* slen stores the rightmost 8 bits of the 11 bits length */ 733 /* slen stores the rightmost 8 bits of the 11 bits length */
734 u8 slen, offset; 734 u8 slen, offset = 0;
735 u16 len, tag; 735 u16 len, tag;
736 bool found = false; 736 bool found = false;
737 737
@@ -742,6 +742,12 @@ lowpan_process_data(struct sk_buff *skb)
742 /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */ 742 /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
743 len = ((iphc0 & 7) << 8) | slen; 743 len = ((iphc0 & 7) << 8) | slen;
744 744
745 /* FRAGN */
746 if ((iphc0 & LOWPAN_DISPATCH_MASK) != LOWPAN_DISPATCH_FRAG1) {
747 if (lowpan_fetch_skb_u8(skb, &offset))
748 goto unlock_and_drop;
749 }
750
745 /* 751 /*
746 * check if frame assembling with the same tag is 752 * check if frame assembling with the same tag is
747 * already in progress 753 * already in progress
@@ -761,12 +767,6 @@ lowpan_process_data(struct sk_buff *skb)
761 goto unlock_and_drop; 767 goto unlock_and_drop;
762 } 768 }
763 769
764 if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
765 goto unlock_and_drop;
766
767 if (lowpan_fetch_skb_u8(skb, &offset)) /* fetch offset */
768 goto unlock_and_drop;
769
770 /* if payload fits buffer, copy it */ 770 /* if payload fits buffer, copy it */
771 if (likely((offset * 8 + skb->len) <= frame->length)) 771 if (likely((offset * 8 + skb->len) <= frame->length))
772 skb_copy_to_linear_data_offset(frame->skb, offset * 8, 772 skb_copy_to_linear_data_offset(frame->skb, offset * 8,
@@ -982,13 +982,13 @@ static int lowpan_get_mac_header_length(struct sk_buff *skb)
982 982
983static int 983static int
984lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, 984lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
985 int mlen, int plen, int offset) 985 int mlen, int plen, int offset, int type)
986{ 986{
987 struct sk_buff *frag; 987 struct sk_buff *frag;
988 int hlen, ret; 988 int hlen, ret;
989 989
990 /* if payload length is zero, therefore it's a first fragment */ 990 hlen = (type == LOWPAN_DISPATCH_FRAG1) ?
991 hlen = (plen == 0 ? LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE); 991 LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE;
992 992
993 lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen); 993 lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
994 994
@@ -1031,7 +1031,13 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
1031 head[2] = tag >> 8; 1031 head[2] = tag >> 8;
1032 head[3] = tag & 0xff; 1032 head[3] = tag & 0xff;
1033 1033
1034 err = lowpan_fragment_xmit(skb, head, header_length, 0, 0); 1034 err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
1035 0, LOWPAN_DISPATCH_FRAG1);
1036
1037 if (err)
1038 goto exit;
1039
1040 offset = LOWPAN_FRAG_SIZE;
1035 1041
1036 /* next fragment header */ 1042 /* next fragment header */
1037 head[0] &= ~LOWPAN_DISPATCH_FRAG1; 1043 head[0] &= ~LOWPAN_DISPATCH_FRAG1;
@@ -1046,10 +1052,14 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
1046 len = payload_length - offset; 1052 len = payload_length - offset;
1047 1053
1048 err = lowpan_fragment_xmit(skb, head, header_length, 1054 err = lowpan_fragment_xmit(skb, head, header_length,
1049 len, offset); 1055 len, offset, LOWPAN_DISPATCH_FRAGN);
1056 if (err)
1057 goto exit;
1058
1050 offset += len; 1059 offset += len;
1051 } 1060 }
1052 1061
1062exit:
1053 return err; 1063 return err;
1054} 1064}
1055 1065