summaryrefslogtreecommitdiffstats
path: root/sys/netpfil/pf
diff options
context:
space:
mode:
authorkp <kp@FreeBSD.org>2016-06-17 18:21:55 +0000
committerkp <kp@FreeBSD.org>2016-06-17 18:21:55 +0000
commitb06d3a64e7ac5d5033eced5e6cc06e9fc2371915 (patch)
tree513dc21f57cd1bcfc5d1de31452d9f22ae3093ff /sys/netpfil/pf
parentf2d255a0a1535a8148b544aca5623d02e67c0098 (diff)
downloadFreeBSD-src-b06d3a64e7ac5d5033eced5e6cc06e9fc2371915.zip
FreeBSD-src-b06d3a64e7ac5d5033eced5e6cc06e9fc2371915.tar.gz
pf: Filter on and set vlan PCP values
Adopt the OpenBSD syntax for setting and filtering on VLAN PCP values. This introduces two new keywords: 'set prio' to set the PCP value, and 'prio' to filter on it. Reviewed by: allanjude, araujo Approved by: re (gjb) Obtained from: OpenBSD (mostly) Differential Revision: https://reviews.freebsd.org/D6786
Diffstat (limited to 'sys/netpfil/pf')
-rw-r--r--sys/netpfil/pf/pf.c72
-rw-r--r--sys/netpfil/pf/pf_ioctl.c4
2 files changed, 75 insertions, 1 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index a35f9e4..02fc7f0 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
+#include <net/if_vlan_var.h>
#include <net/route.h>
#include <net/radix_mpath.h>
#include <net/vnet.h>
@@ -2445,6 +2446,45 @@ pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
pf_send(pfse);
}
+static int
+pf_ieee8021q_setpcp(struct mbuf *m, u_int8_t prio)
+{
+ struct m_tag *mtag;
+
+ KASSERT(prio <= PF_PRIO_MAX,
+ ("%s with invalid pcp", __func__));
+
+ mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_OUT, NULL);
+ if (mtag == NULL) {
+ mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_OUT,
+ sizeof(uint8_t), M_NOWAIT);
+ if (mtag == NULL)
+ return (ENOMEM);
+ m_tag_prepend(m, mtag);
+ }
+
+ *(uint8_t *)(mtag + 1) = prio;
+ return (0);
+}
+
+static int
+pf_match_ieee8021q_pcp(u_int8_t prio, struct mbuf *m)
+{
+ struct m_tag *mtag;
+ u_int8_t mpcp;
+
+ mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_IN, NULL);
+ if (mtag == NULL)
+ return (0);
+
+ if (prio == PF_PRIO_ZERO)
+ prio = 0;
+
+ mpcp = *(uint8_t *)(mtag + 1);
+
+ return (mpcp == prio);
+}
+
static void
pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
struct pf_rule *r)
@@ -3317,6 +3357,9 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
pd->lookup.gid))
r = TAILQ_NEXT(r, entries);
+ else if (r->prio &&
+ !pf_match_ieee8021q_pcp(r->prio, m))
+ r = TAILQ_NEXT(r, entries);
else if (r->prob &&
r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
@@ -3779,6 +3822,9 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
pd->proto == IPPROTO_ICMPV6) &&
(r->type || r->code))
r = TAILQ_NEXT(r, entries);
+ else if (r->prio &&
+ !pf_match_ieee8021q_pcp(r->prio, m))
+ r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <=
(arc4random() % (UINT_MAX - 1) + 1))
r = TAILQ_NEXT(r, entries);
@@ -6003,6 +6049,18 @@ done:
if (r->rtableid >= 0)
M_SETFIB(m, r->rtableid);
+ if (r->scrub_flags & PFSTATE_SETPRIO) {
+ if (pd.tos & IPTOS_LOWDELAY)
+ pqid = 1;
+ if (pf_ieee8021q_setpcp(m, r->set_prio[pqid])) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: failed to allocate 802.1q mtag\n"));
+ }
+ }
+
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
if (pd.pf_mtag == NULL &&
@@ -6176,7 +6234,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, terminal = 0, dirndx, rh_cnt = 0;
+ int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0;
int fwdir = dir;
M_ASSERTPKTHDR(m);
@@ -6449,6 +6507,18 @@ done:
if (r->rtableid >= 0)
M_SETFIB(m, r->rtableid);
+ if (r->scrub_flags & PFSTATE_SETPRIO) {
+ if (pd.tos & IPTOS_LOWDELAY)
+ pqid = 1;
+ if (pf_ieee8021q_setpcp(m, r->set_prio[pqid])) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: failed to allocate 802.1q mtag\n"));
+ }
+ }
+
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
if (pd.pf_mtag == NULL &&
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 83eabcd..3291c9b 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -1242,6 +1242,10 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = ENOMEM;
if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL;
+ if (rule->scrub_flags & PFSTATE_SETPRIO &&
+ (rule->set_prio[0] > PF_PRIO_MAX ||
+ rule->set_prio[1] > PF_PRIO_MAX))
+ error = EINVAL;
TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
if (pa->addr.type == PF_ADDR_TABLE) {
pa->addr.p.tbl = pfr_attach_table(ruleset,
OpenPOWER on IntegriCloud