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

Reply via email to