mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-03 23:28:58 +00:00
pf: match keyword support
Support the 'match' keyword.
Note that support is limited to adding queuing information, so without
ALTQ support in the kernel setting match rules is pointless.
For the avoidance of doubt: this is NOT full support for the match
keyword as found in OpenBSD's pf. That could potentially be built on top
of this, but this commit is NOT that.
MFC after: 2 weeks
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D31115
(cherry picked from commit ef950daa35
)
This commit is contained in:
parent
2400173b93
commit
70d4a7a966
|
@ -456,7 +456,7 @@ int parseport(char *, struct range *r, int);
|
|||
|
||||
%}
|
||||
|
||||
%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
|
||||
%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
|
||||
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
|
||||
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
|
||||
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
|
||||
|
@ -2692,6 +2692,7 @@ action : PASS {
|
|||
$$.w = returnicmpdefault;
|
||||
$$.w2 = returnicmp6default;
|
||||
}
|
||||
| MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
|
||||
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
|
||||
;
|
||||
|
||||
|
@ -5627,6 +5628,7 @@ lookup(char *s)
|
|||
{ "log", LOG},
|
||||
{ "loginterface", LOGINTERFACE},
|
||||
{ "map-e-portset", MAPEPORTSET},
|
||||
{ "match", MATCH},
|
||||
{ "max", MAXIMUM},
|
||||
{ "max-mss", MAXMSS},
|
||||
{ "max-src-conn", MAXSRCCONN},
|
||||
|
|
|
@ -106,6 +106,7 @@ pf_get_ruleset_number(u_int8_t action)
|
|||
break;
|
||||
case PF_PASS:
|
||||
case PF_DROP:
|
||||
case PF_MATCH:
|
||||
return (PF_RULESET_FILTER);
|
||||
break;
|
||||
case PF_NAT:
|
||||
|
|
|
@ -713,7 +713,9 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
|
|||
|
||||
if (verbose)
|
||||
printf("@%d ", r->nr);
|
||||
if (r->action > PF_NORDR)
|
||||
if (r->action == PF_MATCH)
|
||||
printf("match");
|
||||
else if (r->action > PF_NORDR)
|
||||
printf("action(%d)", r->action);
|
||||
else if (anchor_call[0]) {
|
||||
if (anchor_call[0] == '_') {
|
||||
|
|
|
@ -339,6 +339,11 @@ struct pf_kpool {
|
|||
u_int8_t opts;
|
||||
};
|
||||
|
||||
struct pf_rule_actions {
|
||||
u_int32_t qid;
|
||||
u_int32_t pqid;
|
||||
};
|
||||
|
||||
union pf_krule_ptr {
|
||||
struct pf_krule *ptr;
|
||||
u_int32_t nr;
|
||||
|
@ -625,6 +630,8 @@ struct pf_kstate {
|
|||
u_int32_t creation;
|
||||
u_int32_t expire;
|
||||
u_int32_t pfsync_time;
|
||||
u_int32_t qid;
|
||||
u_int32_t pqid;
|
||||
u_int16_t tag;
|
||||
u_int8_t log;
|
||||
};
|
||||
|
@ -1068,6 +1075,7 @@ struct pf_pdesc {
|
|||
u_int16_t *sport;
|
||||
u_int16_t *dport;
|
||||
struct pf_mtag *pf_mtag;
|
||||
struct pf_rule_actions act;
|
||||
|
||||
u_int32_t p_len; /* total length of payload */
|
||||
|
||||
|
|
|
@ -251,6 +251,8 @@ static int pf_state_key_attach(struct pf_state_key *,
|
|||
static void pf_state_key_detach(struct pf_kstate *, int);
|
||||
static int pf_state_key_ctor(void *, int, void *, int);
|
||||
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_rule(struct pf_krule **, struct pf_kstate **,
|
||||
int, struct pfi_kkif *, struct mbuf *, int,
|
||||
struct pf_pdesc *, struct pf_krule **,
|
||||
|
@ -3133,6 +3135,15 @@ pf_addr_inc(struct pf_addr *addr, sa_family_t af)
|
|||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
void
|
||||
pf_rule_to_actions(struct pf_krule *r, struct pf_rule_actions *a)
|
||||
{
|
||||
if (r->qid)
|
||||
a->qid = r->qid;
|
||||
if (r->pqid)
|
||||
a->pqid = r->pqid;
|
||||
}
|
||||
|
||||
int
|
||||
pf_socket_lookup(int direction, struct pf_pdesc *pd, struct mbuf *m)
|
||||
{
|
||||
|
@ -3641,10 +3652,20 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction,
|
|||
if (r->rtableid >= 0)
|
||||
rtableid = r->rtableid;
|
||||
if (r->anchor == NULL) {
|
||||
match = 1;
|
||||
*rm = r;
|
||||
*am = a;
|
||||
*rsm = ruleset;
|
||||
if (r->action == PF_MATCH) {
|
||||
counter_u64_add(r->packets[direction == PF_OUT], 1);
|
||||
counter_u64_add(r->bytes[direction == PF_OUT], pd->tot_len);
|
||||
pf_rule_to_actions(r, &pd->act);
|
||||
if (r->log)
|
||||
PFLOG_PACKET(kif, m, af,
|
||||
direction, PFRES_MATCH, r,
|
||||
a, ruleset, pd, 1);
|
||||
} else {
|
||||
match = 1;
|
||||
*rm = r;
|
||||
*am = a;
|
||||
*rsm = ruleset;
|
||||
}
|
||||
if ((*rm)->quick)
|
||||
break;
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
|
@ -3663,6 +3684,9 @@ pf_test_rule(struct pf_krule **rm, struct pf_kstate **sm, int direction,
|
|||
|
||||
REASON_SET(&reason, PFRES_MATCH);
|
||||
|
||||
/* apply actions for last matching pass/block rule */
|
||||
pf_rule_to_actions(r, &pd->act);
|
||||
|
||||
if (r->log || (nr != NULL && nr->log)) {
|
||||
if (rewrite)
|
||||
m_copyback(m, off, hdrlen, pd->hdr.any);
|
||||
|
@ -3781,6 +3805,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
|||
s->state_flags |= PFSTATE_SLOPPY;
|
||||
s->log = r->log & PF_LOG_ALL;
|
||||
s->sync_state = PFSYNC_S_NONE;
|
||||
s->qid = pd->act.qid;
|
||||
s->pqid = pd->act.pqid;
|
||||
if (nr != NULL)
|
||||
s->log |= nr->log & PF_LOG_ALL;
|
||||
switch (pd->proto) {
|
||||
|
@ -4040,10 +4066,20 @@ pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kkif *kif,
|
|||
r = TAILQ_NEXT(r, entries);
|
||||
else {
|
||||
if (r->anchor == NULL) {
|
||||
match = 1;
|
||||
*rm = r;
|
||||
*am = a;
|
||||
*rsm = ruleset;
|
||||
if (r->action == PF_MATCH) {
|
||||
counter_u64_add(r->packets[direction == PF_OUT], 1);
|
||||
counter_u64_add(r->bytes[direction == PF_OUT], pd->tot_len);
|
||||
pf_rule_to_actions(r, &pd->act);
|
||||
if (r->log)
|
||||
PFLOG_PACKET(kif, m, af,
|
||||
direction, PFRES_MATCH, r,
|
||||
a, ruleset, pd, 1);
|
||||
} else {
|
||||
match = 1;
|
||||
*rm = r;
|
||||
*am = a;
|
||||
*rsm = ruleset;
|
||||
}
|
||||
if ((*rm)->quick)
|
||||
break;
|
||||
r = TAILQ_NEXT(r, entries);
|
||||
|
@ -4062,6 +4098,9 @@ pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kkif *kif,
|
|||
|
||||
REASON_SET(&reason, PFRES_MATCH);
|
||||
|
||||
/* apply actions for last matching pass/block rule */
|
||||
pf_rule_to_actions(r, &pd->act);
|
||||
|
||||
if (r->log)
|
||||
PFLOG_PACKET(kif, m, af, direction, reason, r, a, ruleset, pd,
|
||||
1);
|
||||
|
@ -6237,7 +6276,14 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
|
|||
}
|
||||
|
||||
#ifdef ALTQ
|
||||
if (action == PF_PASS && r->qid) {
|
||||
if (s && s->qid) {
|
||||
pd.act.pqid = s->pqid;
|
||||
pd.act.qid = s->qid;
|
||||
} else if (r->qid) {
|
||||
pd.act.pqid = r->pqid;
|
||||
pd.act.qid = r->qid;
|
||||
}
|
||||
if (action == PF_PASS && pd.act.qid) {
|
||||
if (pd.pf_mtag == NULL &&
|
||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
|
||||
action = PF_DROP;
|
||||
|
@ -6246,9 +6292,9 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
|
|||
if (s != NULL)
|
||||
pd.pf_mtag->qid_hash = pf_state_hash(s);
|
||||
if (pqid || (pd.tos & IPTOS_LOWDELAY))
|
||||
pd.pf_mtag->qid = r->pqid;
|
||||
pd.pf_mtag->qid = pd.act.pqid;
|
||||
else
|
||||
pd.pf_mtag->qid = r->qid;
|
||||
pd.pf_mtag->qid = pd.act.qid;
|
||||
/* Add hints for ecn. */
|
||||
pd.pf_mtag->hdr = h;
|
||||
}
|
||||
|
@ -6677,7 +6723,14 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
|
|||
}
|
||||
|
||||
#ifdef ALTQ
|
||||
if (action == PF_PASS && r->qid) {
|
||||
if (s && s->qid) {
|
||||
pd.act.pqid = s->pqid;
|
||||
pd.act.qid = s->qid;
|
||||
} else if (r->qid) {
|
||||
pd.act.pqid = r->pqid;
|
||||
pd.act.qid = r->qid;
|
||||
}
|
||||
if (action == PF_PASS && pd.act.qid) {
|
||||
if (pd.pf_mtag == NULL &&
|
||||
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
|
||||
action = PF_DROP;
|
||||
|
@ -6686,9 +6739,9 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
|
|||
if (s != NULL)
|
||||
pd.pf_mtag->qid_hash = pf_state_hash(s);
|
||||
if (pd.tos & IPTOS_LOWDELAY)
|
||||
pd.pf_mtag->qid = r->pqid;
|
||||
pd.pf_mtag->qid = pd.act.pqid;
|
||||
else
|
||||
pd.pf_mtag->qid = r->qid;
|
||||
pd.pf_mtag->qid = pd.act.qid;
|
||||
/* Add hints for ecn. */
|
||||
pd.pf_mtag->hdr = h;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
|
||||
enum { PF_INOUT, PF_IN, PF_OUT };
|
||||
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
|
||||
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
|
||||
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER,
|
||||
PF_MATCH };
|
||||
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
|
||||
PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
|
||||
enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT,
|
||||
|
|
|
@ -95,6 +95,7 @@ pf_get_ruleset_number(u_int8_t action)
|
|||
return (PF_RULESET_SCRUB);
|
||||
break;
|
||||
case PF_PASS:
|
||||
case PF_MATCH:
|
||||
case PF_DROP:
|
||||
return (PF_RULESET_FILTER);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue