aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2015-06-23 01:34:39 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-07-10 12:49:30 -0400
commit66634bb1c4f1eda70583eddaf8c5e980f05a8fb9 (patch)
tree71e4b98e69cc5533b43fd58da11c3eaa57ef825f /net/ipv6
parent6fc8b947b364ceb6d91e5b6f3e3d22cd9a013ac0 (diff)
ip: report the original address of ICMP messages
[ Upstream commit 34b99df4e6256ddafb663c6de0711dceceddfe0e ] ICMP messages can trigger ICMP and local errors. In this case serr->port is 0 and starting from Linux 4.0 we do not return the original target address to the error queue readers. Add function to define which errors provide addr_offset. With this fix my ping command is not silent anymore. Fixes: c247f0534cc5 ("ip: fix error queue empty skb handling") Signed-off-by: Julian Anastasov <ja@ssi.bg> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/datagram.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 762a58c772b8..62d908e64eeb 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -325,6 +325,16 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
325 kfree_skb(skb); 325 kfree_skb(skb);
326} 326}
327 327
328/* For some errors we have valid addr_offset even with zero payload and
329 * zero port. Also, addr_offset should be supported if port is set.
330 */
331static inline bool ipv6_datagram_support_addr(struct sock_exterr_skb *serr)
332{
333 return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6 ||
334 serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
335 serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
336}
337
328/* IPv6 supports cmsg on all origins aside from SO_EE_ORIGIN_LOCAL. 338/* IPv6 supports cmsg on all origins aside from SO_EE_ORIGIN_LOCAL.
329 * 339 *
330 * At one point, excluding local errors was a quick test to identify icmp/icmp6 340 * At one point, excluding local errors was a quick test to identify icmp/icmp6
@@ -389,7 +399,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
389 399
390 serr = SKB_EXT_ERR(skb); 400 serr = SKB_EXT_ERR(skb);
391 401
392 if (sin && serr->port) { 402 if (sin && ipv6_datagram_support_addr(serr)) {
393 const unsigned char *nh = skb_network_header(skb); 403 const unsigned char *nh = skb_network_header(skb);
394 sin->sin6_family = AF_INET6; 404 sin->sin6_family = AF_INET6;
395 sin->sin6_flowinfo = 0; 405 sin->sin6_flowinfo = 0;