From nobody Wed Apr 20 11:05:42 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 8865411D865B; Wed, 20 Apr 2022 11:05:42 +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 4KjyWp2yH2z4fcX; Wed, 20 Apr 2022 11:05:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650452742; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=u2rxvgrW9S2ZnMeQlVCc+X+egeDfwYh9Jx7awNRfaAo=; b=R76M6V9AOjB57HqefH63FJNSJ5yOrYMbCFnD6VjWkzt89RzsUvQFhFsXX8lFBOfqG99Qoo szeF89zyJQ2U2lK1rkpfvr9TZr2GoPFPJlD7zUYvKXG6ywQSpJ++mNK8XE2J9wMUjVlIuM lXnrlt+1xZJa/DifExlCZ9G2oFZHwYayJJXLi+TTfrNkjMwPZnMyrsbQltacv2CdeaYgi4 +LEkQGzKyArBWGV37Fi1U87xpwcRYks9kUvBz/A/XKB5q4v9P32ue6G4tACseAh/qYpWab EyewuDrz2liio4LEDNp0F2LDMLrMRwFvCMz3huhWUsVBwp2uX8nVMl91m3kbUA== 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 431D912EB6; Wed, 20 Apr 2022 11:05:42 +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 23KB5gre042435; Wed, 20 Apr 2022 11:05:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 23KB5g6Z042434; Wed, 20 Apr 2022 11:05:42 GMT (envelope-from git) Date: Wed, 20 Apr 2022 11:05:42 GMT Message-Id: <202204201105.23KB5g6Z042434@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: 812839e5aaaf - main - pf: allow the use of tables in ethernet rules List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org 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: 812839e5aaaf495a85ac7dcb743b565c4792d74d Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650452742; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=u2rxvgrW9S2ZnMeQlVCc+X+egeDfwYh9Jx7awNRfaAo=; b=npDHbMVZ63YubeIgtovDiBvgoipvof1TbjHK2CVYz92cvIOOU48BRf30U91MmtYmBxV+hr moYJ51iDpRr3VB9kA7Ra0VZMwXM11/NSlxKzQ8tcMKc6er+yF0wpjePTALBFRuDsxihOLS nCLyi3ahuvhRaz/B9MOIhbMjuH0q53bbV8Vdt3nSu0p0CaSBNqGFYjZeO/a6Lb4tr5Opep SMQIqk60wkVE6zR94VNup54zMuo77aj9WFoauqD1MYRZ+HIf9r7vDzGA0FXKS9RzM6Zwte 2IT2Wgg6Xot4H1Q9VxCcT4jPjQ3OhrngCJj/sW+gg7jAdeF+GHEjgf7C+25+dg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1650452742; a=rsa-sha256; cv=none; b=mNm5O5XYgqEnc5wKlwPitZ+iYUfKi8FR+wwXISa9kR/DMrbKPMr8SGH3V1YJ6y1EJSjye+ jqMMj5XFvjViAf02nK30S21FnikkJ9IvQsAm2AmCto5T7KuempnNX5HShyRN0eH3s6/pKX A8OKbdBXXNks5155zy5wCpYKDhugq2EH9K252WBBfaytuYQtZzS2S7tbfxl6II4IssWdHQ NvjeQQCGMiRZ+n9ON2EygzXm64peBE9QbUzKMs5lOR4YNjtCotPQHHVcSLTiV7nD0o6Ujg sLa8+1KAN8a2kI/ZTLSlbZUh56+P7h360dNWTEw1tH8PYOB1In8nT+qe+8fFlw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=812839e5aaaf495a85ac7dcb743b565c4792d74d commit 812839e5aaaf495a85ac7dcb743b565c4792d74d Author: Kristof Provost AuthorDate: 2022-04-12 11:20:18 +0000 Commit: Kristof Provost CommitDate: 2022-04-20 11:01:12 +0000 pf: allow the use of tables in ethernet rules Allow tables to be used for the l3 source/destination matching. This requires taking the PF_RULES read lock. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D34917 --- sbin/pfctl/parse.y | 10 ++++++---- sys/net/pfvar.h | 2 ++ sys/netpfil/pf/pf.c | 17 +++++++++++++++-- sys/netpfil/pf/pf_ioctl.c | 28 ++++++++++++++++++++++++++++ sys/netpfil/pf/pf_nv.c | 6 ++++-- sys/netpfil/pf/pf_table.c | 38 ++++++++++++++++++++++++++++++++++++++ tests/sys/netpfil/pf/ether.sh | 10 ++++++---- 7 files changed, 99 insertions(+), 12 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 5f84a39371f3..21729fc7ba4e 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -3262,13 +3262,15 @@ l3fromto : /* empty */ { } | L3 fromto { if ($2.src.host != NULL && - $2.src.host->addr.type != PF_ADDR_ADDRMASK) { - yyerror("from must be an address"); + $2.src.host->addr.type != PF_ADDR_ADDRMASK && + $2.src.host->addr.type != PF_ADDR_TABLE) { + yyerror("from must be an address or table"); YYERROR; } if ($2.dst.host != NULL && - $2.dst.host->addr.type != PF_ADDR_ADDRMASK) { - yyerror("to must be an address"); + $2.dst.host->addr.type != PF_ADDR_ADDRMASK && + $2.dst.host->addr.type != PF_ADDR_TABLE) { + yyerror("to must be an address or table"); YYERROR; } $$ = $2; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index db6b5c22f07f..adcf69905698 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2153,6 +2153,8 @@ int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * pfr_attach_table(struct pf_kruleset *, char *); +struct pfr_ktable * + pfr_eth_attach_table(struct pf_keth_ruleset *, char *); void pfr_detach_table(struct pfr_ktable *); int pfr_clr_tables(struct pfr_table *, int *, int); int pfr_add_tables(struct pfr_table *, int, int *, int); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index a150c7e86e5e..d27e6f30f945 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3845,6 +3845,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) MPASS(kif->pfik_ifp->if_vnet == curvnet); NET_EPOCH_ASSERT(); + PF_RULES_RLOCK_TRACKER; + SDT_PROBE3(pf, eth, test_rule, entry, dir, kif->pfik_ifp, m); ruleset = V_pf_keth; @@ -3892,6 +3894,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) e = mtod(m, struct ether_header *); *m0 = m; + PF_RULES_RLOCK(); + while (r != NULL) { counter_u64_add(r->evaluations, 1); SDT_PROBE2(pf, eth, test_rule, test, r->nr, r); @@ -3959,20 +3963,25 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) SDT_PROBE2(pf, eth, test_rule, final_match, (r != NULL ? r->nr : -1), r); /* Default to pass. */ - if (r == NULL) + if (r == NULL) { + PF_RULES_RUNLOCK(); return (PF_PASS); + } /* Execute action. */ counter_u64_add(r->packets[dir == PF_OUT], 1); counter_u64_add(r->bytes[dir == PF_OUT], m_length(m, NULL)); /* Shortcut. Don't tag if we're just going to drop anyway. */ - if (r->action == PF_DROP) + if (r->action == PF_DROP) { + PF_RULES_RUNLOCK(); return (PF_DROP); + } if (r->tag > 0) { mtag = pf_get_mtag(m); if (mtag == NULL) { + PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); return (PF_DROP); } @@ -3982,6 +3991,7 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) if (r->qid != 0) { mtag = pf_get_mtag(m); if (mtag == NULL) { + PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); return (PF_DROP); } @@ -3997,6 +4007,7 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) **/ mtag = pf_get_mtag(m); if (mtag == NULL) { + PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); return (PF_DROP); } @@ -4006,6 +4017,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) action = r->action; + PF_RULES_RUNLOCK(); + return (action); } diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 49fdb6046098..86cbf7aa3808 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -520,6 +520,11 @@ pf_free_eth_rule(struct pf_keth_rule *rule) if (rule->kif) pfi_kkif_unref(rule->kif); + if (rule->ipsrc.addr.type == PF_ADDR_TABLE) + pfr_detach_table(rule->ipsrc.addr.p.tbl); + if (rule->ipdst.addr.type == PF_ADDR_TABLE) + pfr_detach_table(rule->ipdst.addr.p.tbl); + counter_u64_free(rule->evaluations); for (int i = 0; i < 2; i++) { counter_u64_free(rule->packets[i]); @@ -1427,6 +1432,24 @@ pf_setup_pfsync_matching(struct pf_kruleset *rs) return (0); } +static int +pf_eth_addr_setup(struct pf_keth_ruleset *ruleset, struct pf_addr_wrap *addr) +{ + int error = 0; + + switch (addr->type) { + case PF_ADDR_TABLE: + addr->p.tbl = pfr_eth_attach_table(ruleset, addr->v.tblname); + if (addr->p.tbl == NULL) + error = ENOMEM; + break; + default: + error = EINVAL; + } + + return (error); +} + static int pf_addr_setup(struct pf_kruleset *ruleset, struct pf_addr_wrap *addr, sa_family_t af) @@ -2843,6 +2866,11 @@ DIOCGETETHRULE_error: if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0) error = EBUSY; + if (error == 0 && rule->ipdst.addr.type == PF_ADDR_TABLE) + error = pf_eth_addr_setup(ruleset, &rule->ipdst.addr); + if (error == 0 && rule->ipsrc.addr.type == PF_ADDR_TABLE) + error = pf_eth_addr_setup(ruleset, &rule->ipsrc.addr); + if (error) { pf_free_eth_rule(rule); PF_RULES_WUNLOCK(); diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c index 85666a5ee111..4dcb5441f835 100644 --- a/sys/netpfil/pf/pf_nv.c +++ b/sys/netpfil/pf/pf_nv.c @@ -1147,7 +1147,8 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl, if (error != 0) return (error); - if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK) + if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK && + krule->ipsrc.addr.type != PF_ADDR_TABLE) return (EINVAL); } @@ -1157,7 +1158,8 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl, if (error != 0) return (error); - if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK) + if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK && + krule->ipdst.addr.type != PF_ADDR_TABLE) return (EINVAL); } diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index a2afd5c24cff..9b048d899810 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -2151,6 +2151,44 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, } } +struct pfr_ktable * +pfr_eth_attach_table(struct pf_keth_ruleset *rs, char *name) +{ + struct pfr_ktable *kt, *rt; + struct pfr_table tbl; + struct pf_keth_anchor *ac = rs->anchor; + + PF_RULES_WASSERT(); + + bzero(&tbl, sizeof(tbl)); + strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)); + if (ac != NULL) + strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor)); + kt = pfr_lookup_table(&tbl); + if (kt == NULL) { + kt = pfr_create_ktable(&tbl, time_second, 1); + if (kt == NULL) + return (NULL); + if (ac != NULL) { + bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor)); + rt = pfr_lookup_table(&tbl); + if (rt == NULL) { + rt = pfr_create_ktable(&tbl, 0, 1); + if (rt == NULL) { + pfr_destroy_ktable(kt, 0); + return (NULL); + } + pfr_insert_ktable(rt); + } + kt->pfrkt_root = rt; + } + pfr_insert_ktable(kt); + } + if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++) + pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED); + return (kt); +} + struct pfr_ktable * pfr_attach_table(struct pf_kruleset *rs, char *name) { diff --git a/tests/sys/netpfil/pf/ether.sh b/tests/sys/netpfil/pf/ether.sh index 7a7f91844148..da936c9cfaeb 100644 --- a/tests/sys/netpfil/pf/ether.sh +++ b/tests/sys/netpfil/pf/ether.sh @@ -537,10 +537,12 @@ ip_body() "ether block out l3 to 192.0.2.3" atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2 - # We can't use tables in these rules - echo "ether pass out l3 from " | \ - atf_check -s exit:1 -o ignore -e ignore \ - jexec alcatraz pfctl -g -f - + # Test table + pft_set_rules alcatraz \ + "table { 192.0.2.3 }" \ + "ether pass" \ + "ether block out l3 to " + atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2 } ip_cleanup()