summaryrefslogtreecommitdiffstats
path: root/sys/netpfil/pf/pf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netpfil/pf/pf.c')
-rw-r--r--sys/netpfil/pf/pf.c72
1 files changed, 71 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 &&
OpenPOWER on IntegriCloud