aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/ipv4/ip_sockglue.c11
-rw-r--r--net/ipv6/datagram.c12
2 files changed, 21 insertions, 2 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 7cfb0893f263..6ddde89996f4 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -432,6 +432,15 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
432 kfree_skb(skb); 432 kfree_skb(skb);
433} 433}
434 434
435/* For some errors we have valid addr_offset even with zero payload and
436 * zero port. Also, addr_offset should be supported if port is set.
437 */
438static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr)
439{
440 return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
441 serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
442}
443
435/* IPv4 supports cmsg on all imcp errors and some timestamps 444/* IPv4 supports cmsg on all imcp errors and some timestamps
436 * 445 *
437 * Timestamp code paths do not initialize the fields expected by cmsg: 446 * Timestamp code paths do not initialize the fields expected by cmsg:
@@ -498,7 +507,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
498 507
499 serr = SKB_EXT_ERR(skb); 508 serr = SKB_EXT_ERR(skb);
500 509
501 if (sin && serr->port) { 510 if (sin && ipv4_datagram_support_addr(serr)) {
502 sin->sin_family = AF_INET; 511 sin->sin_family = AF_INET;
503 sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + 512 sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
504 serr->addr_offset); 513 serr->addr_offset);
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;