diff --git a/fragmentation.c b/fragmentation.c index 6e4c957..47c5ac0 100644 --- a/fragmentation.c +++ b/fragmentation.c @@ -220,6 +220,18 @@ err: return ret; } +static inline void batadv_frag_dbg_entry(struct batadv_frag_list_entry *entry) +{ + struct sk_buff *skb = entry->skb; + struct batadv_frag_packet *packet; + + packet = (struct batadv_frag_packet *)skb->data; + + printk(KERN_DEBUG " skb->len: %u, skb->tailroom: %u, pkt->pkt_type: %hhu, pkt->version: %hhu, pkt->no: %hhu, pkt->seqno: %hu, pkt->total_size: %hu\n", + skb->len, skb_tailroom(skb), packet->packet_type, packet->version, + packet->no, ntohs(packet->seqno), ntohs(packet->total_size)); +} + /** * batadv_frag_merge_packets - merge a chain of fragments * @chain: head of chain with fragments @@ -234,9 +246,10 @@ static struct sk_buff * batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) { struct batadv_frag_packet *packet; - struct batadv_frag_list_entry *entry; + struct batadv_frag_list_entry *entry, dbg_entry; + struct batadv_frag_table_entry *table_entry; struct sk_buff *skb_out = NULL; - int size, hdr_size = sizeof(struct batadv_frag_packet); + int size, hdr_size = sizeof(struct batadv_frag_packet), i = 0; /* Make sure incoming skb has non-bogus data. */ packet = (struct batadv_frag_packet *)skb->data; @@ -250,8 +263,15 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list); hlist_del(&entry->list); skb_out = entry->skb; + memcpy(&dbg_entry, entry, sizeof(dbg_entry)); kfree(entry); + if (size < skb->len) + goto debug; + + if (size < skb_out->len) + goto debug; + /* Make room for the rest of the fragments. */ if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { kfree_skb(skb_out); @@ -271,6 +291,11 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) /* Copy the payload of the each fragment into the last skb */ hlist_for_each_entry(entry, chain, list) { size = entry->skb->len - hdr_size; + i++; + + if (skb_tailroom(skb_out) < size) + goto debug; + memcpy(skb_put(skb_out, size), entry->skb->data + hdr_size, size); } @@ -279,6 +304,19 @@ free: /* Locking is not needed, because 'chain' is not part of any orig. */ batadv_frag_clear_chain(chain); return skb_out; + +debug: + table_entry = container_of(chain, struct batadv_frag_table_entry, head); + printk(KERN_DEBUG "batadv_frag_merge_packets: i: %i, size: %i, entry->seqno: %hu, entry->size: %hu, entry->total_size: %hu\n", + i, size, table_entry->seqno, table_entry->size, + table_entry->total_size); + batadv_frag_dbg_entry(&dbg_entry); + + hlist_for_each_entry(entry, chain, list) + batadv_frag_dbg_entry(entry); + + batadv_frag_clear_chain(chain); + return NULL; } /**