Hi,

The !r->rt case is only used by af-to.  pf_route6() calls ip6_output()
to do the work while pf_route() has some custom implementation for
that.  It is simpler to call ip_output() or ip6_output() from
pf_test() directly.

ok?

bluhm

Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.998
diff -u -p -r1.998 pf.c
--- net/pf.c    14 Nov 2016 13:25:00 -0000      1.998
+++ net/pf.c    14 Nov 2016 14:08:57 -0000
@@ -5820,50 +5820,34 @@ pf_route(struct pf_pdesc *pd, struct pf_
        dst->sin_addr = ip->ip_dst;
        rtableid = m0->m_pkthdr.ph_rtableid;
 
-       if (!r->rt) {
-               rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
-               if (rt == NULL) {
-                       ipstat_inc(ips_noroute);
+       if (s == NULL) {
+               bzero(sns, sizeof(sns));
+               if (pf_map_addr(AF_INET, r,
+                   (struct pf_addr *)&ip->ip_src,
+                   &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) {
+                       DPFPRINTF(LOG_ERR,
+                           "pf_route: pf_map_addr() failed.");
                        goto bad;
                }
 
-               ifp = if_get(rt->rt_ifidx);
-
-               if (rt->rt_flags & RTF_GATEWAY)
-                       dst = satosin(rt->rt_gateway);
-
-               m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+               if (!PF_AZERO(&naddr, AF_INET))
+                       dst->sin_addr.s_addr = naddr.v4.s_addr;
+               ifp = r->route.kif ?
+                   r->route.kif->pfik_ifp : NULL;
        } else {
-               if (s == NULL) {
-                       bzero(sns, sizeof(sns));
-                       if (pf_map_addr(AF_INET, r,
-                           (struct pf_addr *)&ip->ip_src,
-                           &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) {
-                               DPFPRINTF(LOG_ERR,
-                                   "pf_route: pf_map_addr() failed.");
-                               goto bad;
-                       }
-
-                       if (!PF_AZERO(&naddr, AF_INET))
-                               dst->sin_addr.s_addr = naddr.v4.s_addr;
-                       ifp = r->route.kif ?
-                           r->route.kif->pfik_ifp : NULL;
-               } else {
-                       if (!PF_AZERO(&s->rt_addr, AF_INET))
-                               dst->sin_addr.s_addr =
-                                   s->rt_addr.v4.s_addr;
-                       ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
-               }
-
-               rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
-               if (rt == NULL) {
-                       ipstat_inc(ips_noroute);
-                       goto bad;
-               }
+               if (!PF_AZERO(&s->rt_addr, AF_INET))
+                       dst->sin_addr.s_addr =
+                           s->rt_addr.v4.s_addr;
+               ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
        }
        if (ifp == NULL)
                goto bad;
 
+       rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
+       if (rt == NULL) {
+               ipstat_inc(ips_noroute);
+               goto bad;
+       }
 
        if (pd->kif->pfik_ifp != ifp) {
                if (pf_test(AF_INET, PF_OUT, ifp, &m0) != PF_PASS)
@@ -5928,8 +5912,6 @@ pf_route(struct pf_pdesc *pd, struct pf_
 done:
        if (r->rt != PF_DUPTO)
                pd->m = NULL;
-       if (!r->rt)
-               if_put(ifp);
        rtfree(rt);
        return;
 
@@ -5982,12 +5964,6 @@ pf_route6(struct pf_pdesc *pd, struct pf
        dst->sin6_addr = ip6->ip6_dst;
        rtableid = m0->m_pkthdr.ph_rtableid;
 
-       if (!r->rt) {
-               m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
-               ip6_output(m0, NULL, NULL, 0, NULL, NULL);
-               goto done;
-       }
-
        if (s == NULL) {
                bzero(sns, sizeof(sns));
                if (pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
@@ -6908,10 +6884,28 @@ done:
                        action = PF_DROP;
                        break;
                }
-               if (pd.naf == AF_INET)
-                       pf_route(&pd, r, s);
-               if (pd.naf == AF_INET6)
-                       pf_route6(&pd, r, s);
+               if (r->rt) {
+                       switch (pd.naf) {
+                       case AF_INET:
+                               pf_route(&pd, r, s);
+                               break;
+                       case AF_INET6:
+                               pf_route6(&pd, r, s);
+                               break;
+                       }
+               }
+               if (pd.m) {
+                       pd.m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+                       switch (pd.naf) {
+                       case AF_INET:
+                               ip_output(pd.m, NULL, NULL, 0, NULL, NULL, 0);
+                               break;
+                       case AF_INET6:
+                               ip6_output(pd.m, NULL, NULL, 0, NULL, NULL);
+                               break;
+                       }
+                       pd.m = NULL;
+               }
                action = PF_PASS;
                break;
 #endif /* INET6 */

Reply via email to