3.16.52-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Paolo Abeni <pab...@redhat.com>

commit 7487449c86c65202b3b725c4524cb48dd65e4e6f upstream.

Currently no error is emitted, but this infrastructure will
used by the next patch to allow source address validation
for mcast sockets.
Since early demux can do a route lookup and an ipv4 route
lookup can return an error code this is consistent with the
current ipv4 route infrastructure.

Signed-off-by: Paolo Abeni <pab...@redhat.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
[bwh: Backported to 3.16:
 - Drop change to net_protocol::early_demux_handler
 - Keep using NET_INC_STATS_BH() in ip_rcv_finish()
 - Fix up additional return statement in udp_v4_early_demux()
 - Adjust context]
Signed-off-by: Ben Hutchings <b...@decadent.org.uk>
---
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -39,7 +39,7 @@
 
 /* This is used to register protocols. */
 struct net_protocol {
-       void                    (*early_demux)(struct sk_buff *skb);
+       int                     (*early_demux)(struct sk_buff *skb);
        int                     (*handler)(struct sk_buff *skb);
        void                    (*err_handler)(struct sk_buff *skb, u32 info);
        unsigned int            no_policy:1,
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -350,7 +350,7 @@ void tcp_v4_err(struct sk_buff *skb, u32
 
 void tcp_shutdown(struct sock *sk, int how);
 
-void tcp_v4_early_demux(struct sk_buff *skb);
+int tcp_v4_early_demux(struct sk_buff *skb);
 int tcp_v4_rcv(struct sk_buff *skb);
 
 int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -177,7 +177,7 @@ int udp_lib_get_port(struct sock *sk, un
                     unsigned int hash2_nulladdr);
 
 /* net/ipv4/udp.c */
-void udp_v4_early_demux(struct sk_buff *skb);
+int udp_v4_early_demux(struct sk_buff *skb);
 int udp_get_port(struct sock *sk, unsigned short snum,
                 int (*saddr_cmp)(const struct sock *,
                                  const struct sock *));
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -313,6 +313,7 @@ static int ip_rcv_finish(struct sk_buff
 {
        const struct iphdr *iph = ip_hdr(skb);
        struct rtable *rt;
+       int err;
 
        if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
                const struct net_protocol *ipprot;
@@ -320,7 +321,9 @@ static int ip_rcv_finish(struct sk_buff
 
                ipprot = rcu_dereference(inet_protos[protocol]);
                if (ipprot && ipprot->early_demux) {
-                       ipprot->early_demux(skb);
+                       err = ipprot->early_demux(skb);
+                       if (unlikely(err))
+                               goto drop_error;
                        /* must reload iph, skb->head might have changed */
                        iph = ip_hdr(skb);
                }
@@ -331,14 +334,10 @@ static int ip_rcv_finish(struct sk_buff
         *      how the packet travels inside Linux networking.
         */
        if (!skb_dst(skb)) {
-               int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                              iph->tos, skb->dev);
-               if (unlikely(err)) {
-                       if (err == -EXDEV)
-                               NET_INC_STATS_BH(dev_net(skb->dev),
-                                                LINUX_MIB_IPRPFILTER);
-                       goto drop;
-               }
+               err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
+                                          iph->tos, skb->dev);
+               if (unlikely(err))
+                       goto drop_error;
        }
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -368,6 +367,11 @@ static int ip_rcv_finish(struct sk_buff
 drop:
        kfree_skb(skb);
        return NET_RX_DROP;
+
+drop_error:
+       if (err == -EXDEV)
+               NET_INC_STATS_BH(dev_net(skb->dev), LINUX_MIB_IPRPFILTER);
+       goto drop;
 }
 
 /*
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1616,23 +1616,23 @@ csum_err:
 }
 EXPORT_SYMBOL(tcp_v4_do_rcv);
 
-void tcp_v4_early_demux(struct sk_buff *skb)
+int tcp_v4_early_demux(struct sk_buff *skb)
 {
        const struct iphdr *iph;
        const struct tcphdr *th;
        struct sock *sk;
 
        if (skb->pkt_type != PACKET_HOST)
-               return;
+               return 0;
 
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct 
tcphdr)))
-               return;
+               return 0;
 
        iph = ip_hdr(skb);
        th = tcp_hdr(skb);
 
        if (th->doff < sizeof(struct tcphdr) / 4)
-               return;
+               return 0;
 
        sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                                       iph->saddr, th->source,
@@ -1651,6 +1651,7 @@ void tcp_v4_early_demux(struct sk_buff *
                                skb_dst_set_noref(skb, dst);
                }
        }
+       return 0;
 }
 
 /* Packet is added to VJ-style prequeue for processing in process
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1950,7 +1950,7 @@ static struct sock *__udp4_lib_demux_loo
        return result;
 }
 
-void udp_v4_early_demux(struct sk_buff *skb)
+int udp_v4_early_demux(struct sk_buff *skb)
 {
        struct net *net = dev_net(skb->dev);
        const struct iphdr *iph;
@@ -1962,7 +1962,7 @@ void udp_v4_early_demux(struct sk_buff *
 
        /* validate the packet */
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct 
udphdr)))
-               return;
+               return 0;
 
        iph = ip_hdr(skb);
        uh = udp_hdr(skb);
@@ -1972,14 +1972,14 @@ void udp_v4_early_demux(struct sk_buff *
                struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
 
                if (!in_dev)
-                       return;
+                       return 0;
 
                /* we are supposed to accept bcast packets */
                if (skb->pkt_type == PACKET_MULTICAST) {
                        ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
                                               iph->protocol);
                        if (!ours)
-                               return;
+                               return 0;
                }
 
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
@@ -1988,11 +1988,11 @@ void udp_v4_early_demux(struct sk_buff *
                sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
                                             uh->source, iph->saddr, dif);
        } else {
-               return;
+               return 0;
        }
 
        if (!sk)
-               return;
+               return 0;
 
        skb->sk = sk;
        skb->destructor = sock_edemux;
@@ -2009,6 +2009,7 @@ void udp_v4_early_demux(struct sk_buff *
                        skb_dst_set_noref(skb, dst);
                }
        }
+       return 0;
 }
 
 int udp_rcv(struct sk_buff *skb)

Reply via email to