diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ip_fragment.c | 14 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 12 |
2 files changed, 20 insertions, 6 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a6445b843ef4..52c273ea05c3 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -248,8 +248,7 @@ static void ip_expire(unsigned long arg) | |||
248 | if (!head->dev) | 248 | if (!head->dev) |
249 | goto out_rcu_unlock; | 249 | goto out_rcu_unlock; |
250 | 250 | ||
251 | /* skb dst is stale, drop it, and perform route lookup again */ | 251 | /* skb has no dst, perform route lookup again */ |
252 | skb_dst_drop(head); | ||
253 | iph = ip_hdr(head); | 252 | iph = ip_hdr(head); |
254 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, | 253 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, |
255 | iph->tos, head->dev); | 254 | iph->tos, head->dev); |
@@ -523,9 +522,16 @@ found: | |||
523 | qp->q.max_size = skb->len + ihl; | 522 | qp->q.max_size = skb->len + ihl; |
524 | 523 | ||
525 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 524 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
526 | qp->q.meat == qp->q.len) | 525 | qp->q.meat == qp->q.len) { |
527 | return ip_frag_reasm(qp, prev, dev); | 526 | unsigned long orefdst = skb->_skb_refdst; |
528 | 527 | ||
528 | skb->_skb_refdst = 0UL; | ||
529 | err = ip_frag_reasm(qp, prev, dev); | ||
530 | skb->_skb_refdst = orefdst; | ||
531 | return err; | ||
532 | } | ||
533 | |||
534 | skb_dst_drop(skb); | ||
529 | inet_frag_lru_move(&qp->q); | 535 | inet_frag_lru_move(&qp->q); |
530 | return -EINPROGRESS; | 536 | return -EINPROGRESS; |
531 | 537 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 196ab9347ad1..0ba10e53a629 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -330,9 +330,17 @@ found: | |||
330 | } | 330 | } |
331 | 331 | ||
332 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 332 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
333 | fq->q.meat == fq->q.len) | 333 | fq->q.meat == fq->q.len) { |
334 | return ip6_frag_reasm(fq, prev, dev); | 334 | int res; |
335 | unsigned long orefdst = skb->_skb_refdst; | ||
336 | |||
337 | skb->_skb_refdst = 0UL; | ||
338 | res = ip6_frag_reasm(fq, prev, dev); | ||
339 | skb->_skb_refdst = orefdst; | ||
340 | return res; | ||
341 | } | ||
335 | 342 | ||
343 | skb_dst_drop(skb); | ||
336 | inet_frag_lru_move(&fq->q); | 344 | inet_frag_lru_move(&fq->q); |
337 | return -1; | 345 | return -1; |
338 | 346 | ||