Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Dumazet and committed by
David S. Miller
2d7a3b27 5fbba8ac

+13 -7
+1 -1
include/linux/icmpv6.h
··· 18 18 const struct in6_addr *force_saddr); 19 19 extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); 20 20 extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); 21 - int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs); 21 + int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type); 22 22 23 23 #else 24 24
+9 -3
net/ipv6/icmp.c
··· 564 564 * Either an IPv4 header for SIT encap 565 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 570 struct rt6_info *rt; 570 571 struct sk_buff *skb2; 571 572 ··· 587 586 if (rt && rt->dst.dev) 588 587 skb2->dev = rt->dst.dev; 589 588 590 - icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); 591 - 589 + ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, &temp_saddr); 590 + if (type == ICMP_TIME_EXCEEDED) 591 + icmp6_send(skb2, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 592 + 0, &temp_saddr); 593 + else 594 + icmp6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 595 + 0, &temp_saddr); 592 596 if (rt) 593 597 ip6_rt_put(rt); 594 598
+3 -3
net/ipv6/sit.c
··· 535 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 540 goto out; 540 541 541 - err = 0; 542 - if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4)) 542 + if (t->parms.iph.daddr == 0) 543 543 goto out; 544 544 545 545 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)