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: | |||
311 | static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | 311 | static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) |
312 | { | 312 | { |
313 | const struct iphdr *iph = ip_hdr(skb); | 313 | const struct iphdr *iph = ip_hdr(skb); |
314 | struct rtable *rt; | 314 | int (*edemux)(struct sk_buff *skb); |
315 | struct net_device *dev = skb->dev; | 315 | struct net_device *dev = skb->dev; |
316 | void (*edemux)(struct sk_buff *skb); | 316 | struct rtable *rt; |
317 | int err; | ||
317 | 318 | ||
318 | /* if ingress device is enslaved to an L3 master device pass the | 319 | /* if ingress device is enslaved to an L3 master device pass the |
319 | * skb to its handler for processing | 320 | * 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) | |||
331 | 332 | ||
332 | ipprot = rcu_dereference(inet_protos[protocol]); | 333 | ipprot = rcu_dereference(inet_protos[protocol]); |
333 | if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) { | 334 | if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) { |
334 | edemux(skb); | 335 | err = edemux(skb); |
336 | if (unlikely(err)) | ||
337 | goto drop_error; | ||
335 | /* must reload iph, skb->head might have changed */ | 338 | /* must reload iph, skb->head might have changed */ |
336 | iph = ip_hdr(skb); | 339 | iph = ip_hdr(skb); |
337 | } | 340 | } |
@@ -342,13 +345,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
342 | * how the packet travels inside Linux networking. | 345 | * how the packet travels inside Linux networking. |
343 | */ | 346 | */ |
344 | if (!skb_valid_dst(skb)) { | 347 | if (!skb_valid_dst(skb)) { |
345 | int err = ip_route_input_noref(skb, iph->daddr, iph->saddr, | 348 | err = ip_route_input_noref(skb, iph->daddr, iph->saddr, |
346 | iph->tos, dev); | 349 | iph->tos, dev); |
347 | if (unlikely(err)) { | 350 | if (unlikely(err)) |
348 | if (err == -EXDEV) | 351 | goto drop_error; |
349 | __NET_INC_STATS(net, LINUX_MIB_IPRPFILTER); | ||
350 | goto drop; | ||
351 | } | ||
352 | } | 352 | } |
353 | 353 | ||
354 | #ifdef CONFIG_IP_ROUTE_CLASSID | 354 | #ifdef CONFIG_IP_ROUTE_CLASSID |
@@ -399,6 +399,11 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
399 | drop: | 399 | drop: |
400 | kfree_skb(skb); | 400 | kfree_skb(skb); |
401 | return NET_RX_DROP; | 401 | return NET_RX_DROP; |
402 | |||
403 | drop_error: | ||
404 | if (err == -EXDEV) | ||
405 | __NET_INC_STATS(net, LINUX_MIB_IPRPFILTER); | ||
406 | goto drop; | ||
402 | } | 407 | } |
403 | 408 | ||
404 | /* | 409 | /* |