Page MenuHomeFreeBSD

D34482.diff
No OneTemporary

D34482.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -89,6 +89,7 @@
uint8_t direction;
uint16_t proto;
struct pfctl_eth_addr src, dst;
+ struct pf_rule_addr ipsrc, ipdst;
/* Stats */
uint64_t evaluations;
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -598,6 +598,11 @@
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"),
&rule->dst);
+ pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipsrc"),
+ &rule->ipsrc);
+ pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipdst"),
+ &rule->ipdst);
+
rule->evaluations = nvlist_get_number(nvl, "evaluations");
rule->packets[0] = nvlist_get_number(nvl, "packets-in");
rule->packets[1] = nvlist_get_number(nvl, "packets-out");
@@ -659,7 +664,7 @@
const char *path, struct pfctl_eth_rule *rule, bool clear,
char *anchor_call)
{
- uint8_t buf[1024];
+ uint8_t buf[2048];
struct pfioc_nv nv;
nvlist_t *nvl;
void *data;
@@ -738,6 +743,9 @@
nvlist_add_nvlist(nvl, "dst", addr);
nvlist_destroy(addr);
+ pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc);
+ pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst);
+
nvlist_add_string(nvl, "qname", r->qname);
nvlist_add_string(nvl, "tagname", r->tagname);
nvlist_add_number(nvl, "dnpipe", r->dnpipe);
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -350,7 +350,8 @@
struct pfctl_rule *);
void expand_eth_rule(struct pfctl_eth_rule *,
struct node_if *, struct node_etherproto *,
- struct node_mac *, struct node_mac *, const char *);
+ struct node_mac *, struct node_mac *,
+ struct node_host *, struct node_host *, const char *);
void expand_rule(struct pfctl_rule *, struct node_if *,
struct node_host *, struct node_proto *, struct node_os *,
struct node_host *, struct node_port *, struct node_host *,
@@ -492,7 +493,7 @@
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES
+%token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3
%token ETHER
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
@@ -523,7 +524,7 @@
%type <v.icmp> icmp_list icmp_item
%type <v.icmp> icmp6_list icmp6_item
%type <v.number> reticmpspec reticmp6spec
-%type <v.fromto> fromto
+%type <v.fromto> fromto l3fromto
%type <v.peer> ipportspec from to
%type <v.host> ipspec toipspec xhost host dynaddr host_list
%type <v.host> redir_host_list redirspec
@@ -1182,7 +1183,7 @@
}
;
-etherrule : ETHER action dir quick interface etherproto etherfromto etherfilter_opts
+etherrule : ETHER action dir quick interface etherproto etherfromto l3fromto etherfilter_opts
{
struct pfctl_eth_rule r;
@@ -1194,14 +1195,15 @@
r.action = $2.b1;
r.direction = $3;
r.quick = $4.quick;
- if ($8.tag != NULL)
- memcpy(&r.tagname, $8.tag, sizeof(r.tagname));
- if ($8.queues.qname != NULL)
- memcpy(&r.qname, $8.queues.qname, sizeof(r.qname));
- r.dnpipe = $8.dnpipe;
- r.dnflags = $8.free_flags;
+ if ($9.tag != NULL)
+ memcpy(&r.tagname, $9.tag, sizeof(r.tagname));
+ if ($9.queues.qname != NULL)
+ memcpy(&r.qname, $9.queues.qname, sizeof(r.qname));
+ r.dnpipe = $9.dnpipe;
+ r.dnflags = $9.free_flags;
- expand_eth_rule(&r, $5, $6, $7.src, $7.dst, "");
+ expand_eth_rule(&r, $5, $6, $7.src, $7.dst,
+ $8.src.host, $8.dst.host, "");
}
;
@@ -1236,7 +1238,7 @@
| /* empty */
;
-etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfromto etherpfa_anchor
+etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfromto l3fromto etherpfa_anchor
{
struct pfctl_eth_rule r;
@@ -1286,6 +1288,7 @@
r.quick = $5.quick;
expand_eth_rule(&r, $6, $7, $8.src, $8.dst,
+ $9.src.host, $9.dst.host,
pf->eastack[pf->asd + 1] ? pf->ealast->name : $3);
free($3);
@@ -3254,6 +3257,13 @@
}
;
+l3fromto : /* empty */ {
+ bzero(&$$, sizeof($$));
+ }
+ | L3 fromto {
+ $$ = $2;
+ }
+ ;
etherfromto : ALL {
$$.src = NULL;
$$.dst = NULL;
@@ -5733,23 +5743,45 @@
return (0);
}
+static int
+pf_af_to_proto(sa_family_t af)
+{
+ if (af == AF_INET)
+ return (ETHERTYPE_IP);
+ if (af == AF_INET6)
+ return (ETHERTYPE_IPV6);
+
+ return (0);
+}
+
void
expand_eth_rule(struct pfctl_eth_rule *r,
struct node_if *interfaces, struct node_etherproto *protos,
- struct node_mac *srcs, struct node_mac *dsts, const char *anchor_call)
+ struct node_mac *srcs, struct node_mac *dsts,
+ struct node_host *ipsrcs, struct node_host *ipdsts, const char *anchor_call)
{
LOOP_THROUGH(struct node_if, interface, interfaces,
LOOP_THROUGH(struct node_etherproto, proto, protos,
LOOP_THROUGH(struct node_mac, src, srcs,
LOOP_THROUGH(struct node_mac, dst, dsts,
+ LOOP_THROUGH(struct node_host, ipsrc, ipsrcs,
+ LOOP_THROUGH(struct node_host, ipdst, ipdsts,
strlcpy(r->ifname, interface->ifname,
sizeof(r->ifname));
r->ifnot = interface->not;
r->proto = proto->proto;
+ if (!r->proto && ipsrc->af)
+ r->proto = pf_af_to_proto(ipsrc->af);
+ else if (!r->proto && ipdst->af)
+ r->proto = pf_af_to_proto(ipdst->af);
bcopy(src->mac, r->src.addr, ETHER_ADDR_LEN);
bcopy(src->mask, r->src.mask, ETHER_ADDR_LEN);
r->src.neg = src->neg;
r->src.isset = src->isset;
+ r->ipsrc.addr = ipsrc->addr;
+ r->ipsrc.neg = ipsrc->not;
+ r->ipdst.addr = ipdst->addr;
+ r->ipdst.neg = ipdst->not;
bcopy(dst->mac, r->dst.addr, ETHER_ADDR_LEN);
bcopy(dst->mask, r->dst.mask, ETHER_ADDR_LEN);
r->dst.neg = dst->neg;
@@ -5757,12 +5789,14 @@
r->nr = pf->eastack[pf->asd]->match++;
pfctl_append_eth_rule(pf, r, anchor_call);
- ))));
+ ))))));
FREE_LIST(struct node_if, interfaces);
FREE_LIST(struct node_etherproto, protos);
FREE_LIST(struct node_mac, srcs);
FREE_LIST(struct node_mac, dsts);
+ FREE_LIST(struct node_host, ipsrcs);
+ FREE_LIST(struct node_host, ipdsts);
}
void
@@ -6052,6 +6086,7 @@
{ "interval", INTERVAL},
{ "keep", KEEP},
{ "keepcounters", KEEPCOUNTERS},
+ { "l3", L3},
{ "label", LABEL},
{ "limit", LIMIT},
{ "linkshare", LINKSHARE},
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -782,7 +782,12 @@
printf(" to ");
print_eth_addr(&r->dst);
}
-
+ if (r->proto == ETHERTYPE_IP || r->proto == ETHERTYPE_IPV6) {
+ printf(" l3");
+ print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst,
+ r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0,
+ 0, 0);
+ }
if (r->qname[0])
printf(" queue %s", r->qname);
if (r->tagname[0])
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd September 25, 2021
+.Dd March 9, 2022
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -3072,7 +3072,7 @@
ether-rule = "ether" etheraction [ ( "in" | "out" ) ]
[ "quick" ] [ "on" ifspec ] [ etherprotospec ]
- etherhosts [ etherfilteropt-list ]
+ etherhosts [ "l3" hosts ] [ etherfilteropt-list ]
pf-rule = action [ ( "in" | "out" ) ]
[ "log" [ "(" logopts ")"] ] [ "quick" ]
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -646,6 +646,7 @@
uint8_t direction;
uint16_t proto;
struct pf_keth_rule_addr src, dst;
+ struct pf_rule_addr ipsrc, ipdst;
/* Stats */
counter_u64_t evaluations;
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
@@ -279,7 +279,7 @@
void pf_rule_to_actions(struct pf_krule *,
struct pf_rule_actions *);
static int pf_test_eth_rule(int, struct pfi_kkif *,
- struct mbuf *);
+ struct mbuf **);
static int pf_test_rule(struct pf_krule **, struct pf_kstate **,
int, struct pfi_kkif *, struct mbuf *, int,
struct pf_pdesc *, struct pf_krule **,
@@ -3826,31 +3826,67 @@
}
static int
-pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m)
+pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0)
{
+ struct mbuf *m = *m0;
struct ether_header *e;
struct pf_keth_rule *r, *rm, *a = NULL;
struct pf_keth_ruleset *ruleset = NULL;
struct pf_mtag *mtag;
struct pf_keth_ruleq *rules;
+ struct pf_addr *src, *dst;
+ sa_family_t af = 0;
+ uint16_t proto;
int asd = 0, match = 0;
uint8_t action;
struct pf_keth_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE];
- NET_EPOCH_ASSERT();
-
MPASS(kif->pfik_ifp->if_vnet == curvnet);
NET_EPOCH_ASSERT();
SDT_PROBE3(pf, eth, test_rule, entry, dir, kif->pfik_ifp, m);
- e = mtod(m, struct ether_header *);
-
ruleset = V_pf_keth;
rules = ck_pr_load_ptr(&ruleset->active.rules);
r = TAILQ_FIRST(rules);
rm = NULL;
+ e = mtod(m, struct ether_header *);
+ proto = ntohs(e->ether_type);
+
+ switch (proto) {
+ case ETHERTYPE_IP: {
+ struct ip *ip;
+ m = m_pullup(m, sizeof(struct ether_header) +
+ sizeof(struct ip));
+ if (m == NULL) {
+ *m0 = NULL;
+ return (PF_DROP);
+ }
+ af = AF_INET;
+ ip = mtodo(m, sizeof(struct ether_header));
+ src = (struct pf_addr *)&ip->ip_src;
+ dst = (struct pf_addr *)&ip->ip_dst;
+ break;
+ }
+ case ETHERTYPE_IPV6: {
+ struct ip6_hdr *ip6;
+ m = m_pullup(m, sizeof(struct ether_header) +
+ sizeof(struct ip6_hdr));
+ if (m == NULL) {
+ *m0 = NULL;
+ return (PF_DROP);
+ }
+ af = AF_INET6;
+ ip6 = mtodo(m, sizeof(struct ether_header));
+ src = (struct pf_addr *)&ip6->ip6_src;
+ dst = (struct pf_addr *)&ip6->ip6_dst;
+ break;
+ }
+ }
+ e = mtod(m, struct ether_header *);
+ *m0 = m;
+
while (r != NULL) {
counter_u64_add(r->evaluations, 1);
SDT_PROBE2(pf, eth, test_rule, test, r->nr, r);
@@ -3865,7 +3901,7 @@
"dir");
r = r->skip[PFE_SKIP_DIR].ptr;
}
- else if (r->proto && r->proto != ntohs(e->ether_type)) {
+ else if (r->proto && r->proto != proto) {
SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r,
"proto");
r = r->skip[PFE_SKIP_PROTO].ptr;
@@ -3880,6 +3916,18 @@
"dst");
r = TAILQ_NEXT(r, entries);
}
+ else if (af != 0 && PF_MISMATCHAW(&r->ipsrc.addr, src, af,
+ r->ipsrc.neg, kif, M_GETFIB(m))) {
+ SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r,
+ "ip_src");
+ r = TAILQ_NEXT(r, entries);
+ }
+ else if (af != 0 && PF_MISMATCHAW(&r->ipdst.addr, dst, af,
+ r->ipdst.neg, kif, M_GETFIB(m))) {
+ SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r,
+ "ip_dst");
+ r = TAILQ_NEXT(r, entries);
+ }
else {
if (r->anchor == NULL) {
/* Rule matches */
@@ -6737,7 +6785,7 @@
return (PF_PASS);
/* Stateless! */
- return (pf_test_eth_rule(dir, kif, m));
+ return (pf_test_eth_rule(dir, kif, m0));
}
#ifdef INET
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
@@ -1071,6 +1071,22 @@
}
nvlist_add_nvlist(nvl, "dst", addr);
+ addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc);
+ if (addr == NULL) {
+ nvlist_destroy(nvl);
+ return (NULL);
+ }
+ nvlist_add_nvlist(nvl, "ipsrc", addr);
+ nvlist_destroy(addr);
+
+ addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst);
+ if (addr == NULL) {
+ nvlist_destroy(nvl);
+ return (NULL);
+ }
+ nvlist_add_nvlist(nvl, "ipdst", addr);
+ nvlist_destroy(addr);
+
nvlist_add_number(nvl, "evaluations",
counter_u64_fetch(krule->evaluations));
nvlist_add_number(nvl, "packets-in",
@@ -1125,6 +1141,20 @@
return (error);
}
+ if (nvlist_exists_nvlist(nvl, "ipsrc")) {
+ error = pf_nvrule_addr_to_rule_addr(
+ nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc);
+ if (error != 0)
+ return (error);
+ }
+
+ if (nvlist_exists_nvlist(nvl, "ipdst")) {
+ error = pf_nvrule_addr_to_rule_addr(
+ nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst);
+ if (error != 0)
+ return (error);
+ }
+
PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname)));
PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname,
sizeof(krule->tagname)));

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 14, 2:15 PM (20 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16643563
Default Alt Text
D34482.diff (12 KB)

Event Timeline