The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ea9113be3f19db02d7108ebb207c2d5ca87e6a76

commit ea9113be3f19db02d7108ebb207c2d5ca87e6a76
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2024-10-28 13:18:30 +0000
Commit:     Kristof Provost <k...@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) {

Reply via email to