Hi,
When pf route-to is used for locally generated packets, they may
have invalid source address. In my case, an ICMP error packet
created by ip_forward() with source 127.0.0.1 is sent out over the
network. Of course this is rejected by th other side.
14:28:02.298099 10.188.220.17 > 10.188.213.72: icmp: echo request [ttl 1]
14:28:02.300410 127.0.0.1 > 10.188.220.17: icmp: time exceeded in-transit
As pf route-to happens after IP source selection based on a different
route, I think the address should be corrected when we get the new
pf route.
ok?
bluhm
Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1056
diff -u -p -r1.1056 pf.c
--- net/pf.c 15 Jan 2018 12:25:03 -0000 1.1056
+++ net/pf.c 15 Jan 2018 12:55:08 -0000
@@ -62,6 +62,7 @@
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_var.h>
@@ -77,6 +78,7 @@
#include <netinet/ip_divert.h>
#ifdef INET6
+#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
@@ -5959,13 +5961,16 @@ pf_route(struct pf_pdesc *pd, struct pf_
ip = mtod(m0, struct ip *);
}
- in_proto_cksum_out(m0, ifp);
-
rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
if (!rtisvalid(rt)) {
ipstat_inc(ips_noroute);
goto bad;
}
+ /* A locally generated packet may have invalid source address. */
+ if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr;
+
+ in_proto_cksum_out(m0, ifp);
if (ntohs(ip->ip_len) <= ifp->if_mtu) {
ip->ip_sum = 0;
@@ -6109,16 +6114,18 @@ pf_route6(struct pf_pdesc *pd, struct pf
}
}
- in6_proto_cksum_out(m0, ifp);
-
if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr))
dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
-
rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
if (!rtisvalid(rt)) {
ip6stat_inc(ip6s_noroute);
goto bad;
}
+ /* A locally generated packet may have invalid source address. */
+ if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src))
+ ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr;
+
+ in6_proto_cksum_out(m0, ifp);
/*
* If packet has been reassembled by PF earlier, we have to