diff options
Diffstat (limited to 'net/ipv4/ip_input.c')
| -rw-r--r-- | net/ipv4/ip_input.c | 25 | 
1 files changed, 15 insertions, 10 deletions
| diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index fa2dc8f692c6..57fc13c6ab2b 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -311,9 +311,10 @@ drop:  static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  {  	const struct iphdr *iph = ip_hdr(skb); -	struct rtable *rt; +	int (*edemux)(struct sk_buff *skb);  	struct net_device *dev = skb->dev; -	void (*edemux)(struct sk_buff *skb); +	struct rtable *rt; +	int err;  	/* if ingress device is enslaved to an L3 master device pass the  	 * skb to its handler for processing @@ -331,7 +332,9 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  		ipprot = rcu_dereference(inet_protos[protocol]);  		if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) { -			edemux(skb); +			err = edemux(skb); +			if (unlikely(err)) +				goto drop_error;  			/* must reload iph, skb->head might have changed */  			iph = ip_hdr(skb);  		} @@ -342,13 +345,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  	 *	how the packet travels inside Linux networking.  	 */  	if (!skb_valid_dst(skb)) { -		int err = ip_route_input_noref(skb, iph->daddr, iph->saddr, -					       iph->tos, dev); -		if (unlikely(err)) { -			if (err == -EXDEV) -				__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER); -			goto drop; -		} +		err = ip_route_input_noref(skb, iph->daddr, iph->saddr, +					   iph->tos, dev); +		if (unlikely(err)) +			goto drop_error;  	}  #ifdef CONFIG_IP_ROUTE_CLASSID @@ -399,6 +399,11 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  drop:  	kfree_skb(skb);  	return NET_RX_DROP; + +drop_error: +	if (err == -EXDEV) +		__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER); +	goto drop;  }  /* |