diff options
Diffstat (limited to 'net/ipv4/ip_fragment.c')
| -rw-r--r-- | net/ipv4/ip_fragment.c | 31 | 
1 files changed, 15 insertions, 16 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a1151b8adf3..b1d282f11be 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -223,31 +223,30 @@ static void ip_expire(unsigned long arg)  	if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {  		struct sk_buff *head = qp->q.fragments; +		const struct iphdr *iph; +		int err;  		rcu_read_lock();  		head->dev = dev_get_by_index_rcu(net, qp->iif);  		if (!head->dev)  			goto out_rcu_unlock; +		/* skb dst is stale, drop it, and perform route lookup again */ +		skb_dst_drop(head); +		iph = ip_hdr(head); +		err = ip_route_input_noref(head, iph->daddr, iph->saddr, +					   iph->tos, head->dev); +		if (err) +			goto out_rcu_unlock; +  		/* -		 * Only search router table for the head fragment, -		 * when defraging timeout at PRE_ROUTING HOOK. +		 * Only an end host needs to send an ICMP +		 * "Fragment Reassembly Timeout" message, per RFC792.  		 */ -		if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) { -			const struct iphdr *iph = ip_hdr(head); -			int err = ip_route_input(head, iph->daddr, iph->saddr, -						 iph->tos, head->dev); -			if (unlikely(err)) -				goto out_rcu_unlock; - -			/* -			 * Only an end host needs to send an ICMP -			 * "Fragment Reassembly Timeout" message, per RFC792. -			 */ -			if (skb_rtable(head)->rt_type != RTN_LOCAL) -				goto out_rcu_unlock; +		if (qp->user == IP_DEFRAG_CONNTRACK_IN && +		    skb_rtable(head)->rt_type != RTN_LOCAL) +			goto out_rcu_unlock; -		}  		/* Send an ICMP "Fragment Reassembly Timeout" message. */  		icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);  |