ip: factor out protocol delivery helper
authorPaolo Abeni <pabeni@redhat.com>
Wed, 7 Nov 2018 11:38:31 +0000 (12:38 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 8 Nov 2018 00:23:05 +0000 (16:23 -0800)
So that we can re-use it at the UDP level in a later patch

rfc v3 -> v1
 - add the helper declaration into the ip header

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip.h
net/ipv4/ip_input.c

index 462182f..8866bfc 100644 (file)
@@ -155,6 +155,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 void ip_list_rcv(struct list_head *head, struct packet_type *pt,
                 struct net_device *orig_dev);
 int ip_local_deliver(struct sk_buff *skb);
+void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto);
 int ip_mr_input(struct sk_buff *skb);
 int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb);
 int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb);
index 35a786c..72250b4 100644 (file)
@@ -188,51 +188,50 @@ bool ip_call_ra_chain(struct sk_buff *skb)
        return false;
 }
 
-static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
+void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int protocol)
 {
-       __skb_pull(skb, skb_network_header_len(skb));
-
-       rcu_read_lock();
-       {
-               int protocol = ip_hdr(skb)->protocol;
-               const struct net_protocol *ipprot;
-               int raw;
+       const struct net_protocol *ipprot;
+       int raw, ret;
 
-       resubmit:
-               raw = raw_local_deliver(skb, protocol);
+resubmit:
+       raw = raw_local_deliver(skb, protocol);
 
-               ipprot = rcu_dereference(inet_protos[protocol]);
-               if (ipprot) {
-                       int ret;
-
-                       if (!ipprot->no_policy) {
-                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-                                       kfree_skb(skb);
-                                       goto out;
-                               }
-                               nf_reset(skb);
+       ipprot = rcu_dereference(inet_protos[protocol]);
+       if (ipprot) {
+               if (!ipprot->no_policy) {
+                       if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+                               kfree_skb(skb);
+                               return;
                        }
-                       ret = ipprot->handler(skb);
-                       if (ret < 0) {
-                               protocol = -ret;
-                               goto resubmit;
+                       nf_reset(skb);
+               }
+               ret = ipprot->handler(skb);
+               if (ret < 0) {
+                       protocol = -ret;
+                       goto resubmit;
+               }
+               __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
+       } else {
+               if (!raw) {
+                       if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+                               __IP_INC_STATS(net, IPSTATS_MIB_INUNKNOWNPROTOS);
+                               icmp_send(skb, ICMP_DEST_UNREACH,
+                                         ICMP_PROT_UNREACH, 0);
                        }
-                       __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
+                       kfree_skb(skb);
                } else {
-                       if (!raw) {
-                               if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-                                       __IP_INC_STATS(net, IPSTATS_MIB_INUNKNOWNPROTOS);
-                                       icmp_send(skb, ICMP_DEST_UNREACH,
-                                                 ICMP_PROT_UNREACH, 0);
-                               }
-                               kfree_skb(skb);
-                       } else {
-                               __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
-                               consume_skb(skb);
-                       }
+                       __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
+                       consume_skb(skb);
                }
        }
- out:
+}
+
+static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
+{
+       __skb_pull(skb, skb_network_header_len(skb));
+
+       rcu_read_lock();
+       ip_protocol_deliver_rcu(net, skb, ip_hdr(skb)->protocol);
        rcu_read_unlock();
 
        return 0;