diff options
-rw-r--r-- | net/ieee802154/6lowpan.c | 36 |
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 | ||
663 | static struct lowpan_fragment * | 663 | static struct lowpan_fragment * |
664 | lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag) | 664 | lowpan_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 | ||
983 | static int | 983 | static int |
984 | lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | 984 | lowpan_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 | ||
1062 | exit: | ||
1053 | return err; | 1063 | return err; |
1054 | } | 1064 | } |
1055 | 1065 | ||