ipv6: translate ICMP_TIME_EXCEEDED to ICMPV6_TIME_EXCEED

For better traceroute/mtr support for SIT and GRE tunnels,
we translate IPV4 ICMP ICMP_TIME_EXCEEDED to ICMPV6_TIME_EXCEED

We also have to translate the IPv4 source IP address of ICMP
message to IPv6 v4mapped.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 07bc63c..867aebc 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -564,8 +564,9 @@
  *  Either an IPv4 header for SIT encap
  *         an IPv4 header + GRE header for GRE encap
  */
-int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs)
+int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type)
 {
+	struct in6_addr temp_saddr;
 	struct rt6_info *rt;
 	struct sk_buff *skb2;
 
@@ -586,8 +587,13 @@
 	if (rt && rt->dst.dev)
 		skb2->dev = rt->dst.dev;
 
-	icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
-
+	ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, &temp_saddr);
+	if (type == ICMP_TIME_EXCEEDED)
+		icmp6_send(skb2, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
+			   0, &temp_saddr);
+	else
+		icmp6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH,
+			   0, &temp_saddr);
 	if (rt)
 		ip6_rt_put(rt);