Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ICMPv6: treat dest unreachable codes 5 and 6 as EACCES, not EPROTO

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>

authored by

Jiri Bohac and committed by
David S. Miller
61e76b17 a8787645

+11 -1
+2
include/uapi/linux/icmpv6.h
··· 115 115 #define ICMPV6_NOT_NEIGHBOUR 2 116 116 #define ICMPV6_ADDR_UNREACH 3 117 117 #define ICMPV6_PORT_UNREACH 4 118 + #define ICMPV6_POLICY_FAIL 5 119 + #define ICMPV6_REJECT_ROUTE 6 118 120 119 121 /* 120 122 * Codes for Time Exceeded
+9 -1
net/ipv6/icmp.c
··· 940 940 .err = ECONNREFUSED, 941 941 .fatal = 1, 942 942 }, 943 + { /* POLICY_FAIL */ 944 + .err = EACCES, 945 + .fatal = 1, 946 + }, 947 + { /* REJECT_ROUTE */ 948 + .err = EACCES, 949 + .fatal = 1, 950 + }, 943 951 }; 944 952 945 953 int icmpv6_err_convert(u8 type, u8 code, int *err) ··· 959 951 switch (type) { 960 952 case ICMPV6_DEST_UNREACH: 961 953 fatal = 1; 962 - if (code <= ICMPV6_PORT_UNREACH) { 954 + if (code < ARRAY_SIZE(tab_unreach)) { 963 955 *err = tab_unreach[code].err; 964 956 fatal = tab_unreach[code].fatal; 965 957 }