If pf route-to is used for locally generated packets, they may have
authorbluhm <bluhm@openbsd.org>
Tue, 16 Jan 2018 14:48:38 +0000 (14:48 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 16 Jan 2018 14:48:38 +0000 (14:48 +0000)
an invalid source address.  As pf route-to happens after IP source
selection based on a different route, the address should be corrected
after pf has allocated the new route.  Especially loopback addresses
must not appear at outgoing packets.
OK sashan@ visa@

sys/net/pf.c

index fa0a913..0e41120 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1056 2018/01/15 12:25:03 bluhm Exp $ */
+/*     $OpenBSD: pf.c,v 1.1057 2018/01/16 14:48:38 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -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_rule *r, struct pf_state *s)
                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_rule *r, struct pf_state *s)
                }
        }
 
-       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