diff options
author | Eric Dumazet <edumazet@google.com> | 2016-06-19 00:52:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-19 01:11:39 -0400 |
commit | 2d7a3b276be2d032a6c1a48ced87a474327ee3d3 (patch) | |
tree | 7ec3681b46b8aa456e987f7b0248dd94abafddb6 /net/ipv6 | |
parent | 5fbba8ac9358f1e796c8aedcccc3487364643723 (diff) |
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>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/icmp.c | 12 | ||||
-rw-r--r-- | net/ipv6/sit.c | 6 |
2 files changed, 12 insertions, 6 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 07bc63c23712..867aebc34248 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -564,8 +564,9 @@ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) | |||
564 | * Either an IPv4 header for SIT encap | 564 | * Either an IPv4 header for SIT encap |
565 | * an IPv4 header + GRE header for GRE encap | 565 | * an IPv4 header + GRE header for GRE encap |
566 | */ | 566 | */ |
567 | int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs) | 567 | int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type) |
568 | { | 568 | { |
569 | struct in6_addr temp_saddr; | ||
569 | struct rt6_info *rt; | 570 | struct rt6_info *rt; |
570 | struct sk_buff *skb2; | 571 | struct sk_buff *skb2; |
571 | 572 | ||
@@ -586,8 +587,13 @@ int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs) | |||
586 | if (rt && rt->dst.dev) | 587 | if (rt && rt->dst.dev) |
587 | skb2->dev = rt->dst.dev; | 588 | skb2->dev = rt->dst.dev; |
588 | 589 | ||
589 | icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); | 590 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, &temp_saddr); |
590 | 591 | if (type == ICMP_TIME_EXCEEDED) | |
592 | icmp6_send(skb2, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | ||
593 | 0, &temp_saddr); | ||
594 | else | ||
595 | icmp6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, | ||
596 | 0, &temp_saddr); | ||
591 | if (rt) | 597 | if (rt) |
592 | ip6_rt_put(rt); | 598 | ip6_rt_put(rt); |
593 | 599 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 78e84d6793ee..d7a36114eb50 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -535,11 +535,11 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
535 | goto out; | 535 | goto out; |
536 | } | 536 | } |
537 | 537 | ||
538 | if (t->parms.iph.daddr == 0) | 538 | err = 0; |
539 | if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type)) | ||
539 | goto out; | 540 | goto out; |
540 | 541 | ||
541 | err = 0; | 542 | if (t->parms.iph.daddr == 0) |
542 | if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4)) | ||
543 | goto out; | 543 | goto out; |
544 | 544 | ||
545 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) | 545 | if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) |