From a0866c8d4e955257b45404ca7dec08c4a3148fa8 Mon Sep 17 00:00:00 2001 From: Andre Oppermann Date: Sun, 21 Aug 2005 12:29:39 +0000 Subject: [PATCH] Add an option to have ICMP replies to non-local packets generated with the IP address the packet came through in. This is useful for routers to show in traceroutes the actual path a packet has taken instead of the possibly different return path. The new sysctl is named net.inet.icmp.reply_from_interface and defaults to off. MFC after: 2 weeks --- share/man/man4/icmp.4 | 11 ++++++++++- sys/netinet/ip_icmp.c | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/share/man/man4/icmp.4 b/share/man/man4/icmp.4 index af5c1df1103..335ac730bed 100644 --- a/share/man/man4/icmp.4 +++ b/share/man/man4/icmp.4 @@ -32,7 +32,7 @@ .\" @(#)icmp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd March 21, 2003 +.Dd August 21, 2005 .Dt ICMP 4 .Os .Sh NAME @@ -137,6 +137,15 @@ Defaults to false. An interface name used for the ICMP reply source in response to packets which are not directly addressed to us. By default continue with normal source selection. +.It Va reply_from_interface +.Pq Vt boolean +Use the IP address of the interface the packet came through in for +responses to packets which are not directly addressed to us. +If enabled this rule is processed before all others. +By default continue with normal source selection. +Enabling this option is particularly useful on routers because it +makes external traceroutes show the actual path a packet has taken +instead of the possibly different return path. .El .Sh ERRORS A socket operation may fail with one of the following errors returned: diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 6d1670f6ea8..0cba5941738 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -110,6 +110,11 @@ static char reply_src[IFNAMSIZ]; SYSCTL_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_RW, &reply_src, IFNAMSIZ, "icmp reply source for non-local packets."); +static int icmp_rfi = 0; +SYSCTL_INT(_net_inet_icmp, OID_AUTO, reply_from_interface, CTLFLAG_RW, + &icmp_rfi, 0, "ICMP reply from incoming interface for " + "non-local packets"); + /* * ICMP broadcast echo sysctl */ @@ -623,6 +628,20 @@ icmp_reflect(m) goto match; } } + /* + * If the packet was transiting through us, use the address of + * the interface the packet came through in. If that interface + * doesn't have a suitable IP address, the normal selection + * criteria apply. + */ + if (icmp_rfi && m->m_pkthdr.rcvif != NULL) { + TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = ifatoia(ifa); + goto match; + } + } /* * If the incoming packet was not addressed directly to us, use * designated interface for icmp replies specified by sysctl