git: ea9113be3f19 - main - pf: extra route lookup in pf_route(6)()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 17 Dec 2024 10:07:45 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=ea9113be3f19db02d7108ebb207c2d5ca87e6a76 commit ea9113be3f19db02d7108ebb207c2d5ca87e6a76 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2024-10-28 13:18:30 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2024-12-17 10:07:13 +0000 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 --- sys/netpfil/pf/pf.c | 69 ++++++++++++++++++++++++++++++++++++++++------------- 1 file 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) {