diff options
author | Sven Eckelmann <sven@narfation.org> | 2014-12-01 04:37:28 -0500 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2015-05-29 04:13:35 -0400 |
commit | 83e8b87721f21b26b843633caca8ef453e943623 (patch) | |
tree | c987f856131f264bc54667c1531d75cb875a5256 | |
parent | 53e771457e823fbc21834f60508c42a4270534fd (diff) |
batman-adv: Use only queued fragments when merging
The fragment queueing code now validates the total_size of each fragment,
checks when enough fragments are queued to allow to merge them into a
single packet and if the fragments have the correct size. Therefore, it is
not required to have any other parameter for the merging function than a
list of queued fragments.
This change should avoid problems like in the past when the different skb
from the list and the function parameter were mixed incorrectly.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Acked-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
-rw-r--r-- | net/batman-adv/fragmentation.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index a9fc6537214b..6ce3c84a7e55 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -231,19 +231,13 @@ err: | |||
231 | * Returns the merged skb or NULL on error. | 231 | * Returns the merged skb or NULL on error. |
232 | */ | 232 | */ |
233 | static struct sk_buff * | 233 | static struct sk_buff * |
234 | batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) | 234 | batadv_frag_merge_packets(struct hlist_head *chain) |
235 | { | 235 | { |
236 | struct batadv_frag_packet *packet; | 236 | struct batadv_frag_packet *packet; |
237 | struct batadv_frag_list_entry *entry; | 237 | struct batadv_frag_list_entry *entry; |
238 | struct sk_buff *skb_out = NULL; | 238 | struct sk_buff *skb_out = NULL; |
239 | int size, hdr_size = sizeof(struct batadv_frag_packet); | 239 | int size, hdr_size = sizeof(struct batadv_frag_packet); |
240 | 240 | ||
241 | /* Make sure incoming skb has non-bogus data. */ | ||
242 | packet = (struct batadv_frag_packet *)skb->data; | ||
243 | size = ntohs(packet->total_size); | ||
244 | if (size > batadv_frag_size_limit()) | ||
245 | goto free; | ||
246 | |||
247 | /* Remove first entry, as this is the destination for the rest of the | 241 | /* Remove first entry, as this is the destination for the rest of the |
248 | * fragments. | 242 | * fragments. |
249 | */ | 243 | */ |
@@ -252,6 +246,9 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) | |||
252 | skb_out = entry->skb; | 246 | skb_out = entry->skb; |
253 | kfree(entry); | 247 | kfree(entry); |
254 | 248 | ||
249 | packet = (struct batadv_frag_packet *)skb_out->data; | ||
250 | size = ntohs(packet->total_size); | ||
251 | |||
255 | /* Make room for the rest of the fragments. */ | 252 | /* Make room for the rest of the fragments. */ |
256 | if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { | 253 | if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { |
257 | kfree_skb(skb_out); | 254 | kfree_skb(skb_out); |
@@ -307,7 +304,7 @@ bool batadv_frag_skb_buffer(struct sk_buff **skb, | |||
307 | if (hlist_empty(&head)) | 304 | if (hlist_empty(&head)) |
308 | goto out; | 305 | goto out; |
309 | 306 | ||
310 | skb_out = batadv_frag_merge_packets(&head, *skb); | 307 | skb_out = batadv_frag_merge_packets(&head); |
311 | if (!skb_out) | 308 | if (!skb_out) |
312 | goto out_err; | 309 | goto out_err; |
313 | 310 | ||