The branch main has been updated by kp:

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

commit 27f54be50bbadae936f2ad0f1457fbdbd9634ae5
Author:     Kristof Provost <[email protected]>
AuthorDate: 2024-09-11 11:24:47 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2024-09-27 20:13:22 +0000

    pf: merge pf_test() and pf_test6()
    
    Bye bye pf_test6(). Only one pf_test function for both IPv4 and v6.
    The functions were 95% identical anyway.
    OK bluhm@ mcbride@ and most probably henning@ as well
    
    Obtained from:  OpenBSD, claudio <[email protected]>, c8bc4f6e29
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D46649
---
 sys/net/pfvar.h           |   8 +-
 sys/netpfil/pf/pf.c       | 614 +++++++++++++---------------------------------
 sys/netpfil/pf/pf_ioctl.c |   8 +-
 3 files changed, 173 insertions(+), 457 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 9ad079f9f95b..c4553e6f380f 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2361,16 +2361,16 @@ int                             
pf_setup_pdesc(sa_family_t, int,
 
 int    pf_test_eth(int, int, struct ifnet *, struct mbuf **, struct inpcb *);
 int    pf_scan_sctp(struct mbuf *, int, struct pf_pdesc *, struct pfi_kkif *);
-#ifdef INET
-int    pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *,
+#if defined(INET) || defined(INET6)
+int    pf_test(sa_family_t, int, int, struct ifnet *, struct mbuf **, struct 
inpcb *,
            struct pf_rule_actions *);
+#endif
+#ifdef INET
 int    pf_normalize_ip(struct mbuf **, struct pfi_kkif *, u_short *,
            struct pf_pdesc *);
 #endif /* INET */
 
 #ifdef INET6
-int    pf_test6(int, int, struct ifnet *, struct mbuf **, struct inpcb *,
-           struct pf_rule_actions *);
 int    pf_normalize_ip6(struct mbuf **, struct pfi_kkif *, u_short *,
            struct pf_pdesc *);
 void   pf_poolmask(struct pf_addr *, struct pf_addr*,
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 215f2655d9d4..8072207ef5dd 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -121,8 +121,6 @@
 SDT_PROVIDER_DEFINE(pf);
 SDT_PROBE_DEFINE4(pf, ip, test, done, "int", "int", "struct pf_krule *",
     "struct pf_kstate *");
-SDT_PROBE_DEFINE4(pf, ip, test6, done, "int", "int", "struct pf_krule *",
-    "struct pf_kstate *");
 SDT_PROBE_DEFINE5(pf, ip, state, lookup, "struct pfi_kkif *",
     "struct pf_state_key_cmp *", "int", "struct pf_pdesc *",
     "struct pf_kstate *");
@@ -585,6 +583,19 @@ pf_addr_cmp(struct pf_addr *a, struct pf_addr *b, 
sa_family_t af)
        return (0);
 }
 
+static bool
+pf_is_loopback(sa_family_t af, struct pf_addr *addr)
+{
+       switch (af) {
+       case AF_INET:
+               return IN_LOOPBACK(ntohl(addr->v4.s_addr));
+       case AF_INET6:
+               return IN6_IS_ADDR_LOOPBACK(&addr->v6);
+       default:
+               panic("Unknown af %d", af);
+       }
+}
+
 static void
 pf_packet_rework_nat(struct mbuf *m, struct pf_pdesc *pd, int off,
        struct pf_state_key *nk)
@@ -7906,7 +7917,8 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
                goto bad;
 
        if (pd->dir == PF_IN) {
-               if (pf_test(PF_OUT, PFIL_FWD, ifp, &m0, inp, &pd->act) != 
PF_PASS)
+               if (pf_test(AF_INET, PF_OUT, PFIL_FWD, ifp, &m0, inp,
+                   &pd->act) != PF_PASS)
                        goto bad;
                else if (m0 == NULL)
                        goto done;
@@ -8156,7 +8168,8 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
                goto bad;
 
        if (pd->dir == PF_IN) {
-               if (pf_test6(PF_OUT, PFIL_FWD, ifp, &m0, inp, &pd->act) != 
PF_PASS)
+               if (pf_test(AF_INET6, PF_OUT, PFIL_FWD, ifp, &m0, inp,
+                   &pd->act) != PF_PASS)
                        goto bad;
                else if (m0 == NULL)
                        goto done;
@@ -8586,6 +8599,9 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc 
*pd, struct mbuf *m,
                pd->tot_len = ntohs(h->ip_len);
                pd->act.rtableid = -1;
 
+               if (h->ip_hl > 5)       /* has options */
+                       pd->rh_cnt++;
+
                /* fragments not reassembled handled later */
                if (h->ip_off & htons(IP_MF | IP_OFFMASK))
                        return (0);
@@ -8756,6 +8772,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc 
*pd, struct mbuf *m,
                *hdrlen = ICMP_MINLEN;
                break;
        }
+#ifdef INET6
        case IPPROTO_ICMPV6: {
                size_t icmp_hlen = sizeof(struct icmp6_hdr);
 
@@ -8786,6 +8803,7 @@ pf_setup_pdesc(sa_family_t af, int dir, struct pf_pdesc 
*pd, struct mbuf *m,
                *hdrlen = icmp_hlen;
                break;
        }
+#endif
        }
        return (0);
 }
@@ -8869,15 +8887,16 @@ pf_counters_inc(int action, struct pf_pdesc *pd,
        pf_counter_u64_critical_exit();
 }
 
-#ifdef INET
+#if defined(INET) || defined(INET6)
 int
-pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0,
+pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf 
**m0,
     struct inpcb *inp, struct pf_rule_actions *default_actions)
 {
        struct pfi_kkif         *kif;
        u_short                  action, reason = 0;
        struct mbuf             *m = *m0;
        struct ip               *h = NULL;
+       struct ip6_hdr          *h6 = NULL;
        struct m_tag            *mtag;
        struct pf_krule         *a = NULL, *r = &V_pf_default_rule;
        struct pf_kstate        *s = NULL;
@@ -8886,6 +8905,7 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
        int                      off, hdrlen, use_2nd_queue = 0;
        uint16_t                 tag;
        uint8_t                  rt;
+       uint8_t                  ttl;
 
        PF_RULES_RLOCK_TRACKER;
        KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", 
__func__, dir));
@@ -8920,26 +8940,68 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
                        return (PF_DROP);
        }
 
-       if (__predict_false(m->m_len < sizeof(struct ip)) &&
-           (m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) {
-               DPFPRINTF(PF_DEBUG_URGENT,
-                   ("pf_test: m_len < sizeof(struct ip), pullup failed\n"));
-               PF_RULES_RUNLOCK();
-               return (PF_DROP);
-       }
-
        memset(&pd, 0, sizeof(pd));
        pd.dir = dir;
 
-       if (pf_normalize_ip(m0, kif, &reason, &pd) != PF_PASS) {
+       switch (af) {
+#ifdef INET
+       case AF_INET:
+               if (__predict_false(m->m_len < sizeof(struct ip)) &&
+                   (m = *m0 = m_pullup(*m0, sizeof(struct ip))) == NULL) {
+                       DPFPRINTF(PF_DEBUG_URGENT,
+                           ("pf_test: m_len < sizeof(struct ip), pullup 
failed\n"));
+                       PF_RULES_RUNLOCK();
+                       return (PF_DROP);
+               }
+
+               if (pf_normalize_ip(m0, kif, &reason, &pd) != PF_PASS) {
+                       /* We do IP header normalization and packet reassembly 
here */
+                       action = PF_DROP;
+                       goto done;
+               }
+               m = *m0;        /* pf_normalize messes with m0 */
+               h = mtod(m, struct ip *);
+               ttl = h->ip_ttl;
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               /*
+                * If we end up changing IP addresses (e.g. binat) the stack 
may get
+                * confused and fail to send the icmp6 packet too big error. 
Just send
+                * it here, before we do any NAT.
+                */
+               if (dir == PF_OUT && pflags & PFIL_FWD && IN6_LINKMTU(ifp) < 
pf_max_frag_size(m)) {
+                       PF_RULES_RUNLOCK();
+                       *m0 = NULL;
+                       icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, 
IN6_LINKMTU(ifp));
+                       return (PF_DROP);
+               }
+
+               if (__predict_false(m->m_len < sizeof(struct ip6_hdr)) &&
+                   (m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) {
+                       DPFPRINTF(PF_DEBUG_URGENT,
+                           ("pf_test6: m_len < sizeof(struct ip6_hdr)"
+                            ", pullup failed\n"));
+                       PF_RULES_RUNLOCK();
+                       return (PF_DROP);
+               }
+
                /* We do IP header normalization and packet reassembly here */
-               action = PF_DROP;
-               goto done;
+               if (pf_normalize_ip6(m0, kif, &reason, &pd) != PF_PASS) {
+                       action = PF_DROP;
+                       goto done;
+               }
+               m = *m0;        /* pf_normalize messes with m0 */
+               h6 = mtod(m, struct ip6_hdr *);
+               ttl = h6->ip6_hlim;
+               break;
+#endif
+       default:
+               panic("Unknown af %d", af);
        }
-       m = *m0;        /* pf_normalize messes with m0 */
-       h = mtod(m, struct ip *);
 
-       if (pf_setup_pdesc(AF_INET, dir, &pd, m, &action, &reason, kif, &a, &r,
+       if (pf_setup_pdesc(af, dir, &pd, m, &action, &reason, kif, &a, &r,
                &ruleset, &off, &hdrlen, default_actions) == -1) {
                if (action != PF_PASS)
                        pd.act.log |= PF_LOG_FORCE;
@@ -9000,15 +9062,35 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
                        m_tag_delete(m, mtag);
        }
 
-       /* handle fragments that didn't get reassembled by normalization */
-       if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
-               action = pf_test_fragment(&r, kif, m, &pd, &a, &ruleset);
-               goto done;
+       switch (af) {
+#ifdef INET
+       case AF_INET:
+               /* handle fragments that didn't get reassembled by 
normalization */
+               if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
+                       action = pf_test_fragment(&r, kif, m, &pd, &a, 
&ruleset);
+                       goto done;
+               }
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               /*
+                * we do not support jumbogram.  if we keep going, zero ip6_plen
+                * will do something bad, so drop the packet for now.
+                */
+               if (htons(h6->ip6_plen) == 0) {
+                       action = PF_DROP;
+                       REASON_SET(&reason, PFRES_NORM);        /*XXX*/
+                       goto done;
+               }
+               break;
+#endif
+       default:
+               panic("Unknown af %d", af);
        }
 
-       switch (h->ip_p) {
+       switch (pd.proto) {
        case IPPROTO_TCP: {
-
                /* Respond to SYN with a syncookie. */
                if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN &&
                    pd.dir == PF_IN && pf_synflood_check(&pd)) {
@@ -9036,14 +9118,14 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
                            pd.dir == PF_IN) {
                                struct mbuf *msyn;
 
-                               msyn = pf_syncookie_recreate_syn(h->ip_ttl, off,
+                               msyn = pf_syncookie_recreate_syn(ttl, off,
                                    &pd);
                                if (msyn == NULL) {
                                        action = PF_DROP;
                                        break;
                                }
 
-                               action = pf_test(dir, pflags, ifp, &msyn, inp,
+                               action = pf_test(af, dir, pflags, ifp, &msyn, 
inp,
                                    &pd.act);
                                m_freem(msyn);
                                if (action != PF_PASS)
@@ -9101,6 +9183,12 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
        }
 
        case IPPROTO_ICMP: {
+               if (af != AF_INET) {
+                       action = PF_DROP;
+                       DPFPRINTF(PF_DEBUG_MISC,
+                           ("dropping IPv6 packet with ICMPv4 payload"));
+                       goto done;
+               }
                action = pf_test_state_icmp(&s, kif, m, off, &pd, &reason);
                if (action == PF_PASS) {
                        if (V_pfsync_update_state_ptr != NULL)
@@ -9114,10 +9202,22 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
        }
 
        case IPPROTO_ICMPV6: {
-               action = PF_DROP;
-               DPFPRINTF(PF_DEBUG_MISC,
-                   ("pf: dropping IPv4 packet with ICMPv6 payload\n"));
-               goto done;
+               if (af != AF_INET6) {
+                       action = PF_DROP;
+                       DPFPRINTF(PF_DEBUG_MISC,
+                           ("pf: dropping IPv4 packet with ICMPv6 payload\n"));
+                       goto done;
+               }
+               action = pf_test_state_icmp(&s, kif, m, off, &pd, &reason);
+               if (action == PF_PASS) {
+                       if (V_pfsync_update_state_ptr != NULL)
+                               V_pfsync_update_state_ptr(s);
+                       r = s->rule.ptr;
+                       a = s->anchor.ptr;
+               } else if (s == NULL)
+                       action = pf_test_rule(&r, &s, kif, m, off, &pd,
+                           &a, &ruleset, inp, hdrlen);
+               break;
        }
 
        default:
@@ -9135,13 +9235,14 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct 
mbuf **m0,
 
 done:
        PF_RULES_RUNLOCK();
-       if (action == PF_PASS && h->ip_hl > 5 &&
+
+       if (action == PF_PASS && pd.rh_cnt &&
            !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
                action = PF_DROP;
                REASON_SET(&reason, PFRES_IPOPTIONS);
                pd.act.log = PF_LOG_FORCE;
                DPFPRINTF(PF_DEBUG_MISC,
-                   ("pf: dropping packet with ip options\n"));
+                   ("pf: dropping packet with dangerous headers\n"));
        }
 
        if (s) {
@@ -9193,7 +9294,10 @@ done:
                        else
                                pd.pf_mtag->qid = pd.act.qid;
                        /* Add hints for ecn. */
-                       pd.pf_mtag->hdr = h;
+                       if (af == AF_INET)
+                               pd.pf_mtag->hdr = h;
+                       else
+                               pd.pf_mtag->hdr = h6;
                }
        }
 #endif /* ALTQ */
@@ -9207,11 +9311,11 @@ done:
            pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
            (s->nat_rule.ptr->action == PF_RDR ||
            s->nat_rule.ptr->action == PF_BINAT) &&
-           IN_LOOPBACK(ntohl(pd.dst->v4.s_addr)))
+           pf_is_loopback(af, pd.dst))
                m->m_flags |= M_SKIP_FIREWALL;
 
-       if (__predict_false(ip_divert_ptr != NULL) && action == PF_PASS &&
-           r->divert.port && !PACKET_LOOPED(&pd)) {
+       if (af == AF_INET && __predict_false(ip_divert_ptr != NULL) &&
+           action == PF_PASS && r->divert.port && !PACKET_LOOPED(&pd)) {
                mtag = m_tag_alloc(MTAG_PF_DIVERT, 0,
                    sizeof(struct pf_divert_mtag), M_NOWAIT | M_ZERO);
                if (mtag != NULL) {
@@ -9252,6 +9356,10 @@ done:
                            ("pf: failed to allocate divert tag\n"));
                }
        }
+       /* XXX: Anybody working on it?! */
+       if (af == AF_INET6 && r->divert.port)
+               printf("pf: divert(9) is not supported for IPv6\n");
+
        /* this flag will need revising if the pkt is forwarded */
        if (pd.pf_mtag)
                pd.pf_mtag->flags &= ~PF_MTAG_FLAG_PACKET_LOOPED;
@@ -9291,417 +9399,23 @@ done:
                *m0 = NULL;
                break;
        default:
-               /* pf_route() returns unlocked. */
                if (rt) {
-                       pf_route(m0, r, kif->pfik_ifp, s, &pd, inp);
-                       goto out;
-               }
-               if (pf_dummynet(&pd, s, r, m0) != 0) {
-                       action = PF_DROP;
-                       REASON_SET(&reason, PFRES_MEMORY);
-               }
-               break;
-       }
-
-       SDT_PROBE4(pf, ip, test, done, action, reason, r, s);
-
-       if (s && action != PF_DROP) {
-               if (!s->if_index_in && dir == PF_IN)
-                       s->if_index_in = ifp->if_index;
-               else if (!s->if_index_out && dir == PF_OUT)
-                       s->if_index_out = ifp->if_index;
-       }
-
-       if (s)
-               PF_STATE_UNLOCK(s);
-
-out:
-       pf_sctp_multihome_delayed(&pd, off, kif, s, action);
-
-       return (action);
-}
-#endif /* INET */
-
+                       switch (af) {
+#ifdef INET
+                       case AF_INET:
+                               /* pf_route() returns unlocked. */
+                               pf_route(m0, r, kif->pfik_ifp, s, &pd, inp);
+                               break;
+#endif
 #ifdef INET6
-int
-pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct 
inpcb *inp,
-    struct pf_rule_actions *default_actions)
-{
-       struct pfi_kkif         *kif;
-       u_short                  action, reason = 0;
-       struct mbuf             *m = *m0, *n = NULL;
-       struct m_tag            *mtag;
-       struct ip6_hdr          *h = NULL;
-       struct pf_krule         *a = NULL, *r = &V_pf_default_rule;
-       struct pf_kstate        *s = NULL;
-       struct pf_kruleset      *ruleset = NULL;
-       struct pf_pdesc          pd;
-       int                      off, hdrlen, use_2nd_queue = 0;
-       uint16_t                 tag;
-       uint8_t                  rt;
-
-       PF_RULES_RLOCK_TRACKER;
-       KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", 
__func__, dir));
-       M_ASSERTPKTHDR(m);
-
-       if (!V_pf_status.running)
-               return (PF_PASS);
-
-       PF_RULES_RLOCK();
-
-       kif = (struct pfi_kkif *)ifp->if_pf_kif;
-       if (__predict_false(kif == NULL)) {
-               DPFPRINTF(PF_DEBUG_URGENT,
-                   ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
-               PF_RULES_RUNLOCK();
-               return (PF_DROP);
-       }
-       if (kif->pfik_flags & PFI_IFLAG_SKIP) {
-               PF_RULES_RUNLOCK();
-               return (PF_PASS);
-       }
-
-       if (m->m_flags & M_SKIP_FIREWALL) {
-               PF_RULES_RUNLOCK();
-               return (PF_PASS);
-       }
-
-       /*
-        * If we end up changing IP addresses (e.g. binat) the stack may get
-        * confused and fail to send the icmp6 packet too big error. Just send
-        * it here, before we do any NAT.
-        */
-       if (dir == PF_OUT && pflags & PFIL_FWD && IN6_LINKMTU(ifp) < 
pf_max_frag_size(m)) {
-               PF_RULES_RUNLOCK();
-               *m0 = NULL;
-               icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, IN6_LINKMTU(ifp));
-               return (PF_DROP);
-       }
-
-       if (__predict_false(! M_WRITABLE(*m0))) {
-               m = *m0 = m_unshare(*m0, M_NOWAIT);
-               if (*m0 == NULL)
-                       return (PF_DROP);
-       }
-
-       if (__predict_false(m->m_len < sizeof(struct ip6_hdr)) &&
-           (m = *m0 = m_pullup(*m0, sizeof(struct ip6_hdr))) == NULL) {
-               DPFPRINTF(PF_DEBUG_URGENT,
-                   ("pf_test6: m_len < sizeof(struct ip6_hdr)"
-                    ", pullup failed\n"));
-               PF_RULES_RUNLOCK();
-               return (PF_DROP);
-       }
-
-       memset(&pd, 0, sizeof(pd));
-       pd.dir = dir;
-
-       /* We do IP header normalization and packet reassembly here */
-       if (pf_normalize_ip6(m0, kif, &reason, &pd) != PF_PASS) {
-               action = PF_DROP;
-               goto done;
-       }
-       m = *m0;        /* pf_normalize messes with m0 */
-       h = mtod(m, struct ip6_hdr *);
-       off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
-
-       if (pf_setup_pdesc(AF_INET6, dir, &pd, m, &action, &reason, kif, &a, &r,
-               &ruleset, &off, &hdrlen, default_actions) == -1) {
-               if (action != PF_PASS)
-                       pd.act.log |= PF_LOG_FORCE;
-               goto done;
-       }
-
-       if (pd.pf_mtag != NULL && (pd.pf_mtag->flags & PF_MTAG_FLAG_ROUTE_TO)) {
-               pd.pf_mtag->flags &= ~PF_MTAG_FLAG_ROUTE_TO;
-
-               ifp = ifnet_byindexgen(pd.pf_mtag->if_index,
-                   pd.pf_mtag->if_idxgen);
-               if (ifp == NULL || ifp->if_flags & IFF_DYING) {
-                       PF_RULES_RUNLOCK();
-                       m_freem(*m0);
-                       *m0 = NULL;
-                       return (PF_PASS);
-               }
-               PF_RULES_RUNLOCK();
-               nd6_output_ifp(ifp, ifp, m,
-                    (struct sockaddr_in6 *)&pd.pf_mtag->dst, NULL);
-               *m0 = NULL;
-               return (PF_PASS);
-       }
-
-       if (ip_dn_io_ptr != NULL && pd.pf_mtag != NULL &&
-           pd.pf_mtag->flags & PF_MTAG_FLAG_DUMMYNET) {
-               pf_dummynet_flag_remove(m, pd.pf_mtag);
-               /* Dummynet re-injects packets after they've
-                * completed their delay. We've already
-                * processed them, so pass unconditionally. */
-               PF_RULES_RUNLOCK();
-               return (PF_PASS);
-       }
-
-       /*
-        * we do not support jumbogram.  if we keep going, zero ip6_plen
-        * will do something bad, so drop the packet for now.
-        */
-       if (htons(h->ip6_plen) == 0) {
-               action = PF_DROP;
-               REASON_SET(&reason, PFRES_NORM);        /*XXX*/
-               goto done;
-       }
-
-       /* if there's no routing header, use unmodified mbuf for checksumming */
-       if (!n)
-               n = m;
-
-       switch (pd.proto) {
-       case IPPROTO_TCP: {
-               /* Respond to SYN with a syncookie. */
-               if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN &&
-                   pd.dir == PF_IN && pf_synflood_check(&pd)) {
-                       pf_syncookie_send(m, off, &pd);
-                       action = PF_DROP;
-                       break;
-               }
-
-               if ((pd.hdr.tcp.th_flags & TH_ACK) && pd.p_len == 0)
-                       use_2nd_queue = 1;
-
-               action = pf_normalize_tcp(kif, m, 0, off, &pd);
-               if (action == PF_DROP)
-                       goto done;
-               action = pf_test_state_tcp(&s, kif, m, off, &pd, &reason);
-               if (action == PF_PASS) {
-                       if (V_pfsync_update_state_ptr != NULL)
-                               V_pfsync_update_state_ptr(s);
-                       r = s->rule.ptr;
-                       a = s->anchor.ptr;
-               } else if (s == NULL) {
-                       /* Validate remote SYN|ACK, re-create original SYN if
-                        * valid. */
-                       if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) ==
-                           TH_ACK && pf_syncookie_validate(&pd) &&
-                           pd.dir == PF_IN) {
-                               struct mbuf *msyn;
-
-                               msyn = pf_syncookie_recreate_syn(h->ip6_hlim,
-                                   off, &pd);
-                               if (msyn == NULL) {
-                                       action = PF_DROP;
-                                       break;
-                               }
-
-                               action = pf_test6(dir, pflags, ifp, &msyn, inp,
-                                   &pd.act);
-                               m_freem(msyn);
-                               if (action != PF_PASS)
-                                       break;
-
-                               action = pf_test_state_tcp(&s, kif, m, off,
-                                   &pd, &reason);
-                               if (action != PF_PASS || s == NULL) {
-                                       action = PF_DROP;
-                                       break;
-                               }
-
-                               s->src.seqhi = ntohl(pd.hdr.tcp.th_ack) - 1;
-                               s->src.seqlo = ntohl(pd.hdr.tcp.th_seq) - 1;
-                               pf_set_protostate(s, PF_PEER_SRC, 
PF_TCPS_PROXY_DST);
-
-                               action = pf_synproxy(&pd, &s, &reason);
+                       case AF_INET6:
+                               /* pf_route6() returns unlocked. */
+                               pf_route6(m0, r, kif->pfik_ifp, s, &pd, inp);
                                break;
-                       } else {
-                               action = pf_test_rule(&r, &s, kif, m, off, &pd,
-                                   &a, &ruleset, inp, hdrlen);
+#endif
+                       default:
+                               panic("Unknown af %d", af);
                        }
-               }
-               break;
-       }
-
-       case IPPROTO_UDP: {
-               action = pf_test_state_udp(&s, kif, m, off, &pd);
-               if (action == PF_PASS) {
-                       if (V_pfsync_update_state_ptr != NULL)
-                               V_pfsync_update_state_ptr(s);
-                       r = s->rule.ptr;
-                       a = s->anchor.ptr;
-               } else if (s == NULL)
-                       action = pf_test_rule(&r, &s, kif, m, off, &pd,
-                           &a, &ruleset, inp, hdrlen);
-               break;
-       }
-
-       case IPPROTO_SCTP: {
-               action = pf_normalize_sctp(dir, kif, m, 0, off, &pd);
-               if (action == PF_DROP)
-                       goto done;
-               action = pf_test_state_sctp(&s, kif, m, off, &pd,
-                   &reason);
-               if (action == PF_PASS) {
-                       if (V_pfsync_update_state_ptr != NULL)
-                               V_pfsync_update_state_ptr(s);
-                       r = s->rule.ptr;
-                       a = s->anchor.ptr;
-               } else if (s == NULL) {
-                       action = pf_test_rule(&r, &s, kif, m, off,
-                           &pd, &a, &ruleset, inp, hdrlen);
-               }
-               break;
-       }
-
-       case IPPROTO_ICMP: {
-               action = PF_DROP;
-               DPFPRINTF(PF_DEBUG_MISC,
-                   ("pf: dropping IPv6 packet with ICMPv4 payload\n"));
-               goto done;
-       }
-
-       case IPPROTO_ICMPV6: {
-               action = pf_test_state_icmp(&s, kif, m, off, &pd, &reason);
-               if (action == PF_PASS) {
-                       if (V_pfsync_update_state_ptr != NULL)
-                               V_pfsync_update_state_ptr(s);
-                       r = s->rule.ptr;
-                       a = s->anchor.ptr;
-               } else if (s == NULL)
-                       action = pf_test_rule(&r, &s, kif, m, off, &pd,
-                           &a, &ruleset, inp, hdrlen);
-               break;
-       }
-
-       default:
-               action = pf_test_state_other(&s, kif, m, &pd);
-               if (action == PF_PASS) {
-                       if (V_pfsync_update_state_ptr != NULL)
-                               V_pfsync_update_state_ptr(s);
-                       r = s->rule.ptr;
-                       a = s->anchor.ptr;
-               } else if (s == NULL)
-                       action = pf_test_rule(&r, &s, kif, m, off, &pd,
-                           &a, &ruleset, inp, hdrlen);
-               break;
-       }
-
-done:
-       PF_RULES_RUNLOCK();
-       if (n != m) {
-               m_freem(n);
-               n = NULL;
-       }
-
-       /* handle dangerous IPv6 extension headers. */
-       if (action == PF_PASS && pd.rh_cnt &&
-           !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
-               action = PF_DROP;
-               REASON_SET(&reason, PFRES_IPOPTIONS);
-               pd.act.log = r->log;
-               DPFPRINTF(PF_DEBUG_MISC,
-                   ("pf: dropping packet with dangerous v6 headers\n"));
-       }
-
-       if (s) {
-               uint8_t log = pd.act.log;
-               memcpy(&pd.act, &s->act, sizeof(struct pf_rule_actions));
-               pd.act.log |= log;
-               tag = s->tag;
-               rt = s->rt;
-       } else {
-               tag = r->tag;
-               rt = r->rt;
-       }
-
-       if (tag > 0 && pf_tag_packet(m, &pd, tag)) {
-               action = PF_DROP;
-               REASON_SET(&reason, PFRES_MEMORY);
-       }
-
-       pf_scrub(m, &pd);
-       if (pd.proto == IPPROTO_TCP && pd.act.max_mss)
-               pf_normalize_mss(m, off, &pd);
-
-       if (pd.act.rtableid >= 0)
-               M_SETFIB(m, pd.act.rtableid);
-
-       if (pd.act.flags & PFSTATE_SETPRIO) {
-               if (pd.tos & IPTOS_LOWDELAY)
-                       use_2nd_queue = 1;
-               if (vlan_set_pcp(m, pd.act.set_prio[use_2nd_queue])) {
-                       action = PF_DROP;
-                       REASON_SET(&reason, PFRES_MEMORY);
-                       pd.act.log = PF_LOG_FORCE;
-                       DPFPRINTF(PF_DEBUG_MISC,
-                           ("pf: failed to allocate 802.1q mtag\n"));
-               }
-       }
-
-#ifdef ALTQ
-       if (action == PF_PASS && pd.act.qid) {
-               if (pd.pf_mtag == NULL &&
-                   ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
-                       action = PF_DROP;
-                       REASON_SET(&reason, PFRES_MEMORY);
-               } else {
-                       if (s != NULL)
-                               pd.pf_mtag->qid_hash = pf_state_hash(s);
-                       if (use_2nd_queue || (pd.tos & IPTOS_LOWDELAY))
-                               pd.pf_mtag->qid = pd.act.pqid;
-                       else
-                               pd.pf_mtag->qid = pd.act.qid;
-                       /* Add hints for ecn. */
-                       pd.pf_mtag->hdr = h;
-               }
-       }
-#endif /* ALTQ */
-
-       if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
-           pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
-           (s->nat_rule.ptr->action == PF_RDR ||
-           s->nat_rule.ptr->action == PF_BINAT) &&
-           IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
-               m->m_flags |= M_SKIP_FIREWALL;
-
-       /* XXX: Anybody working on it?! */
-       if (r->divert.port)
-               printf("pf: divert(9) is not supported for IPv6\n");
-
-       if (pd.act.log) {
-               struct pf_krule         *lr;
-               struct pf_krule_item    *ri;
-
-               if (s != NULL && s->nat_rule.ptr != NULL &&
-                   s->nat_rule.ptr->log & PF_LOG_ALL)
-                       lr = s->nat_rule.ptr;
-               else
-                       lr = r;
-
-               if (pd.act.log & PF_LOG_FORCE || lr->log & PF_LOG_ALL)
-                       PFLOG_PACKET(kif, m, action, reason, lr, a, ruleset,
-                           &pd, (s == NULL));
-               if (s) {
-                       SLIST_FOREACH(ri, &s->match_rules, entry)
-                               if (ri->r->log & PF_LOG_ALL)
-                                       PFLOG_PACKET(kif, m, action, reason,
-                                           ri->r, a, ruleset, &pd, 0);
-               }
-       }
-
-       pf_counters_inc(action, &pd, kif, s, r, a);
-
-       switch (action) {
-       case PF_SYNPROXY_DROP:
-               m_freem(*m0);
-       case PF_DEFER:
-               *m0 = NULL;
-               action = PF_PASS;
-               break;
-       case PF_DROP:
-               m_freem(*m0);
-               *m0 = NULL;
-               break;
-       default:
-               /* pf_route6() returns unlocked. */
-               if (rt) {
-                       pf_route6(m0, r, kif->pfik_ifp, s, &pd, inp);
                        goto out;
                }
                if (pf_dummynet(&pd, s, r, m0) != 0) {
@@ -9711,6 +9425,8 @@ done:
                break;
        }
 
+       SDT_PROBE4(pf, ip, test, done, action, reason, r, s);
+
        if (s && action != PF_DROP) {
                if (!s->if_index_in && dir == PF_IN)
                        s->if_index_in = ifp->if_index;
@@ -9721,16 +9437,16 @@ done:
        if (s)
                PF_STATE_UNLOCK(s);
 
+#ifdef INET6
        /* If reassembled packet passed, create new fragments. */
-       if (action == PF_PASS && *m0 && dir == PF_OUT &&
+       if (af == AF_INET6 && action == PF_PASS && *m0 && dir == PF_OUT &&
            (mtag = m_tag_find(m, PACKET_TAG_PF_REASSEMBLED, NULL)) != NULL)
                action = pf_refragment6(ifp, m0, mtag, pflags & PFIL_FWD);
+#endif
 
 out:
-       SDT_PROBE4(pf, ip, test6, done, action, reason, r, s);
-
        pf_sctp_multihome_delayed(&pd, off, kif, s, action);
 
        return (action);
 }
-#endif /* INET6 */
+#endif /* INET || INET6 */
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index dcdab6029558..0a573a017ef3 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -6471,7 +6471,7 @@ pf_check_in(struct mbuf **m, struct ifnet *ifp, int flags,
 
        CURVNET_ASSERT_SET();
 
-       chk = pf_test(PF_IN, flags, ifp, m, inp, NULL);
+       chk = pf_test(AF_INET, PF_IN, flags, ifp, m, inp, NULL);
 
        return (pf_check_return(chk, m));
 }
@@ -6484,7 +6484,7 @@ pf_check_out(struct mbuf **m, struct ifnet *ifp, int 
flags,
 
        CURVNET_ASSERT_SET();
 
-       chk = pf_test(PF_OUT, flags, ifp, m, inp, NULL);
+       chk = pf_test(AF_INET, PF_OUT, flags, ifp, m, inp, NULL);
 
        return (pf_check_return(chk, m));
 }
@@ -6504,7 +6504,7 @@ pf_check6_in(struct mbuf **m, struct ifnet *ifp, int 
flags,
         * order to support scoped addresses. In order to support stateful
         * filtering we have change this to lo0 as it is the case in IPv4.
         */
-       chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp,
+       chk = pf_test(AF_INET6, PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : 
ifp,
            m, inp, NULL);
 
        return (pf_check_return(chk, m));
@@ -6518,7 +6518,7 @@ pf_check6_out(struct mbuf **m, struct ifnet *ifp, int 
flags,
 
        CURVNET_ASSERT_SET();
 
-       chk = pf_test6(PF_OUT, flags, ifp, m, inp, NULL);
+       chk = pf_test(AF_INET6, PF_OUT, flags, ifp, m, inp, NULL);
 
        return (pf_check_return(chk, m));
 }

Reply via email to