aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2024-09-11 11:24:47 +0000
committerKristof Provost <kp@FreeBSD.org>2024-09-27 20:13:22 +0000
commit27f54be50bbadae936f2ad0f1457fbdbd9634ae5 (patch)
treefb34dcc5b318910d8ea974036eaf6a10f7220b78
parent1235d276b78a769bded01d51c9bf3cdc480db9fb (diff)
downloadsrc-27f54be50bba.tar.gz
src-27f54be50bba.zip
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 <claudio@openbsd.org>, c8bc4f6e29 Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D46649
-rw-r--r--sys/net/pfvar.h8
-rw-r--r--sys/netpfil/pf/pf.c614
-rw-r--r--sys/netpfil/pf/pf_ioctl.c8
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));
}