From owner-dev-commits-src-main@freebsd.org Sat Jul 17 12:44:06 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 7E0B0654235; Sat, 17 Jul 2021 12:44:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GRnqB2wSZz4YHH; Sat, 17 Jul 2021 12:44:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4D00410E06; Sat, 17 Jul 2021 12:44:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 16HCi6G8099943; Sat, 17 Jul 2021 12:44:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 16HCi6pJ099942; Sat, 17 Jul 2021 12:44:06 GMT (envelope-from git) Date: Sat, 17 Jul 2021 12:44:06 GMT Message-Id: <202107171244.16HCi6pJ099942@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: ef950daa35d4 - main - pf: match keyword support MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: ef950daa35d43dd396958ca28ce9de0514daf873 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Jul 2021 12:44:06 -0000 The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=ef950daa35d43dd396958ca28ce9de0514daf873 commit ef950daa35d43dd396958ca28ce9de0514daf873 Author: Kristof Provost AuthorDate: 2021-03-02 15:01:04 +0000 Commit: Kristof Provost CommitDate: 2021-07-17 10:01:08 +0000 pf: match keyword support Support the 'match' keyword. Note that support is limited to adding queuing information, so without ALTQ support in the kernel setting match rules is pointless. For the avoidance of doubt: this is NOT full support for the match keyword as found in OpenBSD's pf. That could potentially be built on top of this, but this commit is NOT that. MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D31115 --- sbin/pfctl/parse.y | 4 ++- sbin/pfctl/pf_ruleset.c | 1 + sbin/pfctl/pfctl_parser.c | 4 ++- sys/net/pfvar.h | 8 +++++ sys/netpfil/pf/pf.c | 81 +++++++++++++++++++++++++++++++++++++-------- sys/netpfil/pf/pf.h | 3 +- sys/netpfil/pf/pf_ruleset.c | 1 + 7 files changed, 85 insertions(+), 17 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index acd90e280b53..74744794370f 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -456,7 +456,7 @@ int parseport(char *, struct range *r, int); %} -%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS +%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL @@ -2677,6 +2677,7 @@ action : PASS { $$.w = returnicmpdefault; $$.w2 = returnicmp6default; } + | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } ; @@ -5612,6 +5613,7 @@ lookup(char *s) { "log", LOG}, { "loginterface", LOGINTERFACE}, { "map-e-portset", MAPEPORTSET}, + { "match", MATCH}, { "max", MAXIMUM}, { "max-mss", MAXMSS}, { "max-src-conn", MAXSRCCONN}, diff --git a/sbin/pfctl/pf_ruleset.c b/sbin/pfctl/pf_ruleset.c index f5cddf481871..480e0f0c9b45 100644 --- a/sbin/pfctl/pf_ruleset.c +++ b/sbin/pfctl/pf_ruleset.c @@ -106,6 +106,7 @@ pf_get_ruleset_number(u_int8_t action) break; case PF_PASS: case PF_DROP: + case PF_MATCH: return (PF_RULESET_FILTER); break; case PF_NAT: diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index b4a1cde967bd..62d4b42bd416 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -708,7 +708,9 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer if (verbose) printf("@%d ", r->nr); - if (r->action > PF_NORDR) + if (r->action == PF_MATCH) + printf("match"); + else if (r->action > PF_NORDR) printf("action(%d)", r->action); else if (anchor_call[0]) { if (anchor_call[0] == '_') { diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 17af5d46a183..46b71c5eedce 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -332,6 +332,11 @@ struct pf_kpool { u_int8_t opts; }; +struct pf_rule_actions { + u_int32_t qid; + u_int32_t pqid; +}; + union pf_krule_ptr { struct pf_krule *ptr; u_int32_t nr; @@ -607,6 +612,8 @@ struct pf_kstate { u_int32_t creation; u_int32_t expire; u_int32_t pfsync_time; + u_int32_t qid; + u_int32_t pqid; u_int16_t tag; u_int8_t log; u_int8_t state_flags; @@ -1057,6 +1064,7 @@ struct pf_pdesc { u_int16_t *sport; u_int16_t *dport; struct pf_mtag *pf_mtag; + struct pf_rule_actions act; u_int32_t p_len; /* total length of payload */ diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 3ca921ff3287..7d73f1d119e4 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -257,6 +257,8 @@ static int pf_state_key_attach(struct pf_state_key *, static void pf_state_key_detach(struct pf_kstate *, int); 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_test_rule(struct pf_krule **, struct pf_kstate **, int, struct pfi_kkif *, struct mbuf *, int, struct pf_pdesc *, struct pf_krule **, @@ -3112,6 +3114,15 @@ pf_addr_inc(struct pf_addr *addr, sa_family_t af) } #endif /* INET6 */ +void +pf_rule_to_actions(struct pf_krule *r, struct pf_rule_actions *a) +{ + if (r->qid) + a->qid = r->qid; + if (r->pqid) + a->pqid = r->pqid; +} + int pf_socket_lookup(int direction, struct pf_pdesc *pd, struct mbuf *m) { @@ -3620,10 +3631,20 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction, if (r->rtableid >= 0) rtableid = r->rtableid; if (r->anchor == NULL) { - match = 1; - *rm = r; - *am = a; - *rsm = ruleset; + if (r->action == PF_MATCH) { + counter_u64_add(r->packets[direction == PF_OUT], 1); + counter_u64_add(r->bytes[direction == PF_OUT], pd->tot_len); + pf_rule_to_actions(r, &pd->act); + if (r->log) + PFLOG_PACKET(kif, m, af, + direction, PFRES_MATCH, r, + a, ruleset, pd, 1); + } else { + match = 1; + *rm = r; + *am = a; + *rsm = ruleset; + } if ((*rm)->quick) break; r = TAILQ_NEXT(r, entries); @@ -3642,6 +3663,9 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction, REASON_SET(&reason, PFRES_MATCH); + /* apply actions for last matching pass/block rule */ + pf_rule_to_actions(r, &pd->act); + if (r->log || (nr != NULL && nr->log)) { if (rewrite) m_copyback(m, off, hdrlen, pd->hdr.any); @@ -3760,6 +3784,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, s->state_flags |= PFSTATE_SLOPPY; s->log = r->log & PF_LOG_ALL; s->sync_state = PFSYNC_S_NONE; + s->qid = pd->act.qid; + s->pqid = pd->act.pqid; if (nr != NULL) s->log |= nr->log & PF_LOG_ALL; switch (pd->proto) { @@ -4019,10 +4045,20 @@ pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kkif *kif, r = TAILQ_NEXT(r, entries); else { if (r->anchor == NULL) { - match = 1; - *rm = r; - *am = a; - *rsm = ruleset; + if (r->action == PF_MATCH) { + counter_u64_add(r->packets[direction == PF_OUT], 1); + counter_u64_add(r->bytes[direction == PF_OUT], pd->tot_len); + pf_rule_to_actions(r, &pd->act); + if (r->log) + PFLOG_PACKET(kif, m, af, + direction, PFRES_MATCH, r, + a, ruleset, pd, 1); + } else { + match = 1; + *rm = r; + *am = a; + *rsm = ruleset; + } if ((*rm)->quick) break; r = TAILQ_NEXT(r, entries); @@ -4041,6 +4077,9 @@ pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kkif *kif, REASON_SET(&reason, PFRES_MATCH); + /* apply actions for last matching pass/block rule */ + pf_rule_to_actions(r, &pd->act); + if (r->log) PFLOG_PACKET(kif, m, af, direction, reason, r, a, ruleset, pd, 1); @@ -6152,7 +6191,14 @@ done: } #ifdef ALTQ - if (action == PF_PASS && r->qid) { + if (s && s->qid) { + pd.act.pqid = s->pqid; + pd.act.qid = s->qid; + } else if (r->qid) { + pd.act.pqid = r->pqid; + pd.act.qid = r->qid; + } + if (action == PF_PASS && pd.act.qid) { if (pd.pf_mtag == NULL && ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { action = PF_DROP; @@ -6161,9 +6207,9 @@ done: if (s != NULL) pd.pf_mtag->qid_hash = pf_state_hash(s); if (pqid || (pd.tos & IPTOS_LOWDELAY)) - pd.pf_mtag->qid = r->pqid; + pd.pf_mtag->qid = pd.act.pqid; else - pd.pf_mtag->qid = r->qid; + pd.pf_mtag->qid = pd.act.qid; /* Add hints for ecn. */ pd.pf_mtag->hdr = h; } @@ -6592,7 +6638,14 @@ done: } #ifdef ALTQ - if (action == PF_PASS && r->qid) { + if (s && s->qid) { + pd.act.pqid = s->pqid; + pd.act.qid = s->qid; + } else if (r->qid) { + pd.act.pqid = r->pqid; + pd.act.qid = r->qid; + } + if (action == PF_PASS && pd.act.qid) { if (pd.pf_mtag == NULL && ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { action = PF_DROP; @@ -6601,9 +6654,9 @@ done: if (s != NULL) pd.pf_mtag->qid_hash = pf_state_hash(s); if (pd.tos & IPTOS_LOWDELAY) - pd.pf_mtag->qid = r->pqid; + pd.pf_mtag->qid = pd.act.pqid; else - pd.pf_mtag->qid = r->qid; + pd.pf_mtag->qid = pd.act.qid; /* Add hints for ecn. */ pd.pf_mtag->hdr = h; } diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index 6df1426c9e0c..d8ee43506d99 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -49,7 +49,8 @@ enum { PF_INOUT, PF_IN, PF_OUT }; enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT, - PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER }; + PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER, + PF_MATCH }; enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT, PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX }; enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT, diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c index ad1b07f69fe6..c21f4dfdd4a0 100644 --- a/sys/netpfil/pf/pf_ruleset.c +++ b/sys/netpfil/pf/pf_ruleset.c @@ -95,6 +95,7 @@ pf_get_ruleset_number(u_int8_t action) return (PF_RULESET_SCRUB); break; case PF_PASS: + case PF_MATCH: case PF_DROP: return (PF_RULESET_FILTER); break;