Commit 2d7a3b27 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5fbba8ac
...@@ -18,7 +18,7 @@ typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, ...@@ -18,7 +18,7 @@ typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info,
const struct in6_addr *force_saddr); const struct in6_addr *force_saddr);
extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn);
extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn);
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);
#else #else
......
...@@ -564,8 +564,9 @@ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) ...@@ -564,8 +564,9 @@ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos)
* Either an IPv4 header for SIT encap * Either an IPv4 header for SIT encap
* an IPv4 header + GRE header for GRE 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 rt6_info *rt;
struct sk_buff *skb2; struct sk_buff *skb2;
...@@ -586,8 +587,13 @@ int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs) ...@@ -586,8 +587,13 @@ int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs)
if (rt && rt->dst.dev) if (rt && rt->dst.dev)
skb2->dev = 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) if (rt)
ip6_rt_put(rt); ip6_rt_put(rt);
......
...@@ -535,11 +535,11 @@ static int ipip6_err(struct sk_buff *skb, u32 info) ...@@ -535,11 +535,11 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
goto out; goto out;
} }
if (t->parms.iph.daddr == 0) err = 0;
if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type))
goto out; goto out;
err = 0; if (t->parms.iph.daddr == 0)
if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4))
goto out; goto out;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment