aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2024-10-28 13:18:30 +0000
committerKristof Provost <kp@FreeBSD.org>2024-12-17 10:07:13 +0000
commitea9113be3f19db02d7108ebb207c2d5ca87e6a76 (patch)
tree9f1ae2efb7cdb3b446f22ae186a2a66c5f5c2ce0
parentebe11b46988eb27d287272b8c827eb80ebd900ba (diff)
pf: extra route lookup in pf_route(6)()
In the NAT64 case we use pf_route(6)() to emit the translated packet. This requires a new route lookup, so perform this, but only in the NAT64/NAT46 case. Update the destination sockaddr to send packets to the gateway if appropriate. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D47788
-rw-r--r--sys/netpfil/pf/pf.c69
1 files changed, 52 insertions, 17 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 860f9a8fce64..36bb0e1975fa 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -8648,14 +8648,13 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
struct mbuf *m0, *m1, *md;
struct sockaddr_in dst;
struct ip *ip;
- struct ifnet *ifp;
+ struct ifnet *ifp = NULL;
int error = 0;
uint16_t ip_len, ip_off;
uint16_t tmp;
int r_dir;
- KASSERT(m && *m && r && oifp && pd->act.rt_kif,
- ("%s: invalid parameters", __func__));
+ KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__));
SDT_PROBE4(pf, ip, route_to, entry, *m, pd, s, oifp);
@@ -8678,12 +8677,8 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
goto bad_locked;
}
- if ((ifp = pd->act.rt_kif->pfik_ifp) == NULL) {
- m0 = *m;
- *m = NULL;
- SDT_PROBE1(pf, ip, route_to, drop, __LINE__);
- goto bad_locked;
- }
+ if (pd->act.rt_kif != NULL)
+ ifp = pd->act.rt_kif->pfik_ifp;
if (pd->act.rt == PF_DUPTO) {
if ((pd->pf_mtag->flags & PF_MTAG_FLAG_DUPLICATED)) {
@@ -8733,9 +8728,31 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
s->orig_kif = oifp->if_pf_kif;
}
+ if (ifp == NULL && (pd->af != pd->naf)) {
+ /* We're in the AFTO case. Do a route lookup. */
+ struct nhop_object *nh;
+ nh = fib4_lookup(M_GETFIB(*m), ip->ip_dst, 0, NHR_NONE, 0);
+ if (nh) {
+ ifp = nh->nh_ifp;
+
+ /* Use the gateway if needed. */
+ if (nh->nh_flags & NHF_GATEWAY)
+ dst.sin_addr = nh->gw4_sa.sin_addr;
+ else
+ dst.sin_addr = ip->ip_dst;
+ }
+ }
+
PF_STATE_UNLOCK(s);
}
+ if (ifp == NULL) {
+ m0 = *m;
+ *m = NULL;
+ SDT_PROBE1(pf, ip, route_to, drop, __LINE__);
+ goto bad;
+ }
+
if (pd->dir == PF_IN) {
if (pf_test(AF_INET, PF_OUT, PFIL_FWD, ifp, &m0, inp,
&pd->act) != PF_PASS) {
@@ -8887,8 +8904,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
struct ifnet *ifp = NULL;
int r_dir;
- KASSERT(m && *m && r && oifp && pd->act.rt_kif,
- ("%s: invalid parameters", __func__));
+ KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__));
SDT_PROBE4(pf, ip6, route_to, entry, *m, pd, s, oifp);
@@ -8911,12 +8927,8 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
goto bad_locked;
}
- if ((ifp = pd->act.rt_kif->pfik_ifp) == NULL) {
- m0 = *m;
- *m = NULL;
- SDT_PROBE1(pf, ip6, route_to, drop, __LINE__);
- goto bad_locked;
- }
+ if (pd->act.rt_kif != NULL)
+ ifp = pd->act.rt_kif->pfik_ifp;
if (pd->act.rt == PF_DUPTO) {
if ((pd->pf_mtag->flags & PF_MTAG_FLAG_DUPLICATED)) {
@@ -8965,9 +8977,32 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
s->kif = pd->act.rt_kif;
s->orig_kif = oifp->if_pf_kif;
}
+
+ if (ifp == NULL && (pd->af != pd->naf)) {
+ struct nhop_object *nh;
+ nh = fib6_lookup(M_GETFIB(*m), &ip6->ip6_dst, 0, NHR_NONE, 0);
+ if (nh) {
+ ifp = nh->nh_ifp;
+
+ /* Use the gateway if needed. */
+ if (nh->nh_flags & NHF_GATEWAY)
+ bcopy(&dst.sin6_addr, &nh->gw6_sa.sin6_addr,
+ sizeof(dst.sin6_addr));
+ else
+ dst.sin6_addr = ip6->ip6_dst;
+ }
+ }
+
PF_STATE_UNLOCK(s);
}
+ if (ifp == NULL) {
+ m0 = *m;
+ *m = NULL;
+ SDT_PROBE1(pf, ip6, route_to, drop, __LINE__);
+ goto bad;
+ }
+
if (pd->dir == PF_IN) {
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT,
ifp, &m0, inp, &pd->act) != PF_PASS) {