aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pfvar.h1
-rw-r--r--sys/netpfil/pf/pf.c64
-rw-r--r--sys/netpfil/pf/pf_nv.c30
3 files changed, 87 insertions, 8 deletions
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 57acab788b20..a61feb07334f 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -646,6 +646,7 @@ struct pf_keth_rule {
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
index fb0abc8cd035..a900da0b8bd1 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -279,7 +279,7 @@ 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_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 @@ pf_match_eth_addr(const uint8_t *a, const struct pf_keth_rule_addr *r)
}
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 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m)
"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 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf *m)
"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 @@ pf_test_eth(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0,
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
index 42434dabf565..3b0d92cc5d20 100644
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -1071,6 +1071,22 @@ pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
}
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 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
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)));