"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "net/batman-adv/fragmentation.c" between
linux-3.16.62.tar.xz and linux-3.16.63.tar.xz

About: The full source of the Linux kernel 3.16.x (longterm stable)

fragmentation.c  (linux-3.16.62.tar.xz):fragmentation.c  (linux-3.16.63.tar.xz)
skipping to change at line 164 skipping to change at line 164
/* Select entry in the "chain table" and delete any prior fragments /* Select entry in the "chain table" and delete any prior fragments
* with another sequence number. batadv_frag_init_chain() returns true, * with another sequence number. batadv_frag_init_chain() returns true,
* if the list is empty at return. * if the list is empty at return.
*/ */
chain = &orig_node->fragments[bucket]; chain = &orig_node->fragments[bucket];
spin_lock_bh(&chain->lock); spin_lock_bh(&chain->lock);
if (batadv_frag_init_chain(chain, seqno)) { if (batadv_frag_init_chain(chain, seqno)) {
hlist_add_head(&frag_entry_new->list, &chain->head); hlist_add_head(&frag_entry_new->list, &chain->head);
chain->size = skb->len - hdr_size; chain->size = skb->len - hdr_size;
chain->timestamp = jiffies; chain->timestamp = jiffies;
chain->total_size = ntohs(frag_packet->total_size);
ret = true; ret = true;
goto out; goto out;
} }
/* Find the position for the new fragment. */ /* Find the position for the new fragment. */
hlist_for_each_entry(frag_entry_curr, &chain->head, list) { hlist_for_each_entry(frag_entry_curr, &chain->head, list) {
/* Drop packet if fragment already exists. */ /* Drop packet if fragment already exists. */
if (frag_entry_curr->no == frag_entry_new->no) if (frag_entry_curr->no == frag_entry_new->no)
goto err_unlock; goto err_unlock;
skipping to change at line 198 skipping to change at line 199
/* Reached the end of the list, so insert after 'frag_entry_last'. */ /* Reached the end of the list, so insert after 'frag_entry_last'. */
if (likely(frag_entry_last)) { if (likely(frag_entry_last)) {
hlist_add_after(&frag_entry_last->list, &frag_entry_new->list); hlist_add_after(&frag_entry_last->list, &frag_entry_new->list);
chain->size += skb->len - hdr_size; chain->size += skb->len - hdr_size;
chain->timestamp = jiffies; chain->timestamp = jiffies;
ret = true; ret = true;
} }
out: out:
if (chain->size > batadv_frag_size_limit() || if (chain->size > batadv_frag_size_limit() ||
ntohs(frag_packet->total_size) > batadv_frag_size_limit()) { chain->total_size != ntohs(frag_packet->total_size) ||
chain->total_size > batadv_frag_size_limit()) {
/* Clear chain if total size of either the list or the packet /* Clear chain if total size of either the list or the packet
* exceeds the maximum size of one merged packet. * exceeds the maximum size of one merged packet. Don't allow
* packets to have different total_size.
*/ */
batadv_frag_clear_chain(&chain->head); batadv_frag_clear_chain(&chain->head);
chain->size = 0; chain->size = 0;
} else if (ntohs(frag_packet->total_size) == chain->size) { } else if (ntohs(frag_packet->total_size) == chain->size) {
/* All fragments received. Hand over chain to caller. */ /* All fragments received. Hand over chain to caller. */
hlist_move_list(&chain->head, chain_out); hlist_move_list(&chain->head, chain_out);
chain->size = 0; chain->size = 0;
} }
err_unlock: err_unlock:
skipping to change at line 233 skipping to change at line 236
* batadv_frag_merge_packets - merge a chain of fragments * batadv_frag_merge_packets - merge a chain of fragments
* @chain: head of chain with fragments * @chain: head of chain with fragments
* @skb: packet with total size of skb after merging * @skb: packet with total size of skb after merging
* *
* Expand the first skb in the chain and copy the content of the remaining * Expand the first skb in the chain and copy the content of the remaining
* skb's into the expanded one. After doing so, clear the chain. * skb's into the expanded one. After doing so, clear the chain.
* *
* Returns the merged skb or NULL on error. * Returns the merged skb or NULL on error.
*/ */
static struct sk_buff * static struct sk_buff *
batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) batadv_frag_merge_packets(struct hlist_head *chain)
{ {
struct batadv_frag_packet *packet; struct batadv_frag_packet *packet;
struct batadv_frag_list_entry *entry; struct batadv_frag_list_entry *entry;
struct sk_buff *skb_out = NULL; struct sk_buff *skb_out = NULL;
int size, hdr_size = sizeof(struct batadv_frag_packet); int size, hdr_size = sizeof(struct batadv_frag_packet);
/* Make sure incoming skb has non-bogus data. */
packet = (struct batadv_frag_packet *)skb->data;
size = ntohs(packet->total_size);
if (size > batadv_frag_size_limit())
goto free;
/* Remove first entry, as this is the destination for the rest of the /* Remove first entry, as this is the destination for the rest of the
* fragments. * fragments.
*/ */
entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list); entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list);
hlist_del(&entry->list); hlist_del(&entry->list);
skb_out = entry->skb; skb_out = entry->skb;
kfree(entry); kfree(entry);
packet = (struct batadv_frag_packet *)skb_out->data;
size = ntohs(packet->total_size) + hdr_size;
/* Make room for the rest of the fragments. */ /* Make room for the rest of the fragments. */
if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) {
kfree_skb(skb_out); kfree_skb(skb_out);
skb_out = NULL; skb_out = NULL;
goto free; goto free;
} }
/* Move the existing MAC header to just before the payload. (Override /* Move the existing MAC header to just before the payload. (Override
* the fragment header.) * the fragment header.)
*/ */
skipping to change at line 310 skipping to change at line 310
bool ret = false; bool ret = false;
/* Add packet to buffer and table entry if merge is possible. */ /* Add packet to buffer and table entry if merge is possible. */
if (!batadv_frag_insert_packet(orig_node_src, *skb, &head)) if (!batadv_frag_insert_packet(orig_node_src, *skb, &head))
goto out_err; goto out_err;
/* Leave if more fragments are needed to merge. */ /* Leave if more fragments are needed to merge. */
if (hlist_empty(&head)) if (hlist_empty(&head))
goto out; goto out;
skb_out = batadv_frag_merge_packets(&head, *skb); skb_out = batadv_frag_merge_packets(&head);
if (!skb_out) if (!skb_out)
goto out_err; goto out_err;
out: out:
ret = true; ret = true;
out_err: out_err:
*skb = skb_out; *skb = skb_out;
return ret; return ret;
} }
 End of changes. 7 change blocks. 
10 lines changed or deleted 10 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)