diff options
-rw-r--r-- | sys/netinet/ip_icmp.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 340efd4..a157dd5 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -110,6 +110,10 @@ static int icmplim_output = 1; SYSCTL_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW, &icmplim_output, 0, ""); +static char reply_src[IFNAMSIZ+1]; +SYSCTL_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_RW, + &reply_src, IFNAMSIZ, "icmp reply source for non-local packets."); + /* * ICMP broadcast echo sysctl */ @@ -618,6 +622,7 @@ icmp_reflect(m) { struct ip *ip = mtod(m, struct ip *); struct ifaddr *ifa; + struct ifnet *ifn; struct in_ifaddr *ia; struct in_addr t; struct mbuf *opts = 0; @@ -658,6 +663,20 @@ icmp_reflect(m) goto match; } } + /* + * If the incoming packet was not addressed directly to us, use + * designated interface for icmp replies specified by sysctl + * net.inet.icmp.reply_src (default not set). Otherwise continue + * with normal source selection. + */ + if (reply_src[0] != '\0' && (ifn = ifunit(reply_src))) { + TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = ifatoia(ifa); + goto match; + } + } /* * If the packet was transiting through us, use the address of * the interface that is the closest to the packet source. |