aboutsummaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-04-20 09:04:48 +0000
committerKristof Provost <kp@FreeBSD.org>2021-04-26 12:14:21 +0000
commit6fcc8e042ac480f9276177339f7de1ad0f95c1b0 (patch)
tree07d745a169e7d2a50b230cf6ccf2f332796cc5f8 /sbin/pfctl
parentcd17774d30c6cb70643c694ddf5a11f3c795dec8 (diff)
downloadsrc-6fcc8e042ac480f9276177339f7de1ad0f95c1b0.tar.gz
src-6fcc8e042ac480f9276177339f7de1ad0f95c1b0.zip
pf: Allow multiple labels to be set on a rule
Allow up to 5 labels to be set on each rule. This offers more flexibility in using labels. For example, it replaces the customer 'schedule' keyword used by pfSense to terminate states according to a schedule. Reviewed by: glebius MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D29936
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/parse.y59
-rw-r--r--sbin/pfctl/pfctl.c16
-rw-r--r--sbin/pfctl/pfctl_parser.c5
3 files changed, 49 insertions, 31 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index e0314241eec3..6acfefbf5ad3 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <net/altq/altq_hfsc.h>
#include <net/altq/altq_fairq.h>
+#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@@ -241,7 +242,8 @@ static struct filter_opts {
} keep;
int fragment;
int allowopts;
- char *label;
+ char *label[PF_RULE_MAX_LABEL_COUNT];
+ int labelcount;
struct node_qassign queues;
char *tag;
char *match_tag;
@@ -256,7 +258,8 @@ static struct filter_opts {
} filter_opts;
static struct antispoof_opts {
- char *label;
+ char *label[PF_RULE_MAX_LABEL_COUNT];
+ int labelcount;
u_int rtableid;
} antispoof_opts;
@@ -349,7 +352,7 @@ int expand_skip_interface(struct node_if *);
int check_rulestate(int);
int getservice(char *);
-int rule_label(struct pfctl_rule *, char *);
+int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
int rt_tableid_max(void);
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
@@ -887,7 +890,8 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
r.match_tag_not = $9.match_tag_not;
if (rule_label(&r, $9.label))
YYERROR;
- free($9.label);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free($9.label[i]);
r.flags = $9.flags.b1;
r.flagset = $9.flags.b2;
if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
@@ -1333,7 +1337,8 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
} else
free(hh);
}
- free($5.label);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free($5.label[i]);
}
;
@@ -1374,11 +1379,11 @@ antispoof_opts_l : antispoof_opts_l antispoof_opt
;
antispoof_opt : label {
- if (antispoof_opts.label) {
- yyerror("label cannot be redefined");
+ if (antispoof_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
+ yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
YYERROR;
}
- antispoof_opts.label = $1;
+ antispoof_opts.label[antispoof_opts.labelcount++] = $1;
}
| RTABLE NUMBER {
if ($2 < 0 || $2 > rt_tableid_max()) {
@@ -2093,7 +2098,8 @@ pfrule : action dir logquick interface route af proto fromto
r.match_tag_not = $9.match_tag_not;
if (rule_label(&r, $9.label))
YYERROR;
- free($9.label);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free($9.label[i]);
r.flags = $9.flags.b1;
r.flagset = $9.flags.b2;
if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
@@ -2531,11 +2537,11 @@ filter_opt : USER uids {
filter_opts.allowopts = 1;
}
| label {
- if (filter_opts.label) {
- yyerror("label cannot be redefined");
+ if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
+ yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
YYERROR;
}
- filter_opts.label = $1;
+ filter_opts.label[filter_opts.labelcount++] = $1;
}
| qname {
if (filter_opts.queues.qname) {
@@ -5316,15 +5322,15 @@ expand_rule(struct pfctl_rule *r,
sa_family_t af = r->af;
int added = 0, error = 0;
char ifname[IF_NAMESIZE];
- char label[PF_RULE_LABEL_SIZE];
+ char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
struct pf_pooladdr *pa;
struct node_host *h;
u_int8_t flags, flagset, keep_state;
- if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
- errx(1, "expand_rule: strlcpy");
+ memcpy(label, r->label, sizeof(r->label));
+ assert(sizeof(r->label) == sizeof(label));
if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
errx(1, "expand_rule: strlcpy");
if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
@@ -5373,17 +5379,17 @@ expand_rule(struct pfctl_rule *r,
else
memset(r->ifname, '\0', sizeof(r->ifname));
- if (strlcpy(r->label, label, sizeof(r->label)) >=
- sizeof(r->label))
- errx(1, "expand_rule: strlcpy");
+ memcpy(r->label, label, sizeof(r->label));
if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
sizeof(r->tagname))
errx(1, "expand_rule: strlcpy");
if (strlcpy(r->match_tagname, match_tagname,
sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
errx(1, "expand_rule: strlcpy");
- expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
- src_host, src_port, dst_host, dst_port, proto->proto);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ expand_label(r->label[i], PF_RULE_LABEL_SIZE,
+ r->ifname, r->af, src_host, src_port, dst_host,
+ dst_port, proto->proto);
expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
src_host, src_port, dst_host, dst_port, proto->proto);
expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
@@ -6273,13 +6279,16 @@ getservice(char *n)
}
int
-rule_label(struct pfctl_rule *r, char *s)
+rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
{
- if (s) {
- if (strlcpy(r->label, s, sizeof(r->label)) >=
- sizeof(r->label)) {
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ if (s[i] == NULL)
+ return (0);
+
+ if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
+ sizeof(r->label[0])) {
yyerror("rule label too long (max %d chars)",
- sizeof(r->label)-1);
+ sizeof(r->label[0])-1);
return (-1);
}
}
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 82af047e7571..af2ae6fe3bf0 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -996,11 +996,18 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
goto error;
switch (format) {
- case PFCTL_SHOW_LABELS:
- if (rule.label[0]) {
- printf("%s %llu %llu %llu %llu"
+ case PFCTL_SHOW_LABELS: {
+ bool show = false;
+ int i = 0;
+
+ while (rule.label[i][0]) {
+ printf("%s ", rule.label[i++]);
+ show = true;
+ }
+
+ if (show) {
+ printf("%llu %llu %llu %llu"
" %llu %llu %llu %ju\n",
- rule.label,
(unsigned long long)rule.evaluations,
(unsigned long long)(rule.packets[0] +
rule.packets[1]),
@@ -1013,6 +1020,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
(uintmax_t)rule.states_tot);
}
break;
+ }
case PFCTL_SHOW_RULES:
brace = 0;
if (rule.label[0] && (opts & PF_OPT_SHOWALL))
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 422e93460a43..282a0922bec7 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1019,8 +1019,9 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" fragment reassemble");
}
- if (r->label[0])
- printf(" label \"%s\"", r->label);
+ i = 0;
+ while (r->label[i][0])
+ printf(" label \"%s\"", r->label[i++]);
if (r->qname[0] && r->pqname[0])
printf(" queue(%s, %s)", r->qname, r->pqname);
else if (r->qname[0])