The branch main has been updated by kp:

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

commit 37c452292132c062a4deb2b136facb9b6a675cf9
Author:     Kristof Provost <[email protected]>
AuthorDate: 2022-05-09 09:11:42 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2022-05-12 19:50:09 +0000

    pf: also apply dummynet to route-to/dup-to packets
    
    If packets are processed by a route-to/dup-to/reply-to rule (i.e. they
    pass through pf_route(6)) dummynet was not applied to them.
    This is because pf_route(6) passes packets directly to ifp->if_output(),
    so the dummynet functions were never called.
    
    Factor out the dummynet code and call dummynet prior to
    ifp->if_output(). This has a secondary benefit of reducing some code
    duplication between the IPv4 and IPv6 paths.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D35158
---
 sys/netpfil/pf/pf.c | 144 ++++++++++++++++++++++++----------------------------
 1 file changed, 67 insertions(+), 77 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index e9185c4d8587..343668030d0d 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -281,6 +281,8 @@ static int           pf_state_key_ctor(void *, int, void *, 
int);
 static u_int32_t        pf_tcp_iss(struct pf_pdesc *);
 void                    pf_rule_to_actions(struct pf_krule *,
                            struct pf_rule_actions *);
+static int              pf_dummynet(struct pf_pdesc *, int, struct pf_kstate *,
+                           struct pf_krule *, struct mbuf **);
 static int              pf_test_eth_rule(int, struct pfi_kkif *,
                            struct mbuf **);
 static int              pf_test_rule(struct pf_krule **, struct pf_kstate **,
@@ -6247,7 +6249,7 @@ static void
 pf_route(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
     struct pf_kstate *s, struct pf_pdesc *pd, struct inpcb *inp)
 {
-       struct mbuf             *m0, *m1;
+       struct mbuf             *m0, *m1, *md;
        struct sockaddr_in      dst;
        struct ip               *ip;
        struct ifnet            *ifp = NULL;
@@ -6295,6 +6297,7 @@ pf_route(struct mbuf **m, struct pf_krule *r, int dir, 
struct ifnet *oifp,
                }
        } else {
                if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
+                       pf_dummynet(pd, dir, s, r, m);
                        if (s)
                                PF_STATE_UNLOCK(s);
                        return;
@@ -6377,7 +6380,11 @@ pf_route(struct mbuf **m, struct pf_krule *r, int dir, 
struct ifnet *oifp,
                        m0->m_pkthdr.csum_flags &= ~CSUM_IP;
                }
                m_clrprotoflags(m0);    /* Avoid confusing lower layers. */
-               error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL);
+
+               md = m0;
+               error = pf_dummynet(pd, dir, s, r, &md);
+               if (md != NULL)
+                       error = (*ifp->if_output)(ifp, md, sintosa(&dst), NULL);
                goto done;
        }
 
@@ -6407,7 +6414,11 @@ pf_route(struct mbuf **m, struct pf_krule *r, int dir, 
struct ifnet *oifp,
                m0->m_nextpkt = NULL;
                if (error == 0) {
                        m_clrprotoflags(m0);
-                       error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL);
+                       md = m0;
+                       error = pf_dummynet(pd, dir, s, r, &md);
+                       if (md != NULL)
+                               error = (*ifp->if_output)(ifp, md,
+                                   sintosa(&dst), NULL);
                } else
                        m_freem(m0);
        }
@@ -6434,7 +6445,7 @@ static void
 pf_route6(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
     struct pf_kstate *s, struct pf_pdesc *pd, struct inpcb *inp)
 {
-       struct mbuf             *m0;
+       struct mbuf             *m0, *md;
        struct sockaddr_in6     dst;
        struct ip6_hdr          *ip6;
        struct ifnet            *ifp = NULL;
@@ -6480,6 +6491,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, int dir, 
struct ifnet *oifp,
                }
        } else {
                if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
+                       pf_dummynet(pd, dir, s, r, m);
                        if (s)
                                PF_STATE_UNLOCK(s);
                        return;
@@ -6551,8 +6563,12 @@ pf_route6(struct mbuf **m, struct pf_krule *r, int dir, 
struct ifnet *oifp,
         */
        if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr))
                dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
-       if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu)
-               nd6_output_ifp(ifp, ifp, m0, &dst, NULL);
+       if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
+               md = m0;
+               pf_dummynet(pd, dir, s, r, &md);
+               if (md != NULL)
+                       nd6_output_ifp(ifp, ifp, md, &dst, NULL);
+       }
        else {
                in6_ifstat_inc(ifp, ifs6_in_toobig);
                if (r->rt != PF_DUPTO) {
@@ -6807,6 +6823,45 @@ pf_test_eth(int dir, int pflags, struct ifnet *ifp, 
struct mbuf **m0,
        return (pf_test_eth_rule(dir, kif, m0));
 }
 
+static int
+pf_dummynet(struct pf_pdesc *pd, int dir, struct pf_kstate *s,
+    struct pf_krule *r, struct mbuf **m0)
+{
+       if (s && (s->dnpipe || s->dnrpipe)) {
+               pd->act.dnpipe = s->dnpipe;
+               pd->act.dnrpipe = s->dnrpipe;
+               pd->act.flags = s->state_flags;
+       } else if (r->dnpipe || r->dnrpipe) {
+               pd->act.dnpipe = r->dnpipe;
+               pd->act.dnrpipe = r->dnrpipe;
+               pd->act.flags = r->free_flags;
+       }
+       if (pd->act.dnpipe || pd->act.dnrpipe) {
+               struct ip_fw_args dnflow;
+               if (ip_dn_io_ptr == NULL) {
+                       m_freem(*m0);
+                       *m0 = NULL;
+                       return (ENOMEM);
+               }
+
+               if (pd->pf_mtag == NULL &&
+                   ((pd->pf_mtag = pf_get_mtag(*m0)) == NULL)) {
+                       m_freem(*m0);
+                       *m0 = NULL;
+                       return (ENOMEM);
+               }
+
+               if (pf_pdesc_to_dnflow(dir, pd, r, s, &dnflow)) {
+                       pd->pf_mtag->flags |= PF_TAG_DUMMYNET;
+                       ip_dn_io_ptr(m0, &dnflow);
+                       if (*m0 != NULL)
+                               pd->pf_mtag->flags &= ~PF_TAG_DUMMYNET;
+               }
+       }
+
+       return (0);
+}
+
 #ifdef INET
 int
 pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb 
*inp)
@@ -7266,41 +7321,9 @@ done:
                        pf_route(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
                        return (action);
                }
-               /* Dummynet processing. */
-               if (s && (s->dnpipe || s->dnrpipe)) {
-                       pd.act.dnpipe = s->dnpipe;
-                       pd.act.dnrpipe = s->dnrpipe;
-                       pd.act.flags = s->state_flags;
-               } else if (r->dnpipe || r->dnrpipe) {
-                       pd.act.dnpipe = r->dnpipe;
-                       pd.act.dnrpipe = r->dnrpipe;
-                       pd.act.flags = r->free_flags;
-               }
-               if (pd.act.dnpipe || pd.act.dnrpipe) {
-                       struct ip_fw_args dnflow;
-                       if (ip_dn_io_ptr == NULL) {
-                               m_freem(*m0);
-                               *m0 = NULL;
-                               action = PF_DROP;
-                               REASON_SET(&reason, PFRES_MEMORY);
-                               break;
-                       }
-
-                       if (pd.pf_mtag == NULL &&
-                           ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
-                               m_freem(*m0);
-                               *m0 = NULL;
-                               action = PF_DROP;
-                               REASON_SET(&reason, PFRES_MEMORY);
-                               break;
-                       }
-
-                       if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) {
-                               pd.pf_mtag->flags |= PF_TAG_DUMMYNET;
-                               ip_dn_io_ptr(m0, &dnflow);
-                               if (*m0 != NULL)
-                                       pd.pf_mtag->flags &= ~PF_TAG_DUMMYNET;
-                       }
+               if (pf_dummynet(&pd, dir, s, r, m0) != 0) {
+                       action = PF_DROP;
+                       REASON_SET(&reason, PFRES_MEMORY);
                }
                break;
        }
@@ -7723,42 +7746,9 @@ done:
                        pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd, inp);
                        return (action);
                }
-               /* Dummynet processing. */
-               if (s && (s->dnpipe || s->dnrpipe)) {
-                       pd.act.dnpipe = s->dnpipe;
-                       pd.act.dnrpipe = s->dnrpipe;
-                       pd.act.flags = s->state_flags;
-               } else {
-                       pd.act.dnpipe = r->dnpipe;
-                       pd.act.dnrpipe = r->dnrpipe;
-                       pd.act.flags = r->free_flags;
-               }
-               if (pd.act.dnpipe || pd.act.dnrpipe) {
-                       struct ip_fw_args dnflow;
-
-                       if (ip_dn_io_ptr == NULL) {
-                               m_freem(*m0);
-                               *m0 = NULL;
-                               action = PF_DROP;
-                               REASON_SET(&reason, PFRES_MEMORY);
-                               break;
-                       }
-
-                       if (pd.pf_mtag == NULL &&
-                                       ((pd.pf_mtag = pf_get_mtag(m)) == 
NULL)) {
-                               m_freem(*m0);
-                               *m0 = NULL;
-                               action = PF_DROP;
-                               REASON_SET(&reason, PFRES_MEMORY);
-                               break;
-                       }
-
-                       if (pf_pdesc_to_dnflow(dir, &pd, r, s, &dnflow)) {
-                               pd.pf_mtag->flags |= PF_TAG_DUMMYNET;
-                               ip_dn_io_ptr(m0, &dnflow);
-                               if (*m0 != NULL)
-                                       pd.pf_mtag->flags &= ~PF_TAG_DUMMYNET;
-                       }
+               if (pf_dummynet(&pd, dir, s, r, m0) != 0) {
+                       action = PF_DROP;
+                       REASON_SET(&reason, PFRES_MEMORY);
                }
                break;
        }

Reply via email to