aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154/6lowpan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee802154/6lowpan.c')
-rw-r--r--net/ieee802154/6lowpan.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 840821b90bcd..32eb4179e8fa 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -196,7 +196,7 @@ lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
196static void 196static void
197lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr) 197lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr)
198{ 198{
199 memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ALEN); 199 memcpy(&ipaddr->s6_addr[8], lladdr, IEEE802154_ADDR_LEN);
200 /* second bit-flip (Universe/Local) is done according RFC2464 */ 200 /* second bit-flip (Universe/Local) is done according RFC2464 */
201 ipaddr->s6_addr[8] ^= 0x02; 201 ipaddr->s6_addr[8] ^= 0x02;
202} 202}
@@ -221,7 +221,7 @@ lowpan_uncompress_addr(struct sk_buff *skb, struct in6_addr *ipaddr,
221 221
222 if (lladdr) 222 if (lladdr)
223 lowpan_raw_dump_inline(__func__, "linklocal address", 223 lowpan_raw_dump_inline(__func__, "linklocal address",
224 lladdr, IEEE802154_ALEN); 224 lladdr, IEEE802154_ADDR_LEN);
225 if (prefcount > 0) 225 if (prefcount > 0)
226 memcpy(ipaddr, prefix, prefcount); 226 memcpy(ipaddr, prefix, prefcount);
227 227
@@ -371,7 +371,7 @@ err:
371static int lowpan_header_create(struct sk_buff *skb, 371static int lowpan_header_create(struct sk_buff *skb,
372 struct net_device *dev, 372 struct net_device *dev,
373 unsigned short type, const void *_daddr, 373 unsigned short type, const void *_daddr,
374 const void *_saddr, unsigned len) 374 const void *_saddr, unsigned int len)
375{ 375{
376 u8 tmp, iphc0, iphc1, *hc06_ptr; 376 u8 tmp, iphc0, iphc1, *hc06_ptr;
377 struct ipv6hdr *hdr; 377 struct ipv6hdr *hdr;
@@ -650,6 +650,53 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
650 kfree(entry); 650 kfree(entry);
651} 651}
652 652
653static struct lowpan_fragment *
654lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u8 tag)
655{
656 struct lowpan_fragment *frame;
657
658 frame = kzalloc(sizeof(struct lowpan_fragment),
659 GFP_ATOMIC);
660 if (!frame)
661 goto frame_err;
662
663 INIT_LIST_HEAD(&frame->list);
664
665 frame->length = (iphc0 & 7) | (len << 3);
666 frame->tag = tag;
667
668 /* allocate buffer for frame assembling */
669 frame->skb = alloc_skb(frame->length +
670 sizeof(struct ipv6hdr), GFP_ATOMIC);
671
672 if (!frame->skb)
673 goto skb_err;
674
675 frame->skb->priority = skb->priority;
676 frame->skb->dev = skb->dev;
677
678 /* reserve headroom for uncompressed ipv6 header */
679 skb_reserve(frame->skb, sizeof(struct ipv6hdr));
680 skb_put(frame->skb, frame->length);
681
682 init_timer(&frame->timer);
683 /* time out is the same as for ipv6 - 60 sec */
684 frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
685 frame->timer.data = (unsigned long)frame;
686 frame->timer.function = lowpan_fragment_timer_expired;
687
688 add_timer(&frame->timer);
689
690 list_add_tail(&frame->list, &lowpan_fragments);
691
692 return frame;
693
694skb_err:
695 kfree(frame);
696frame_err:
697 return NULL;
698}
699
653static int 700static int
654lowpan_process_data(struct sk_buff *skb) 701lowpan_process_data(struct sk_buff *skb)
655{ 702{
@@ -692,41 +739,9 @@ lowpan_process_data(struct sk_buff *skb)
692 739
693 /* alloc new frame structure */ 740 /* alloc new frame structure */
694 if (!found) { 741 if (!found) {
695 frame = kzalloc(sizeof(struct lowpan_fragment), 742 frame = lowpan_alloc_new_frame(skb, iphc0, len, tag);
696 GFP_ATOMIC);
697 if (!frame) 743 if (!frame)
698 goto unlock_and_drop; 744 goto unlock_and_drop;
699
700 INIT_LIST_HEAD(&frame->list);
701
702 frame->length = (iphc0 & 7) | (len << 3);
703 frame->tag = tag;
704
705 /* allocate buffer for frame assembling */
706 frame->skb = alloc_skb(frame->length +
707 sizeof(struct ipv6hdr), GFP_ATOMIC);
708
709 if (!frame->skb) {
710 kfree(frame);
711 goto unlock_and_drop;
712 }
713
714 frame->skb->priority = skb->priority;
715 frame->skb->dev = skb->dev;
716
717 /* reserve headroom for uncompressed ipv6 header */
718 skb_reserve(frame->skb, sizeof(struct ipv6hdr));
719 skb_put(frame->skb, frame->length);
720
721 init_timer(&frame->timer);
722 /* time out is the same as for ipv6 - 60 sec */
723 frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT;
724 frame->timer.data = (unsigned long)frame;
725 frame->timer.function = lowpan_fragment_timer_expired;
726
727 add_timer(&frame->timer);
728
729 list_add_tail(&frame->list, &lowpan_fragments);
730 } 745 }
731 746
732 if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) 747 if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)