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 */