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:54:56 +0000 (06:54 -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/uapi/linux/icmpv6.h
net/ipv6/icmp.c

index e0133c73c30409fd29b1a9ada5ccb6a9118fb2f5..590beda78ea0ffcaa9c72321c9ba1ea893d0e4d3 100644 (file)
@@ -115,6 +115,8 @@ struct icmp6hdr {
 #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 b4ff0a42b8c70248faf1b7298c1bec2cc79368ee..70e704d4900732a4f20492ccdd5723abf18db11c 100644 (file)
@@ -931,6 +931,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)
@@ -942,7 +950,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;
                }