{
struct ethhdr *ethhdr;
unsigned long flags;
+ struct sk_buff *skb_old;
/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < sizeof(struct batman_packet))
if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
- spin_lock_irqsave(&orig_hash_lock, flags);
/* TODO: we use headlen instead of "length", because
* only this data is paged in. */
- /* TODO: is another skb_copy needed here? there will be
- * written on the data, but nobody (?) should further use
- * this data */
+
+ /* create a copy of the skb, if needed, to modify it. */
+ if (!skb_clone_writable(skb, skb_headlen(skb))) {
+ skb_old = skb;
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_DROP;
+ kfree_skb(skb_old);
+ }
+
+ spin_lock_irqsave(&orig_hash_lock, flags);
receive_aggr_bat_packet(ethhdr,
skb->data,
skb_headlen(skb),