Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153502766
D34917.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D34917.diff
View Options
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -3262,13 +3262,15 @@
}
| 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
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2153,6 +2153,8 @@
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
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -3845,6 +3845,8 @@
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 @@
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 @@
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 @@
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 @@
**/
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 @@
action = r->action;
+ PF_RULES_RUNLOCK();
+
return (action);
}
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -520,6 +520,11 @@
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 @@
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 @@
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
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -1147,7 +1147,8 @@
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 @@
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
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -2151,6 +2151,44 @@
}
}
+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
--- a/tests/sys/netpfil/pf/ether.sh
+++ b/tests/sys/netpfil/pf/ether.sh
@@ -537,10 +537,12 @@
"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 <test>" | \
- atf_check -s exit:1 -o ignore -e ignore \
- jexec alcatraz pfctl -g -f -
+ # Test table
+ pft_set_rules alcatraz \
+ "table <tbl> { 192.0.2.3 }" \
+ "ether pass" \
+ "ether block out l3 to <tbl>"
+ atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
}
ip_cleanup()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 22, 12:11 PM (8 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31978001
Default Alt Text
D34917.diff (6 KB)
Attached To
Mode
D34917: pf: allow the use of tables in ethernet rules
Attached
Detach File
Event Timeline
Log In to Comment