mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
pf: introduce ridentifier and labels to ether rules
Make Ethernet rules more similar to the usual layer 3 rules by also allowing ridentifier and labels to be set on them. Reviewed by: kp Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
0912408a28
commit
ef661d4a5b
|
@ -625,6 +625,9 @@ pfctl_eth_addr_to_nveth_addr(const struct pfctl_eth_addr *addr)
|
||||||
static void
|
static void
|
||||||
pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
|
pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
|
||||||
{
|
{
|
||||||
|
const char *const *labels;
|
||||||
|
size_t labelcount, i;
|
||||||
|
|
||||||
rule->nr = nvlist_get_number(nvl, "nr");
|
rule->nr = nvlist_get_number(nvl, "nr");
|
||||||
rule->quick = nvlist_get_bool(nvl, "quick");
|
rule->quick = nvlist_get_bool(nvl, "quick");
|
||||||
strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
|
strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
|
||||||
|
@ -636,6 +639,12 @@ pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
|
||||||
rule->match_tag = nvlist_get_number(nvl, "match_tag");
|
rule->match_tag = nvlist_get_number(nvl, "match_tag");
|
||||||
rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not");
|
rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not");
|
||||||
|
|
||||||
|
labels = nvlist_get_string_array(nvl, "labels", &labelcount);
|
||||||
|
assert(labelcount <= PF_RULE_MAX_LABEL_COUNT);
|
||||||
|
for (i = 0; i < labelcount; i++)
|
||||||
|
strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE);
|
||||||
|
rule->ridentifier = nvlist_get_number(nvl, "ridentifier");
|
||||||
|
|
||||||
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"),
|
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"),
|
||||||
&rule->src);
|
&rule->src);
|
||||||
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"),
|
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"),
|
||||||
|
@ -775,7 +784,7 @@ pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor,
|
||||||
nvlist_t *nvl, *addr;
|
nvlist_t *nvl, *addr;
|
||||||
void *packed;
|
void *packed;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
size_t size;
|
size_t labelcount, size;
|
||||||
|
|
||||||
nvl = nvlist_create(0);
|
nvl = nvlist_create(0);
|
||||||
|
|
||||||
|
@ -811,6 +820,15 @@ pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor,
|
||||||
pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc);
|
pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc);
|
||||||
pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst);
|
pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst);
|
||||||
|
|
||||||
|
labelcount = 0;
|
||||||
|
while (r->label[labelcount][0] != 0 &&
|
||||||
|
labelcount < PF_RULE_MAX_LABEL_COUNT) {
|
||||||
|
nvlist_append_string_array(nvl, "labels",
|
||||||
|
r->label[labelcount]);
|
||||||
|
labelcount++;
|
||||||
|
}
|
||||||
|
nvlist_add_number(nvl, "ridentifier", r->ridentifier);
|
||||||
|
|
||||||
nvlist_add_string(nvl, "qname", r->qname);
|
nvlist_add_string(nvl, "qname", r->qname);
|
||||||
nvlist_add_string(nvl, "tagname", r->tagname);
|
nvlist_add_string(nvl, "tagname", r->tagname);
|
||||||
nvlist_add_number(nvl, "dnpipe", r->dnpipe);
|
nvlist_add_number(nvl, "dnpipe", r->dnpipe);
|
||||||
|
|
|
@ -87,6 +87,9 @@ struct pfctl_eth_addr {
|
||||||
struct pfctl_eth_rule {
|
struct pfctl_eth_rule {
|
||||||
uint32_t nr;
|
uint32_t nr;
|
||||||
|
|
||||||
|
char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
|
||||||
|
uint32_t ridentifier;
|
||||||
|
|
||||||
bool quick;
|
bool quick;
|
||||||
|
|
||||||
/* Filter */
|
/* Filter */
|
||||||
|
|
|
@ -379,6 +379,7 @@ int expand_skip_interface(struct node_if *);
|
||||||
int check_rulestate(int);
|
int check_rulestate(int);
|
||||||
int getservice(char *);
|
int getservice(char *);
|
||||||
int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
|
int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
|
||||||
|
int eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
|
||||||
int rt_tableid_max(void);
|
int rt_tableid_max(void);
|
||||||
|
|
||||||
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
|
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
|
||||||
|
@ -1243,6 +1244,11 @@ etherrule : ETHER action dir quick interface bridge etherproto etherfromto l3fro
|
||||||
memcpy(&r.qname, $10.queues.qname, sizeof(r.qname));
|
memcpy(&r.qname, $10.queues.qname, sizeof(r.qname));
|
||||||
r.dnpipe = $10.dnpipe;
|
r.dnpipe = $10.dnpipe;
|
||||||
r.dnflags = $10.free_flags;
|
r.dnflags = $10.free_flags;
|
||||||
|
if (eth_rule_label(&r, $10.label))
|
||||||
|
YYERROR;
|
||||||
|
for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
|
||||||
|
free($10.label[i]);
|
||||||
|
r.ridentifier = $10.ridentifier;
|
||||||
|
|
||||||
expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
|
expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
|
||||||
$9.src.host, $9.dst.host, $6, "");
|
$9.src.host, $9.dst.host, $6, "");
|
||||||
|
@ -1366,6 +1372,16 @@ etherfilter_opt : etherqname {
|
||||||
}
|
}
|
||||||
filter_opts.queues = $1;
|
filter_opts.queues = $1;
|
||||||
}
|
}
|
||||||
|
| RIDENTIFIER number {
|
||||||
|
filter_opts.ridentifier = $2;
|
||||||
|
}
|
||||||
|
| label {
|
||||||
|
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[filter_opts.labelcount++] = $1;
|
||||||
|
}
|
||||||
| TAG string {
|
| TAG string {
|
||||||
filter_opts.tag = $2;
|
filter_opts.tag = $2;
|
||||||
}
|
}
|
||||||
|
@ -6945,6 +6961,23 @@ rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
|
||||||
|
{
|
||||||
|
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[0])-1);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
u_int16_t
|
u_int16_t
|
||||||
parseicmpspec(char *w, sa_family_t af)
|
parseicmpspec(char *w, sa_family_t af)
|
||||||
{
|
{
|
||||||
|
|
|
@ -755,6 +755,8 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
|
||||||
static const char *actiontypes[] = { "pass", "block", "", "", "", "",
|
static const char *actiontypes[] = { "pass", "block", "", "", "", "",
|
||||||
"", "", "", "", "", "", "match" };
|
"", "", "", "", "", "", "match" };
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
if (rule_numbers)
|
if (rule_numbers)
|
||||||
printf("@%u ", r->nr);
|
printf("@%u ", r->nr);
|
||||||
|
|
||||||
|
@ -797,6 +799,13 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
|
||||||
print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst,
|
print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst,
|
||||||
r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0,
|
r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0,
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (r->label[i][0])
|
||||||
|
printf(" label \"%s\"", r->label[i++]);
|
||||||
|
if (r->ridentifier)
|
||||||
|
printf(" ridentifier %u", r->ridentifier);
|
||||||
|
|
||||||
if (r->qname[0])
|
if (r->qname[0])
|
||||||
printf(" queue %s", r->qname);
|
printf(" queue %s", r->qname);
|
||||||
if (r->tagname[0])
|
if (r->tagname[0])
|
||||||
|
|
1
sbin/pfctl/tests/files/pf1013.in
Normal file
1
sbin/pfctl/tests/files/pf1013.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 ridentifier 12345678
|
1
sbin/pfctl/tests/files/pf1013.ok
Normal file
1
sbin/pfctl/tests/files/pf1013.ok
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 l3 all ridentifier 12345678
|
1
sbin/pfctl/tests/files/pf1014.in
Normal file
1
sbin/pfctl/tests/files/pf1014.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 label "test"
|
1
sbin/pfctl/tests/files/pf1014.ok
Normal file
1
sbin/pfctl/tests/files/pf1014.ok
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 l3 all label "test"
|
1
sbin/pfctl/tests/files/pf1015.in
Normal file
1
sbin/pfctl/tests/files/pf1015.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 label "test" label "another label"
|
1
sbin/pfctl/tests/files/pf1015.ok
Normal file
1
sbin/pfctl/tests/files/pf1015.ok
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 l3 all label "test" label "another label"
|
1
sbin/pfctl/tests/files/pf1016.in
Normal file
1
sbin/pfctl/tests/files/pf1016.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 label "test" ridentifier 12345678
|
1
sbin/pfctl/tests/files/pf1016.ok
Normal file
1
sbin/pfctl/tests/files/pf1016.ok
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 l3 all label "test" ridentifier 12345678
|
1
sbin/pfctl/tests/files/pf1017.in
Normal file
1
sbin/pfctl/tests/files/pf1017.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 label "test" label "another test" ridentifier 12345678
|
1
sbin/pfctl/tests/files/pf1017.ok
Normal file
1
sbin/pfctl/tests/files/pf1017.ok
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ether block out on igb0 l3 all label "test" label "another test" ridentifier 12345678
|
|
@ -123,3 +123,8 @@ PFCTL_TEST(1009, "Ethernet rule with mask")
|
||||||
PFCTL_TEST(1010, "POM_STICKYADDRESS test")
|
PFCTL_TEST(1010, "POM_STICKYADDRESS test")
|
||||||
PFCTL_TEST(1011, "Test disabling scrub fragment reassemble")
|
PFCTL_TEST(1011, "Test disabling scrub fragment reassemble")
|
||||||
PFCTL_TEST(1012, "Test scrub fragment reassemble is default")
|
PFCTL_TEST(1012, "Test scrub fragment reassemble is default")
|
||||||
|
PFCTL_TEST(1013, "Ethernet rule with ridentifier")
|
||||||
|
PFCTL_TEST(1014, "Ethernet rule with one label")
|
||||||
|
PFCTL_TEST(1015, "Ethernet rule with several labels")
|
||||||
|
PFCTL_TEST(1016, "Ethernet rule with ridentifier and one label")
|
||||||
|
PFCTL_TEST(1017, "Ethernet rule with ridentifier and several labels")
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd April 21, 2023
|
.Dd April 26, 2023
|
||||||
.Dt PF.CONF 5
|
.Dt PF.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -3108,7 +3108,8 @@ logopts = logopt [ "," logopts ]
|
||||||
logopt = "all" | "user" | "to" interface-name
|
logopt = "all" | "user" | "to" interface-name
|
||||||
|
|
||||||
etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
|
etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
|
||||||
etherfilteropt = "tag" string | "tagged" string | "queue" ( string )
|
etherfilteropt = "tag" string | "tagged" string | "queue" ( string ) |
|
||||||
|
"ridentifier" number | "label" string
|
||||||
|
|
||||||
filteropt-list = filteropt-list filteropt | filteropt
|
filteropt-list = filteropt-list filteropt | filteropt
|
||||||
filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos |
|
filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos |
|
||||||
|
|
|
@ -703,6 +703,9 @@ struct pf_keth_rule {
|
||||||
uint8_t action;
|
uint8_t action;
|
||||||
uint16_t dnpipe;
|
uint16_t dnpipe;
|
||||||
uint32_t dnflags;
|
uint32_t dnflags;
|
||||||
|
|
||||||
|
char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
|
||||||
|
uint32_t ridentifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
union pf_krule_ptr {
|
union pf_krule_ptr {
|
||||||
|
|
|
@ -1051,6 +1051,11 @@ pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
|
||||||
if (nvl == NULL)
|
if (nvl == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
|
||||||
|
nvlist_append_string_array(nvl, "labels", krule->label[i]);
|
||||||
|
}
|
||||||
|
nvlist_add_number(nvl, "ridentifier", krule->ridentifier);
|
||||||
|
|
||||||
nvlist_add_number(nvl, "nr", krule->nr);
|
nvlist_add_number(nvl, "nr", krule->nr);
|
||||||
nvlist_add_bool(nvl, "quick", krule->quick);
|
nvlist_add_bool(nvl, "quick", krule->quick);
|
||||||
nvlist_add_string(nvl, "ifname", krule->ifname);
|
nvlist_add_string(nvl, "ifname", krule->ifname);
|
||||||
|
@ -1126,8 +1131,29 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
|
||||||
|
|
||||||
bzero(krule, sizeof(*krule));
|
bzero(krule, sizeof(*krule));
|
||||||
|
|
||||||
|
if (nvlist_exists_string_array(nvl, "labels")) {
|
||||||
|
const char *const *strs;
|
||||||
|
size_t items;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
strs = nvlist_get_string_array(nvl, "labels", &items);
|
||||||
|
if (items > PF_RULE_MAX_LABEL_COUNT)
|
||||||
|
ERROUT(E2BIG);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < items; i++) {
|
||||||
|
ret = strlcpy(krule->label[i], strs[i],
|
||||||
|
sizeof(krule->label[0]));
|
||||||
|
if (ret >= sizeof(krule->label[0]))
|
||||||
|
ERROUT(E2BIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &krule->ridentifier, 0));
|
||||||
|
|
||||||
PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
|
PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
|
||||||
PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
|
PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
|
||||||
PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
|
PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
|
||||||
|
@ -1192,6 +1218,7 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
|
||||||
krule->action != PF_MATCH)
|
krule->action != PF_MATCH)
|
||||||
return (EBADMSG);
|
return (EBADMSG);
|
||||||
|
|
||||||
|
#undef ERROUT
|
||||||
errout:
|
errout:
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue