diff options
Diffstat (limited to 'net/ieee802154/6lowpan.c')
-rw-r--r-- | net/ieee802154/6lowpan.c | 87 |
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, | |||
196 | static void | 196 | static void |
197 | lowpan_uip_ds6_set_addr_iid(struct in6_addr *ipaddr, unsigned char *lladdr) | 197 | lowpan_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: | |||
371 | static int lowpan_header_create(struct sk_buff *skb, | 371 | static 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 | ||
653 | static struct lowpan_fragment * | ||
654 | lowpan_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 | |||
694 | skb_err: | ||
695 | kfree(frame); | ||
696 | frame_err: | ||
697 | return NULL; | ||
698 | } | ||
699 | |||
653 | static int | 700 | static int |
654 | lowpan_process_data(struct sk_buff *skb) | 701 | lowpan_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) |