ICMPv6: treat dest unreachable codes 5 and 6 as EACCES, not EPROTO
authorJiri Bohac <jbohac@suse.cz>
Fri, 30 Aug 2013 09:18:45 +0000 (11:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Sep 2013 13:02:10 +0000 (06:02 -0700)
[ Upstream commit 61e76b178dbe7145e8d6afa84bb4ccea71918994 ]

RFC 4443 has defined two additional codes for ICMPv6 type 1 (destination
unreachable) messages:
        5 - Source address failed ingress/egress policy
6 - Reject route to destination

Now they are treated as protocol error and icmpv6_err_convert() converts them
to EPROTO.

RFC 4443 says:
"Codes 5 and 6 are more informative subsets of code 1."

Treat codes 5 and 6 as code 1 (EACCES)

Btw, connect() returning -EPROTO confuses firefox, so that fallback to
other/IPv4 addresses does not work:
https://bugzilla.mozilla.org/show_bug.cgi?id=910773

Signed-off-by: Jiri Bohac <jbohac@suse.cz>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/icmpv6.h
net/ipv6/icmp.c

index ba45e6b..f5a21d0 100644 (file)
@@ -123,6 +123,8 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb)
 #define ICMPV6_NOT_NEIGHBOUR           2
 #define ICMPV6_ADDR_UNREACH            3
 #define ICMPV6_PORT_UNREACH            4
+#define ICMPV6_POLICY_FAIL             5
+#define ICMPV6_REJECT_ROUTE            6
 
 /*
  *     Codes for Time Exceeded
index 27ac95a..dbf20f6 100644 (file)
@@ -917,6 +917,14 @@ static const struct icmp6_err {
                .err    = ECONNREFUSED,
                .fatal  = 1,
        },
+       {       /* POLICY_FAIL */
+               .err    = EACCES,
+               .fatal  = 1,
+       },
+       {       /* REJECT_ROUTE */
+               .err    = EACCES,
+               .fatal  = 1,
+       },
 };
 
 int icmpv6_err_convert(u8 type, u8 code, int *err)
@@ -928,7 +936,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err)
        switch (type) {
        case ICMPV6_DEST_UNREACH:
                fatal = 1;
-               if (code <= ICMPV6_PORT_UNREACH) {
+               if (code < ARRAY_SIZE(tab_unreach)) {
                        *err  = tab_unreach[code].err;
                        fatal = tab_unreach[code].fatal;
                }