aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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