ICMP reply uses wrong source address as destination

From: Anders Nilsson Plymoth
Date: Mon Feb 28 2011 - 11:27:54 EST

Dear linux kernel enthusiasts,

I came upon an issue where ICMP reply packets were issued towards the
IP address of the receiving interface, rather than the source IP
Looking at the kernel code, I saw that this is caused by the following
line in net/ipv4/icmp.c function icmp_reply:

daddr = ipc.addr = rt->rt_src;

For most cases the original line of code is ok, but in some situations
doesn't arrive to the kernel from the network device, but through some
other mechanism such as a userspace application. In these cases the
receiving device in the skb appears to be the loopback interface, not
a physical device. icmp_reply will thus issue the reply to the
loopback IP address, rather than the source IP address as it should.

While googling to see if this issue have been submitted, I found this
two threads that address the same problem:

([PATCH] NETWORKING [IPV4]: Always use source addr in skb to
reply packet) on 17 sep 2007
([PATCH RESEND] networking [ipv4]: fix wrong destination when
reply packetes) on 20 sep 2007).

Nothing came out of these threads, and some of the questions there are
easy to answer; such as this doesn't affect DNAT, and if source IP
address is not set then you should not issue a reply for echo and
timestamp anyway.

As to the statement:
"... which IP address should be used as the source
1. the destination address of the packet that generated the message


2. the IP address that the machine would use by default if the machine
were to generate a new connection to the destination."
These may be relevant questions, but the ICMP RFC clearly states the
answer is 1. 2. may seem relevant to multi-homing, but its not the
role of the ICMP reply to resolve multi-homing issues.
The following code will correct the issue.
   struct iphdr *ip = ip_hdr(skb);
   daddr = ipc.addr = ip->saddr;
The only functions that use icmp_reply are icmp_echo and
icmp_timestamp, and this change do not modify their behavior. After
extensive testing, in regular setups and DNATed situations, I can
verify this change works as intended.
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/