net: Convert protocol error handlers from void to int
authorStefano Brivio <sbrivio@redhat.com>
Thu, 8 Nov 2018 11:19:21 +0000 (12:19 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Nov 2018 01:13:08 +0000 (17:13 -0800)
We'll need this to handle ICMP errors for tunnels without a sending socket
(i.e. FoU and GUE). There, we might have to look up different types of IP
tunnels, registered as network protocols, before we get a match, so we
want this for the error handlers of IPPROTO_IPIP and IPPROTO_IPV6 in both
inet_protos and inet6_protos. These error codes will be used in the next
patch.

For consistency, return sensible error codes in protocol error handlers
whenever handlers can't handle errors because, even if valid, they don't
match a protocol or any of its states.

This has no effect on existing error handling paths.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
27 files changed:
include/net/icmp.h
include/net/protocol.h
include/net/sctp/sctp.h
include/net/tcp.h
include/net/udp.h
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ipv4/gre_demux.c
net/ipv4/icmp.c
net/ipv4/ip_gre.c
net/ipv4/ipip.c
net/ipv4/tcp_ipv4.c
net/ipv4/tunnel4.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv4/udplite.c
net/ipv4/xfrm4_protocol.c
net/ipv6/icmp.c
net/ipv6/ip6_gre.c
net/ipv6/tcp_ipv6.c
net/ipv6/tunnel6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c
net/ipv6/xfrm6_protocol.c
net/sctp/input.c
net/sctp/ipv6.c

index 3ef2743a8eecc742d05b369914af22111122af4f..6ac3a5bd0117cda508f379c001351e20c63ef727 100644 (file)
@@ -41,7 +41,7 @@ struct net;
 
 void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
 int icmp_rcv(struct sk_buff *skb);
-void icmp_err(struct sk_buff *skb, u32 info);
+int icmp_err(struct sk_buff *skb, u32 info);
 int icmp_init(void);
 void icmp_out_count(struct net *net, unsigned char type);
 
index 4fc75f7ae23beb47674b04df27ac6ef4594679fe..92b3eaad60888963d3dce6a637f06582829ca883 100644 (file)
@@ -42,7 +42,10 @@ struct net_protocol {
        int                     (*early_demux)(struct sk_buff *skb);
        int                     (*early_demux_handler)(struct sk_buff *skb);
        int                     (*handler)(struct sk_buff *skb);
-       void                    (*err_handler)(struct sk_buff *skb, u32 info);
+
+       /* This returns an error if we weren't able to handle the error. */
+       int                     (*err_handler)(struct sk_buff *skb, u32 info);
+
        unsigned int            no_policy:1,
                                netns_ok:1,
                                /* does the protocol do more stringent
@@ -58,10 +61,12 @@ struct inet6_protocol {
        void    (*early_demux_handler)(struct sk_buff *skb);
        int     (*handler)(struct sk_buff *skb);
 
-       void    (*err_handler)(struct sk_buff *skb,
+       /* This returns an error if we weren't able to handle the error. */
+       int     (*err_handler)(struct sk_buff *skb,
                               struct inet6_skb_parm *opt,
                               u8 type, u8 code, int offset,
                               __be32 info);
+
        unsigned int    flags;  /* INET6_PROTO_xxx */
 };
 
index 8c2caa370e0f683ea764bc0d72da6dfa93699673..9a3b48a35e90c777669a1037882624fcbd777222 100644 (file)
@@ -151,7 +151,7 @@ int sctp_primitive_RECONF(struct net *net, struct sctp_association *asoc,
  * sctp/input.c
  */
 int sctp_rcv(struct sk_buff *skb);
-void sctp_v4_err(struct sk_buff *skb, u32 info);
+int sctp_v4_err(struct sk_buff *skb, u32 info);
 void sctp_hash_endpoint(struct sctp_endpoint *);
 void sctp_unhash_endpoint(struct sctp_endpoint *);
 struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
index a18914d204864e3016fe8121ec7065da6696f9ef..4743836bed2e2944c041b25be33cd6635096b809 100644 (file)
@@ -313,7 +313,7 @@ extern struct proto tcp_prot;
 
 void tcp_tasklet_init(void);
 
-void tcp_v4_err(struct sk_buff *skb, u32);
+int tcp_v4_err(struct sk_buff *skb, u32);
 
 void tcp_shutdown(struct sock *sk, int how);
 
index eccca2325ee6def47cd4c8f4203ec72627b89a34..fd6d948755c81a5a48838bc4439a778e87542304 100644 (file)
@@ -283,7 +283,7 @@ bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
 int udp_get_port(struct sock *sk, unsigned short snum,
                 int (*saddr_cmp)(const struct sock *,
                                  const struct sock *));
-void udp_err(struct sk_buff *, u32);
+int udp_err(struct sk_buff *, u32);
 int udp_abort(struct sock *sk, int err);
 int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
 int udp_push_pending_frames(struct sock *sk);
index 8e08cea6f17866b5fb1619f570de747c6a837cbd..26a21d97b6b078558b125134ebe326bf27dc08d6 100644 (file)
@@ -231,7 +231,7 @@ EXPORT_SYMBOL(dccp_req_err);
  * check at all. A more general error queue to queue errors for later handling
  * is probably better.
  */
-static void dccp_v4_err(struct sk_buff *skb, u32 info)
+static int dccp_v4_err(struct sk_buff *skb, u32 info)
 {
        const struct iphdr *iph = (struct iphdr *)skb->data;
        const u8 offset = iph->ihl << 2;
@@ -259,16 +259,18 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
                                       inet_iif(skb), 0);
        if (!sk) {
                __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
-               return;
+               return -ENOENT;
        }
 
        if (sk->sk_state == DCCP_TIME_WAIT) {
                inet_twsk_put(inet_twsk(sk));
-               return;
+               return 0;
        }
        seq = dccp_hdr_seq(dh);
-       if (sk->sk_state == DCCP_NEW_SYN_RECV)
-               return dccp_req_err(sk, seq);
+       if (sk->sk_state == DCCP_NEW_SYN_RECV) {
+               dccp_req_err(sk, seq);
+               return 0;
+       }
 
        bh_lock_sock(sk);
        /* If too many ICMPs get dropped on busy
@@ -357,6 +359,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
+       return 0;
 }
 
 static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,
index 6344f1b18a6a1b30cd2f3c559987a2c9e9546f81..d5740bad5b1811cd42e44fb3b0da6edabbf18095 100644 (file)
@@ -68,7 +68,7 @@ static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
 
 }
 
-static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        u8 type, u8 code, int offset, __be32 info)
 {
        const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
@@ -96,16 +96,18 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (!sk) {
                __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
                                  ICMP6_MIB_INERRORS);
-               return;
+               return -ENOENT;
        }
 
        if (sk->sk_state == DCCP_TIME_WAIT) {
                inet_twsk_put(inet_twsk(sk));
-               return;
+               return 0;
        }
        seq = dccp_hdr_seq(dh);
-       if (sk->sk_state == DCCP_NEW_SYN_RECV)
-               return dccp_req_err(sk, seq);
+       if (sk->sk_state == DCCP_NEW_SYN_RECV) {
+               dccp_req_err(sk, seq);
+               return 0;
+       }
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk))
@@ -183,6 +185,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
+       return 0;
 }
 
 
index 7efe740c06ebff66d5e50f1cc067bc5973fc58e3..a4bf22ee3aedb746c999a20a4e6f0bd9e0ccbfe0 100644 (file)
@@ -151,20 +151,25 @@ drop:
        return NET_RX_DROP;
 }
 
-static void gre_err(struct sk_buff *skb, u32 info)
+static int gre_err(struct sk_buff *skb, u32 info)
 {
        const struct gre_protocol *proto;
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f;
+       int err = 0;
 
        if (ver >= GREPROTO_MAX)
-               return;
+               return -EINVAL;
 
        rcu_read_lock();
        proto = rcu_dereference(gre_proto[ver]);
        if (proto && proto->err_handler)
                proto->err_handler(skb, info);
+       else
+               err = -EPROTONOSUPPORT;
        rcu_read_unlock();
+
+       return err;
 }
 
 static const struct net_protocol net_gre_protocol = {
index d832beed6e3a3d382f96ce1de94f3ac97aeed10b..065997f414e61e22a31e663f89bd642800cf72b4 100644 (file)
@@ -1079,7 +1079,7 @@ error:
        goto drop;
 }
 
-void icmp_err(struct sk_buff *skb, u32 info)
+int icmp_err(struct sk_buff *skb, u32 info)
 {
        struct iphdr *iph = (struct iphdr *)skb->data;
        int offset = iph->ihl<<2;
@@ -1094,13 +1094,15 @@ void icmp_err(struct sk_buff *skb, u32 info)
         */
        if (icmph->type != ICMP_ECHOREPLY) {
                ping_err(skb, offset, info);
-               return;
+               return 0;
        }
 
        if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
                ipv4_update_pmtu(skb, net, info, 0, IPPROTO_ICMP);
        else if (type == ICMP_REDIRECT)
                ipv4_redirect(skb, net, 0, IPPROTO_ICMP);
+
+       return 0;
 }
 
 /*
index 2c67af644e64bcffb8a48ebbf9289b699e56482f..76a9a5f7a40e6ded698cb4f8d73c1437179083de 100644 (file)
@@ -121,8 +121,8 @@ static unsigned int ipgre_net_id __read_mostly;
 static unsigned int gre_tap_net_id __read_mostly;
 static unsigned int erspan_net_id __read_mostly;
 
-static void ipgre_err(struct sk_buff *skb, u32 info,
-                     const struct tnl_ptk_info *tpi)
+static int ipgre_err(struct sk_buff *skb, u32 info,
+                    const struct tnl_ptk_info *tpi)
 {
 
        /* All the routers (except for Linux) return only
@@ -146,17 +146,32 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
        unsigned int data_len = 0;
        struct ip_tunnel *t;
 
+       if (tpi->proto == htons(ETH_P_TEB))
+               itn = net_generic(net, gre_tap_net_id);
+       else if (tpi->proto == htons(ETH_P_ERSPAN) ||
+                tpi->proto == htons(ETH_P_ERSPAN2))
+               itn = net_generic(net, erspan_net_id);
+       else
+               itn = net_generic(net, ipgre_net_id);
+
+       iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
+       t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
+                            iph->daddr, iph->saddr, tpi->key);
+
+       if (!t)
+               return -ENOENT;
+
        switch (type) {
        default:
        case ICMP_PARAMETERPROB:
-               return;
+               return 0;
 
        case ICMP_DEST_UNREACH:
                switch (code) {
                case ICMP_SR_FAILED:
                case ICMP_PORT_UNREACH:
                        /* Impossible event. */
-                       return;
+                       return 0;
                default:
                        /* All others are translated to HOST_UNREACH.
                           rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -168,7 +183,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
 
        case ICMP_TIME_EXCEEDED:
                if (code != ICMP_EXC_TTL)
-                       return;
+                       return 0;
                data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
                break;
 
@@ -176,40 +191,27 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
                break;
        }
 
-       if (tpi->proto == htons(ETH_P_TEB))
-               itn = net_generic(net, gre_tap_net_id);
-       else if (tpi->proto == htons(ETH_P_ERSPAN) ||
-                tpi->proto == htons(ETH_P_ERSPAN2))
-               itn = net_generic(net, erspan_net_id);
-       else
-               itn = net_generic(net, ipgre_net_id);
-
-       iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
-       t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
-                            iph->daddr, iph->saddr, tpi->key);
-
-       if (!t)
-               return;
-
 #if IS_ENABLED(CONFIG_IPV6)
        if (tpi->proto == htons(ETH_P_IPV6) &&
            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
                                       type, data_len))
-               return;
+               return 0;
 #endif
 
        if (t->parms.iph.daddr == 0 ||
            ipv4_is_multicast(t->parms.iph.daddr))
-               return;
+               return 0;
 
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
-               return;
+               return 0;
 
        if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
                t->err_count++;
        else
                t->err_count = 1;
        t->err_time = jiffies;
+
+       return 0;
 }
 
 static void gre_err(struct sk_buff *skb, u32 info)
index e65287c27e3d85f17a03d7958f197b54528b9d10..57c5dd283a2c166ea47e1d9aea32331bbb7198ab 100644 (file)
@@ -140,6 +140,13 @@ static int ipip_err(struct sk_buff *skb, u32 info)
        struct ip_tunnel *t;
        int err = 0;
 
+       t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+                            iph->daddr, iph->saddr, 0);
+       if (!t) {
+               err = -ENOENT;
+               goto out;
+       }
+
        switch (type) {
        case ICMP_DEST_UNREACH:
                switch (code) {
@@ -167,13 +174,6 @@ static int ipip_err(struct sk_buff *skb, u32 info)
                goto out;
        }
 
-       t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
-                            iph->daddr, iph->saddr, 0);
-       if (!t) {
-               err = -ENOENT;
-               goto out;
-       }
-
        if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
                ipv4_update_pmtu(skb, net, info, t->parms.link, iph->protocol);
                goto out;
index de47038afdf0261f964f346fe3b3febf9b1652ce..a336787d75e5a2e9146383d3b4b433ce838a201c 100644 (file)
@@ -423,7 +423,7 @@ EXPORT_SYMBOL(tcp_req_err);
  *
  */
 
-void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
+int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 {
        const struct iphdr *iph = (const struct iphdr *)icmp_skb->data;
        struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
@@ -446,20 +446,21 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                                       inet_iif(icmp_skb), 0);
        if (!sk) {
                __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
-               return;
+               return -ENOENT;
        }
        if (sk->sk_state == TCP_TIME_WAIT) {
                inet_twsk_put(inet_twsk(sk));
-               return;
+               return 0;
        }
        seq = ntohl(th->seq);
-       if (sk->sk_state == TCP_NEW_SYN_RECV)
-               return tcp_req_err(sk, seq,
-                                 type == ICMP_PARAMETERPROB ||
-                                 type == ICMP_TIME_EXCEEDED ||
-                                 (type == ICMP_DEST_UNREACH &&
-                                  (code == ICMP_NET_UNREACH ||
-                                   code == ICMP_HOST_UNREACH)));
+       if (sk->sk_state == TCP_NEW_SYN_RECV) {
+               tcp_req_err(sk, seq, type == ICMP_PARAMETERPROB ||
+                                    type == ICMP_TIME_EXCEEDED ||
+                                    (type == ICMP_DEST_UNREACH &&
+                                     (code == ICMP_NET_UNREACH ||
+                                      code == ICMP_HOST_UNREACH)));
+               return 0;
+       }
 
        bh_lock_sock(sk);
        /* If too many ICMPs get dropped on busy
@@ -613,6 +614,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
+       return 0;
 }
 
 void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr)
index c0630013c1aed55b9a515079eaa613ed6957a667..33bf8e9c86630e5bb582bcf9dac803e4a26cf27b 100644 (file)
@@ -149,34 +149,40 @@ drop:
 }
 #endif
 
-static void tunnel4_err(struct sk_buff *skb, u32 info)
+static int tunnel4_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm_tunnel *handler;
 
        for_each_tunnel_rcu(tunnel4_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static void tunnel64_err(struct sk_buff *skb, u32 info)
+static int tunnel64_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm_tunnel *handler;
 
        for_each_tunnel_rcu(tunnel64_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 #endif
 
 #if IS_ENABLED(CONFIG_MPLS)
-static void tunnelmpls4_err(struct sk_buff *skb, u32 info)
+static int tunnelmpls4_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm_tunnel *handler;
 
        for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 #endif
 
index ce759b61f6cde206fe060bc1ef41929cbf663506..a505ee5eb92c35b2c0ad3f0a8b22fa1c32de547b 100644 (file)
@@ -650,7 +650,7 @@ static struct sock *__udp4_lib_err_encap(struct net *net,
  * to find the appropriate port.
  */
 
-void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
+int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 {
        struct inet_sock *inet;
        const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -673,7 +673,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 
                if (!sk) {
                        __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
-                       return;
+                       return -ENOENT;
                }
                tunnel = true;
        }
@@ -731,12 +731,12 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
-       return;
+       return 0;
 }
 
-void udp_err(struct sk_buff *skb, u32 info)
+int udp_err(struct sk_buff *skb, u32 info)
 {
-       __udp4_lib_err(skb, info, &udp_table);
+       return __udp4_lib_err(skb, info, &udp_table);
 }
 
 /*
index e7d18b140287f013d2b8c043a982a44bee8f91dc..3226726554196ec42e84819bae2b8ee66f2bdf5b 100644 (file)
@@ -7,7 +7,7 @@
 #include <net/inet_common.h>
 
 int __udp4_lib_rcv(struct sk_buff *, struct udp_table *, int);
-void __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
+int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
 
 int udp_v4_get_port(struct sock *sk, unsigned short snum);
 
index 8545457752fb95e9239ff683efbdacfd08f8a004..39c7f17d916feadca83fa9c6b1b54b63c64c55b7 100644 (file)
@@ -25,9 +25,9 @@ static int udplite_rcv(struct sk_buff *skb)
        return __udp4_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
 }
 
-static void udplite_err(struct sk_buff *skb, u32 info)
+static int udplite_err(struct sk_buff *skb, u32 info)
 {
-       __udp4_lib_err(skb, info, &udplite_table);
+       return __udp4_lib_err(skb, info, &udplite_table);
 }
 
 static const struct net_protocol udplite_protocol = {
index 8dd0e6ab86065f4e5e17bcd6d119def4677a2b86..35c54865dc42399da6be67e036692ed56b0ba333 100644 (file)
@@ -106,13 +106,15 @@ static int xfrm4_esp_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm4_esp_err(struct sk_buff *skb, u32 info)
+static int xfrm4_esp_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm4_protocol *handler;
 
        for_each_protocol_rcu(esp4_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static int xfrm4_ah_rcv(struct sk_buff *skb)
@@ -132,13 +134,15 @@ static int xfrm4_ah_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm4_ah_err(struct sk_buff *skb, u32 info)
+static int xfrm4_ah_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm4_protocol *handler;
 
        for_each_protocol_rcu(ah4_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static int xfrm4_ipcomp_rcv(struct sk_buff *skb)
@@ -158,13 +162,15 @@ static int xfrm4_ipcomp_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm4_ipcomp_err(struct sk_buff *skb, u32 info)
+static int xfrm4_ipcomp_err(struct sk_buff *skb, u32 info)
 {
        struct xfrm4_protocol *handler;
 
        for_each_protocol_rcu(ipcomp4_handlers, handler)
                if (!handler->err_handler(skb, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static const struct net_protocol esp4_protocol = {
index c9c53ade55c3cee53ffed639aed8eb0f3e5a0f76..5d7aa2c2770ca2b4981d2dd211c3cf0a79a6f9e2 100644 (file)
@@ -84,7 +84,7 @@ static inline struct sock *icmpv6_sk(struct net *net)
        return net->ipv6.icmp_sk[smp_processor_id()];
 }
 
-static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                       u8 type, u8 code, int offset, __be32 info)
 {
        /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
@@ -100,6 +100,8 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (!(type & ICMPV6_INFOMSG_MASK))
                if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
                        ping_err(skb, offset, ntohl(info));
+
+       return 0;
 }
 
 static int icmpv6_rcv(struct sk_buff *skb);
index 515adbdba1d278bf7773b78d42957679418ec0d7..81b69bcee7146276e05238e2811935d69d6a95d3 100644 (file)
@@ -423,7 +423,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
 }
 
 
-static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                       u8 type, u8 code, int offset, __be32 info)
 {
        struct net *net = dev_net(skb->dev);
@@ -433,13 +433,13 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IPV6),
                             offset) < 0)
-               return;
+               return -EINVAL;
 
        ipv6h = (const struct ipv6hdr *)skb->data;
        t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
                                 tpi.key, tpi.proto);
        if (!t)
-               return;
+               return -ENOENT;
 
        switch (type) {
                struct ipv6_tlv_tnl_enc_lim *tel;
@@ -449,14 +449,14 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                                    t->parms.name);
                if (code != ICMPV6_PORT_UNREACH)
                        break;
-               return;
+               return 0;
        case ICMPV6_TIME_EXCEED:
                if (code == ICMPV6_EXC_HOPLIMIT) {
                        net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
                                            t->parms.name);
                        break;
                }
-               return;
+               return 0;
        case ICMPV6_PARAMPROB:
                teli = 0;
                if (code == ICMPV6_HDR_FIELD)
@@ -472,14 +472,14 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
                                            t->parms.name);
                }
-               return;
+               return 0;
        case ICMPV6_PKT_TOOBIG:
                ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
-               return;
+               return 0;
        case NDISC_REDIRECT:
                ip6_redirect(skb, net, skb->dev->ifindex, 0,
                             sock_net_uid(net, NULL));
-               return;
+               return 0;
        }
 
        if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO))
@@ -487,6 +487,8 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        else
                t->err_count = 1;
        t->err_time = jiffies;
+
+       return 0;
 }
 
 static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
index 03e6b7a2bc530d1a19c565f00a03575b898b6f88..a3f559162521543f948894bd6905342ff2401d6c 100644 (file)
@@ -349,7 +349,7 @@ static void tcp_v6_mtu_reduced(struct sock *sk)
        }
 }
 
-static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                u8 type, u8 code, int offset, __be32 info)
 {
        const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
@@ -371,17 +371,19 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (!sk) {
                __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
                                  ICMP6_MIB_INERRORS);
-               return;
+               return -ENOENT;
        }
 
        if (sk->sk_state == TCP_TIME_WAIT) {
                inet_twsk_put(inet_twsk(sk));
-               return;
+               return 0;
        }
        seq = ntohl(th->seq);
        fatal = icmpv6_err_convert(type, code, &err);
-       if (sk->sk_state == TCP_NEW_SYN_RECV)
-               return tcp_req_err(sk, seq, fatal);
+       if (sk->sk_state == TCP_NEW_SYN_RECV) {
+               tcp_req_err(sk, seq, fatal);
+               return 0;
+       }
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
@@ -467,6 +469,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
+       return 0;
 }
 
 
index dae25cad05cd788146321016597a7badb53ef3d4..1991dede736771d60719b103ec1bfb31f2e12b7b 100644 (file)
@@ -134,24 +134,28 @@ drop:
        return 0;
 }
 
-static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        u8 type, u8 code, int offset, __be32 info)
 {
        struct xfrm6_tunnel *handler;
 
        for_each_tunnel_rcu(tunnel6_handlers, handler)
                if (!handler->err_handler(skb, opt, type, code, offset, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
-static void tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                         u8 type, u8 code, int offset, __be32 info)
 {
        struct xfrm6_tunnel *handler;
 
        for_each_tunnel_rcu(tunnel46_handlers, handler)
                if (!handler->err_handler(skb, opt, type, code, offset, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static const struct inet6_protocol tunnel6_protocol = {
index 1216c920f945999d3d346c01cbaaefec3a1abfc9..61316ec48b51ec16ef590c9a5a1eabbb7d22e60b 100644 (file)
@@ -517,9 +517,9 @@ static struct sock *__udp6_lib_err_encap(struct net *net,
        return sk;
 }
 
-void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-                   u8 type, u8 code, int offset, __be32 info,
-                   struct udp_table *udptable)
+int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                  u8 type, u8 code, int offset, __be32 info,
+                  struct udp_table *udptable)
 {
        struct ipv6_pinfo *np;
        const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
@@ -544,7 +544,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                if (!sk) {
                        __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
                                          ICMP6_MIB_INERRORS);
-                       return;
+                       return -ENOENT;
                }
                tunnel = true;
        }
@@ -583,7 +583,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
-       return;
+       return 0;
 }
 
 static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
@@ -614,11 +614,11 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        return 0;
 }
 
-static __inline__ void udpv6_err(struct sk_buff *skb,
-                                struct inet6_skb_parm *opt, u8 type,
-                                u8 code, int offset, __be32 info)
+static __inline__ int udpv6_err(struct sk_buff *skb,
+                               struct inet6_skb_parm *opt, u8 type,
+                               u8 code, int offset, __be32 info)
 {
-       __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table);
+       return __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table);
 }
 
 static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
index 7903e21c178b94f1a58faf4362609908b64e5fa3..5730e6503cb496c6adfcada286ac24b4bab65ab8 100644 (file)
@@ -9,8 +9,8 @@
 #include <net/transp_v6.h>
 
 int __udp6_lib_rcv(struct sk_buff *, struct udp_table *, int);
-void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
-                   __be32, struct udp_table *);
+int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
+                  __be32, struct udp_table *);
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum);
 
index 5000ad6878e6f7b8bfa3d4823f38ca8a9b0e7043..a125aebc29e5e9d2874b3c7bd5f1f1e9970fda67 100644 (file)
@@ -20,11 +20,12 @@ static int udplitev6_rcv(struct sk_buff *skb)
        return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
 }
 
-static void udplitev6_err(struct sk_buff *skb,
+static int udplitev6_err(struct sk_buff *skb,
                          struct inet6_skb_parm *opt,
                          u8 type, u8 code, int offset, __be32 info)
 {
-       __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table);
+       return __udp6_lib_err(skb, opt, type, code, offset, info,
+                             &udplite_table);
 }
 
 static const struct inet6_protocol udplitev6_protocol = {
index b2dc8ce493784c7f824d7a0db4b16947ad7512c5..cc979b702c898cb32405edd78d74dba9e1ac849e 100644 (file)
@@ -80,14 +80,16 @@ static int xfrm6_esp_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                          u8 type, u8 code, int offset, __be32 info)
 {
        struct xfrm6_protocol *handler;
 
        for_each_protocol_rcu(esp6_handlers, handler)
                if (!handler->err_handler(skb, opt, type, code, offset, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static int xfrm6_ah_rcv(struct sk_buff *skb)
@@ -107,14 +109,16 @@ static int xfrm6_ah_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                         u8 type, u8 code, int offset, __be32 info)
 {
        struct xfrm6_protocol *handler;
 
        for_each_protocol_rcu(ah6_handlers, handler)
                if (!handler->err_handler(skb, opt, type, code, offset, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
@@ -134,14 +138,16 @@ static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
        return 0;
 }
 
-static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                             u8 type, u8 code, int offset, __be32 info)
 {
        struct xfrm6_protocol *handler;
 
        for_each_protocol_rcu(ipcomp6_handlers, handler)
                if (!handler->err_handler(skb, opt, type, code, offset, info))
-                       break;
+                       return 0;
+
+       return -ENOENT;
 }
 
 static const struct inet6_protocol esp6_protocol = {
index 5c36a99882ed1286a3d30fa178ea8acaacf046e1..7ab08a5b36dcb26e8ba222609d71a826caba9330 100644 (file)
@@ -574,7 +574,7 @@ void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
  * is probably better.
  *
  */
-void sctp_v4_err(struct sk_buff *skb, __u32 info)
+int sctp_v4_err(struct sk_buff *skb, __u32 info)
 {
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        const int ihlen = iph->ihl * 4;
@@ -599,7 +599,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
        skb->transport_header = savesctp;
        if (!sk) {
                __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
-               return;
+               return -ENOENT;
        }
        /* Warning:  The sock lock is held.  Remember to call
         * sctp_err_finish!
@@ -653,6 +653,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 
 out_unlock:
        sctp_err_finish(sk, transport);
+       return 0;
 }
 
 /*
index fc6c5e4bffa540069f70cf33bda2942d7143fcd4..6e27c62646e99feaf8614c9212ca05deefead8ab 100644 (file)
@@ -138,7 +138,7 @@ static struct notifier_block sctp_inet6addr_notifier = {
 };
 
 /* ICMP error handler. */
-static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        u8 type, u8 code, int offset, __be32 info)
 {
        struct inet6_dev *idev;
@@ -147,7 +147,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct sctp_transport *transport;
        struct ipv6_pinfo *np;
        __u16 saveip, savesctp;
-       int err;
+       int err, ret = 0;
        struct net *net = dev_net(skb->dev);
 
        idev = in6_dev_get(skb->dev);
@@ -163,6 +163,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        skb->transport_header = savesctp;
        if (!sk) {
                __ICMP6_INC_STATS(net, idev, ICMP6_MIB_INERRORS);
+               ret = -ENOENT;
                goto out;
        }
 
@@ -202,6 +203,8 @@ out_unlock:
 out:
        if (likely(idev != NULL))
                in6_dev_put(idev);
+
+       return ret;
 }
 
 static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)