diff options
author | Kristof Provost <kp@FreeBSD.org> | 2021-04-20 09:04:48 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2021-04-26 12:14:21 +0000 |
commit | 6fcc8e042ac480f9276177339f7de1ad0f95c1b0 (patch) | |
tree | 07d745a169e7d2a50b230cf6ccf2f332796cc5f8 /sbin/pfctl | |
parent | cd17774d30c6cb70643c694ddf5a11f3c795dec8 (diff) | |
download | src-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.y | 59 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 16 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 5 |
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]) |