* [iptables PATCH 01/23] libxtables: xtoptions: Prevent XTOPT_PUT with XTTYPE_HOSTMASK
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT* Phil Sutter
` (22 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Do as the comment in xtopt_parse_hostmask() claims and omit
XTTYPE_HOSTMASK from xtopt_psize array so xtables_option_metavalidate()
will catch the incompatibility.
Fixes: 66266abd17adc ("libxtables: XTTYPE_HOSTMASK support")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
include/xtables.h | 1 -
libxtables/xtoptions.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/include/xtables.h b/include/xtables.h
index b3c45c981b1c7..db7c492a9556e 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -61,7 +61,6 @@ struct in_addr;
* %XTTYPE_SYSLOGLEVEL: syslog level by name or number
* %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr)
* %XTTYPE_HOSTMASK: one host or address, with an optional prefix length
- * (ptr: union nf_inet_addr; only host portion is stored)
* %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t)
* %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO)
* %XTTYPE_PORTRC: colon-separated port range (names acceptable),
diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c
index 5964a9bfb57fe..9694639188006 100644
--- a/libxtables/xtoptions.c
+++ b/libxtables/xtoptions.c
@@ -57,7 +57,6 @@ static const size_t xtopt_psize[] = {
[XTTYPE_STRING] = -1,
[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
[XTTYPE_HOST] = sizeof(union nf_inet_addr),
- [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr),
[XTTYPE_PROTOCOL] = sizeof(uint8_t),
[XTTYPE_PORT] = sizeof(uint16_t),
[XTTYPE_PORTRC] = sizeof(uint16_t[2]),
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT*
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 01/23] libxtables: xtoptions: Prevent XTOPT_PUT with XTTYPE_HOSTMASK Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 19:07 ` Jan Engelhardt
2023-12-20 16:06 ` [iptables PATCH 03/23] libxtables: xtoptions: Implement XTTYPE_ETHERMACMASK Phil Sutter
` (21 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Value conversion into Big Endian byteorder is pretty straightforward,
merely needed a small helper for uint64.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
libxtables/xtoptions.c | 40 +++++++++++++++++++++++++++++++---------
1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c
index 9694639188006..3973c807ded0e 100644
--- a/libxtables/xtoptions.c
+++ b/libxtables/xtoptions.c
@@ -147,6 +147,14 @@ static size_t xtopt_esize_by_type(enum xt_option_type type)
}
}
+static uint64_t htonll(uint64_t val)
+{
+ uint32_t high = val >> 32;
+ uint32_t low = val & UINT32_MAX;
+
+ return (uint64_t)htonl(low) << 32 | htonl(high);
+}
+
/**
* Require a simple integer.
*/
@@ -174,14 +182,20 @@ static void xtopt_parse_int(struct xt_option_call *cb)
*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
} else if (entry->type == XTTYPE_UINT16) {
cb->val.u16 = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u16 = htons(cb->val.u16);
if (entry->flags & XTOPT_PUT)
*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16;
} else if (entry->type == XTTYPE_UINT32) {
cb->val.u32 = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u32 = htonl(cb->val.u32);
if (entry->flags & XTOPT_PUT)
*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
} else if (entry->type == XTTYPE_UINT64) {
cb->val.u64 = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u64 = htonll(cb->val.u64);
if (entry->flags & XTOPT_PUT)
*(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
}
@@ -216,17 +230,25 @@ static void xtopt_parse_float(struct xt_option_call *cb)
static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value)
{
const struct xt_option_entry *entry = cb->entry;
+ int i = cb->nvals;
- if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range))
+ if (i >= ARRAY_SIZE(cb->val.u32_range))
return;
- if (entry->type == XTTYPE_UINT8RC)
- cb->val.u8_range[cb->nvals] = value;
- else if (entry->type == XTTYPE_UINT16RC)
- cb->val.u16_range[cb->nvals] = value;
- else if (entry->type == XTTYPE_UINT32RC)
- cb->val.u32_range[cb->nvals] = value;
- else if (entry->type == XTTYPE_UINT64RC)
- cb->val.u64_range[cb->nvals] = value;
+ if (entry->type == XTTYPE_UINT8RC) {
+ cb->val.u8_range[i] = value;
+ } else if (entry->type == XTTYPE_UINT16RC) {
+ cb->val.u16_range[i] = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u16_range[i] = htons(cb->val.u16_range[i]);
+ } else if (entry->type == XTTYPE_UINT32RC) {
+ cb->val.u32_range[i] = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u32_range[i] = htonl(cb->val.u32_range[i]);
+ } else if (entry->type == XTTYPE_UINT64RC) {
+ cb->val.u64_range[i] = value;
+ if (entry->flags & XTOPT_NBO)
+ cb->val.u64_range[i] = htonll(cb->val.u64_range[i]);
+ }
}
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT*
2023-12-20 16:06 ` [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT* Phil Sutter
@ 2023-12-20 19:07 ` Jan Engelhardt
2023-12-20 21:28 ` Phil Sutter
0 siblings, 1 reply; 31+ messages in thread
From: Jan Engelhardt @ 2023-12-20 19:07 UTC (permalink / raw)
To: Phil Sutter; +Cc: netfilter-devel
On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
> {
> const struct xt_option_entry *entry = cb->entry;
>+ int i = cb->nvals;
>
>- if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range))
>+ if (i >= ARRAY_SIZE(cb->val.u32_range))
> return;
`i` should be unsigned (size_t) because ARRAY_SIZE is,
else you get -Wsigned warnings at some point.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT*
2023-12-20 19:07 ` Jan Engelhardt
@ 2023-12-20 21:28 ` Phil Sutter
0 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 21:28 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
On Wed, Dec 20, 2023 at 08:07:41PM +0100, Jan Engelhardt wrote:
>
> On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
> > {
> > const struct xt_option_entry *entry = cb->entry;
> >+ int i = cb->nvals;
> >
> >- if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range))
> >+ if (i >= ARRAY_SIZE(cb->val.u32_range))
> > return;
>
> `i` should be unsigned (size_t) because ARRAY_SIZE is,
> else you get -Wsigned warnings at some point.
Oh, right! I'll make it uint8_t to match typeof(cb->nvals).
Thanks, Phil
^ permalink raw reply [flat|nested] 31+ messages in thread
* [iptables PATCH 03/23] libxtables: xtoptions: Implement XTTYPE_ETHERMACMASK
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 01/23] libxtables: xtoptions: Prevent XTOPT_PUT with XTTYPE_HOSTMASK Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 02/23] libxtables: xtoptions: Support XTOPT_NBO with XTTYPE_UINT* Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4 Phil Sutter
` (20 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Accept an Ethernet MAC address with optional mask in the format
xtables_parse_mac_and_mask() expects it. Does not support XTOPT_PUT (for
now) due to the lack of defined data structure.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
include/xtables.h | 7 ++++++-
libxtables/xtoptions.c | 10 ++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/xtables.h b/include/xtables.h
index db7c492a9556e..ab856ebc426ac 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -12,6 +12,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/types.h>
@@ -68,6 +69,7 @@ struct in_addr;
* %XTTYPE_PLEN: prefix length
* %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr)
* %XTTYPE_ETHERMAC: Ethernet MAC address in hex form
+ * %XTTYPE_ETHERMACMASK: Ethernet MAC address in hex form with optional mask
*/
enum xt_option_type {
XTTYPE_NONE,
@@ -92,6 +94,7 @@ enum xt_option_type {
XTTYPE_PLEN,
XTTYPE_PLENMASK,
XTTYPE_ETHERMAC,
+ XTTYPE_ETHERMACMASK,
};
/**
@@ -167,7 +170,9 @@ struct xt_option_call {
struct {
uint32_t mark, mask;
};
- uint8_t ethermac[6];
+ struct {
+ uint8_t ethermac[ETH_ALEN], ethermacmask[ETH_ALEN];
+ };
} val;
/* Wished for a world where the ones below were gone: */
union {
diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c
index 3973c807ded0e..9377e1641f28c 100644
--- a/libxtables/xtoptions.c
+++ b/libxtables/xtoptions.c
@@ -791,6 +791,15 @@ static void xtopt_parse_ethermac(struct xt_option_call *cb)
xt_params->exit_err(PARAMETER_PROBLEM, "Invalid MAC address specified.");
}
+static void xtopt_parse_ethermacmask(struct xt_option_call *cb)
+{
+ memset(cb->val.ethermacmask, 0xff, ETH_ALEN);
+ if (xtables_parse_mac_and_mask(cb->arg, cb->val.ethermac,
+ cb->val.ethermacmask))
+ xt_params->exit_err(PARAMETER_PROBLEM,
+ "Invalid MAC/mask address specified.");
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
[XTTYPE_UINT16] = xtopt_parse_int,
@@ -813,6 +822,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_PLEN] = xtopt_parse_plen,
[XTTYPE_PLENMASK] = xtopt_parse_plenmask,
[XTTYPE_ETHERMAC] = xtopt_parse_ethermac,
+ [XTTYPE_ETHERMACMASK]= xtopt_parse_ethermacmask,
};
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (2 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 03/23] libxtables: xtoptions: Implement XTTYPE_ETHERMACMASK Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 19:20 ` Jan Engelhardt
2023-12-20 16:06 ` [iptables PATCH 05/23] ebtables: Support for guided option parser Phil Sutter
` (19 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
When parsing for XTTYPE_HOST(MASK), the return value of afinfo_family()
is used to indicate the expected address family.
Make guided option parser expect IPv4 by default for ebtables as this is
the more common case. The exception is libebt_ip6, which will
temporarily adjust afinfo->family while parsing.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
libxtables/xtoptions.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c
index 9377e1641f28c..5b693a9b00e3f 100644
--- a/libxtables/xtoptions.c
+++ b/libxtables/xtoptions.c
@@ -71,6 +71,7 @@ static uint8_t afinfo_family(void)
{
switch (afinfo->family) {
case NFPROTO_ARP:
+ case NFPROTO_BRIDGE:
return NFPROTO_IPV4;
default:
return afinfo->family;
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4
2023-12-20 16:06 ` [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4 Phil Sutter
@ 2023-12-20 19:20 ` Jan Engelhardt
2023-12-20 21:35 ` Phil Sutter
0 siblings, 1 reply; 31+ messages in thread
From: Jan Engelhardt @ 2023-12-20 19:20 UTC (permalink / raw)
To: Phil Sutter; +Cc: netfilter-devel
On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
>When parsing for XTTYPE_HOST(MASK), the return value of afinfo_family()
>is used to indicate the expected address family.
>
>Make guided option parser expect IPv4 by default for ebtables as this is
>the more common case.
ebtables is about Ethernet addresses mostly,
and ebt_ip6 and ebt_ip have the same priority really.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4
2023-12-20 19:20 ` Jan Engelhardt
@ 2023-12-20 21:35 ` Phil Sutter
0 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 21:35 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
On Wed, Dec 20, 2023 at 08:20:10PM +0100, Jan Engelhardt wrote:
>
> On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
>
> >When parsing for XTTYPE_HOST(MASK), the return value of afinfo_family()
> >is used to indicate the expected address family.
> >
> >Make guided option parser expect IPv4 by default for ebtables as this is
> >the more common case.
>
> ebtables is about Ethernet addresses mostly,
> and ebt_ip6 and ebt_ip have the same priority really.
That's right, but there's also libebt_arp which expects IPv4 address
in --arp-ip-src and --arp-ip-dst options.
I was a bit undecided about this solution because libebt_ip6's
workaround is fugly:
| xtables_set_nfproto(NFPROTO_IPV6);
| xtables_option_parse(cb);
| xtables_set_nfproto(NFPROTO_BRIDGE);
OTOH introducing XTTYPE_HOST{,MASK}{4,6} to force the expected address
family despite afinfo->family value seemed over-engineering given the
single user I had to cover after treating NFPROTO_BRIDGE as IPv4 by
default.
Cheers, Phil
^ permalink raw reply [flat|nested] 31+ messages in thread
* [iptables PATCH 05/23] ebtables: Support for guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (3 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 04/23] libxtables: xtoptions: Treat NFPROTO_BRIDGE as IPv4 Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 06/23] extensions: libebt_*: Drop some needless init callbacks Phil Sutter
` (18 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Adjust ebt_load_match() and ebt_command_default() to expect
x6_options/x6_parse fiels to be set instead of the traditional ones.
Much of this is c'n'p from command_default() in xshared.c, but due to
ebtables' custom match data structure (combining matches and watchers),
sharing the code is probably not feasible.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
iptables/xtables-eb.c | 108 ++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 57 deletions(-)
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index c3cf1c2c74104..e8cdd7eaa8e44 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -170,36 +170,6 @@ static void ebt_list_extensions(const struct xtables_target *t,
}*/
}
-#define OPTION_OFFSET 256
-static struct option *merge_options(struct option *oldopts,
- const struct option *newopts,
- unsigned int *options_offset)
-{
- unsigned int num_old, num_new, i;
- struct option *merge;
-
- if (!newopts || !oldopts || !options_offset)
- return oldopts;
- for (num_old = 0; oldopts[num_old].name; num_old++);
- for (num_new = 0; newopts[num_new].name; num_new++);
-
- ebtables_globals.option_offset += OPTION_OFFSET;
- *options_offset = ebtables_globals.option_offset;
-
- merge = xtables_malloc(sizeof(struct option) * (num_new + num_old + 1));
- memcpy(merge, oldopts, num_old * sizeof(struct option));
- for (i = 0; i < num_new; i++) {
- merge[num_old + i] = newopts[i];
- merge[num_old + i].val += *options_offset;
- }
- memset(merge + num_old + num_new, 0, sizeof(struct option));
- /* Only free dynamically allocated stuff */
- if (oldopts != ebt_original_options)
- free(oldopts);
-
- return merge;
-}
-
void nft_bridge_print_help(struct iptables_command_state *cs)
{
const struct xtables_rule_match *m = cs->matches;
@@ -327,7 +297,12 @@ static void ebt_load_match(const char *name)
m->m->u.user.revision = m->revision;
xs_init_match(m);
- opts = merge_options(opts, m->extra_opts, &m->option_offset);
+ if (m->x6_options != NULL)
+ opts = xtables_options_xfrm(opts, NULL,
+ m->x6_options, &m->option_offset);
+ else if (m->extra_opts != NULL)
+ opts = xtables_merge_options(opts, NULL,
+ m->extra_opts, &m->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "Can't alloc memory");
}
@@ -354,8 +329,12 @@ static void ebt_load_watcher(const char *name)
xs_init_target(watcher);
- opts = merge_options(opts, watcher->extra_opts,
- &watcher->option_offset);
+ if (watcher->x6_options != NULL)
+ opts = xtables_options_xfrm(opts, NULL, watcher->x6_options,
+ &watcher->option_offset);
+ else if (watcher->extra_opts != NULL)
+ opts = xtables_merge_options(opts, NULL, watcher->extra_opts,
+ &watcher->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "Can't alloc memory");
}
@@ -450,37 +429,50 @@ int ebt_command_default(struct iptables_command_state *cs,
struct ebt_match *matchp;
/* Is it a target option? */
- if (t && t->parse) {
- if (t->parse(cs->c - t->option_offset, cs->argv,
- ebt_invert, &t->tflags, NULL, &t->t))
- return 0;
+ if (cs->target != NULL &&
+ (cs->target->parse != NULL || cs->target->x6_parse != NULL) &&
+ cs->c >= cs->target->option_offset &&
+ cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) {
+ xtables_option_tpcall(cs->c, cs->argv, ebt_invert,
+ cs->target, &cs->eb);
+ return 0;
}
/* check previously added matches/watchers to this rule first */
for (matchp = cs->match_list; matchp; matchp = matchp->next) {
if (matchp->ismatch) {
m = matchp->u.match;
- if (m->parse &&
- m->parse(cs->c - m->option_offset, cs->argv,
- ebt_invert, &m->mflags, NULL, &m->m))
- return 0;
+ if (!m->parse && !m->x6_parse)
+ continue;
+ if (cs->c < m->option_offset ||
+ cs->c >= m->option_offset + XT_OPTION_OFFSET_SCALE)
+ continue;
+ xtables_option_mpcall(cs->c, cs->argv, ebt_invert,
+ m, &cs->eb);
+ return 0;
} else {
t = matchp->u.watcher;
- if (t->parse &&
- t->parse(cs->c - t->option_offset, cs->argv,
- ebt_invert, &t->tflags, NULL, &t->t))
- return 0;
+ if (!t->parse && !t->x6_parse)
+ continue;
+ if (cs->c < t->option_offset ||
+ cs->c >= t->option_offset + XT_OPTION_OFFSET_SCALE)
+ continue;
+ xtables_option_tpcall(cs->c, cs->argv, ebt_invert,
+ t, &cs->eb);
+ return 0;
}
}
/* Is it a match_option? */
for (m = xtables_matches; m; m = m->next) {
- if (m->parse &&
- m->parse(cs->c - m->option_offset, cs->argv,
- ebt_invert, &m->mflags, NULL, &m->m)) {
- ebt_add_match(m, cs);
- return 0;
- }
+ if (!m->parse && !m->x6_parse)
+ continue;
+ if (cs->c < m->option_offset ||
+ cs->c >= m->option_offset + XT_OPTION_OFFSET_SCALE)
+ continue;
+ xtables_option_mpcall(cs->c, cs->argv, ebt_invert, m, &cs->eb);
+ ebt_add_match(m, cs);
+ return 0;
}
/* Is it a watcher option? */
@@ -488,12 +480,14 @@ int ebt_command_default(struct iptables_command_state *cs,
if (!(t->ext_flags & XTABLES_EXT_WATCHER))
continue;
- if (t->parse &&
- t->parse(cs->c - t->option_offset, cs->argv,
- ebt_invert, &t->tflags, NULL, &t->t)) {
- ebt_add_watcher(t, cs);
- return 0;
- }
+ if (!t->parse && !t->x6_parse)
+ continue;
+ if (cs->c < t->option_offset ||
+ cs->c >= t->option_offset + XT_OPTION_OFFSET_SCALE)
+ continue;
+ xtables_option_tpcall(cs->c, cs->argv, ebt_invert, t, &cs->eb);
+ ebt_add_watcher(t, cs);
+ return 0;
}
if (cs->c == ':')
xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 06/23] extensions: libebt_*: Drop some needless init callbacks
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (4 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 05/23] ebtables: Support for guided option parser Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser Phil Sutter
` (17 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Extension data is zero by default.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_802_3.c | 9 ---------
extensions/libebt_ip.c | 9 ---------
extensions/libebt_ip6.c | 13 -------------
extensions/libebt_mark_m.c | 11 -----------
4 files changed, 42 deletions(-)
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
index f05d02ead5a4a..8cbcdcea4912f 100644
--- a/extensions/libebt_802_3.c
+++ b/extensions/libebt_802_3.c
@@ -36,14 +36,6 @@ static void br802_3_print_help(void)
" Type implies SAP value 0xaa\n");
}
-static void br802_3_init(struct xt_entry_match *match)
-{
- struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
-
- info->invflags = 0;
- info->bitmask = 0;
-}
-
static int
br802_3_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
@@ -119,7 +111,6 @@ static struct xtables_match br802_3_match =
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_802_3_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
- .init = br802_3_init,
.help = br802_3_print_help,
.parse = br802_3_parse,
.final_check = br802_3_final_check,
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 68f34bff97deb..97ec4160942da 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -69,14 +69,6 @@ static void brip_print_help(void)
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
}
-static void brip_init(struct xt_entry_match *match)
-{
- struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
-
- info->invflags = 0;
- info->bitmask = 0;
-}
-
static void
parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
{
@@ -503,7 +495,6 @@ static struct xtables_match brip_match = {
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
- .init = brip_init,
.help = brip_print_help,
.parse = brip_parse,
.final_check = brip_final_check,
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index 18bb2720ccbec..d926e86a585f4 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -127,18 +127,6 @@ static void brip6_print_help(void)
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
}
-static void brip6_init(struct xt_entry_match *match)
-{
- struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
-
- ipinfo->invflags = 0;
- ipinfo->bitmask = 0;
- memset(ipinfo->saddr.s6_addr, 0, sizeof(ipinfo->saddr.s6_addr));
- memset(ipinfo->smsk.s6_addr, 0, sizeof(ipinfo->smsk.s6_addr));
- memset(ipinfo->daddr.s6_addr, 0, sizeof(ipinfo->daddr.s6_addr));
- memset(ipinfo->dmsk.s6_addr, 0, sizeof(ipinfo->dmsk.s6_addr));
-}
-
/* wrap xtables_ip6parse_any(), ignoring any but the first returned address */
static void ebt_parse_ip6_address(char *address,
struct in6_addr *addr, struct in6_addr *msk)
@@ -452,7 +440,6 @@ static struct xtables_match brip6_match = {
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
- .init = brip6_init,
.help = brip6_print_help,
.parse = brip6_parse,
.final_check = brip6_final_check,
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index 2462d0af7d0bc..178c9ecef94da 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -30,16 +30,6 @@ static void brmark_m_print_help(void)
"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
}
-static void brmark_m_init(struct xt_entry_match *match)
-{
- struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
-
- info->mark = 0;
- info->mask = 0;
- info->invert = 0;
- info->bitmask = 0;
-}
-
#define OPT_MARK 0x01
static int
brmark_m_parse(int c, char **argv, int invert, unsigned int *flags,
@@ -128,7 +118,6 @@ static struct xtables_match brmark_m_match = {
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
- .init = brmark_m_init,
.help = brmark_m_print_help,
.parse = brmark_m_parse,
.final_check = brmark_m_final_check,
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (5 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 06/23] extensions: libebt_*: Drop some needless init callbacks Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 19:29 ` Jan Engelhardt
2023-12-20 16:06 ` [iptables PATCH 08/23] extensions: libebt_arpreply: " Phil Sutter
` (16 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_stp.c | 244 ++++++++++++++--------------------------
extensions/libebt_stp.t | 16 +++
2 files changed, 100 insertions(+), 160 deletions(-)
diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c
index 41059baae7078..9b372d1d4351a 100644
--- a/extensions/libebt_stp.c
+++ b/extensions/libebt_stp.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <linux/netfilter_bridge/ebt_stp.h>
#include <xtables.h>
@@ -17,35 +16,37 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define STP_TYPE 'a'
-#define STP_FLAGS 'b'
-#define STP_ROOTPRIO 'c'
-#define STP_ROOTADDR 'd'
-#define STP_ROOTCOST 'e'
-#define STP_SENDERPRIO 'f'
-#define STP_SENDERADDR 'g'
-#define STP_PORT 'h'
-#define STP_MSGAGE 'i'
-#define STP_MAXAGE 'j'
-#define STP_HELLOTIME 'k'
-#define STP_FWDD 'l'
-#define STP_NUMOPS 12
+/* These must correspond to the bit position in EBT_STP_* defines */
+enum {
+ O_TYPE = 0,
+ O_FLAGS,
+ O_RPRIO,
+ O_RADDR,
+ O_RCOST,
+ O_SPRIO,
+ O_SADDR,
+ O_PORT,
+ O_MSGAGE,
+ O_MAXAGE,
+ O_HTIME,
+ O_FWDD,
+};
-static const struct option brstp_opts[] =
-{
- { "stp-type" , required_argument, 0, STP_TYPE},
- { "stp-flags" , required_argument, 0, STP_FLAGS},
- { "stp-root-prio" , required_argument, 0, STP_ROOTPRIO},
- { "stp-root-addr" , required_argument, 0, STP_ROOTADDR},
- { "stp-root-cost" , required_argument, 0, STP_ROOTCOST},
- { "stp-sender-prio" , required_argument, 0, STP_SENDERPRIO},
- { "stp-sender-addr" , required_argument, 0, STP_SENDERADDR},
- { "stp-port" , required_argument, 0, STP_PORT},
- { "stp-msg-age" , required_argument, 0, STP_MSGAGE},
- { "stp-max-age" , required_argument, 0, STP_MAXAGE},
- { "stp-hello-time" , required_argument, 0, STP_HELLOTIME},
- { "stp-forward-delay", required_argument, 0, STP_FWDD},
- { 0 }
+static const struct xt_option_entry brstp_opts[] = {
+#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
+ ENTRY("stp-type", O_TYPE, XTTYPE_STRING),
+ ENTRY("stp-flags", O_FLAGS, XTTYPE_STRING),
+ ENTRY("stp-root-prio", O_RPRIO, XTTYPE_UINT16RC),
+ ENTRY("stp-root-addr", O_RADDR, XTTYPE_ETHERMACMASK),
+ ENTRY("stp-root-cost", O_RCOST, XTTYPE_UINT32RC),
+ ENTRY("stp-sender-prio", O_SPRIO, XTTYPE_UINT16RC),
+ ENTRY("stp-sender-addr", O_SADDR, XTTYPE_ETHERMACMASK),
+ ENTRY("stp-port", O_PORT, XTTYPE_UINT16RC),
+ ENTRY("stp-msg-age", O_MSGAGE, XTTYPE_UINT16RC),
+ ENTRY("stp-max-age", O_MAXAGE, XTTYPE_UINT16RC),
+ ENTRY("stp-hello-time", O_HTIME, XTTYPE_UINT16RC),
+ ENTRY("stp-forward-delay", O_FWDD, XTTYPE_UINT16RC),
+ XTOPT_TABLEEND,
};
#define BPDU_TYPE_CONFIG 0
@@ -82,67 +83,6 @@ static void brstp_print_help(void)
" \"topology-change-ack\": topology change acknowledgement flag (0x80)");
}
-static int parse_range(const char *portstring, void *lower, void *upper,
- int bits, uint32_t min, uint32_t max)
-{
- char *buffer;
- char *cp, *end;
- uint32_t low_nr, upp_nr;
- int ret = 0;
-
- buffer = xtables_strdup(portstring);
-
- if ((cp = strchr(buffer, ':')) == NULL) {
- low_nr = strtoul(buffer, &end, 10);
- if (*end || low_nr < min || low_nr > max) {
- ret = -1;
- goto out;
- }
- if (bits == 2) {
- *(uint16_t *)lower = low_nr;
- *(uint16_t *)upper = low_nr;
- } else {
- *(uint32_t *)lower = low_nr;
- *(uint32_t *)upper = low_nr;
- }
- } else {
- *cp = '\0';
- cp++;
- if (!*buffer)
- low_nr = min;
- else {
- low_nr = strtoul(buffer, &end, 10);
- if (*end || low_nr < min) {
- ret = -1;
- goto out;
- }
- }
- if (!*cp)
- upp_nr = max;
- else {
- upp_nr = strtoul(cp, &end, 10);
- if (*end || upp_nr > max) {
- ret = -1;
- goto out;
- }
- }
- if (upp_nr < low_nr) {
- ret = -1;
- goto out;
- }
- if (bits == 2) {
- *(uint16_t *)lower = low_nr;
- *(uint16_t *)upper = upp_nr;
- } else {
- *(uint32_t *)lower = low_nr;
- *(uint32_t *)upper = upp_nr;
- }
- }
-out:
- free(buffer);
- return ret;
-}
-
static void print_range(unsigned int l, unsigned int u)
{
if (l == u)
@@ -151,103 +91,87 @@ static void print_range(unsigned int l, unsigned int u)
printf("%u:%u", l, u);
}
-static int
-brstp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brstp_parse(struct xt_option_call *cb)
{
- struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)(*match)->data;
- unsigned int flag;
- long int i;
+ struct ebt_stp_info *stpinfo = cb->data;
char *end = NULL;
+ long int i;
+
+ xtables_option_parse(cb);
- if (c < 'a' || c > ('a' + STP_NUMOPS - 1))
- return 0;
- flag = 1 << (c - 'a');
- EBT_CHECK_OPTION(flags, flag);
- if (invert)
- stpinfo->invflags |= flag;
- stpinfo->bitmask |= flag;
- switch (flag) {
- case EBT_STP_TYPE:
- i = strtol(optarg, &end, 0);
+ stpinfo->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ stpinfo->invflags |= 1 << cb->entry->id;
+
+ switch (cb->entry->id) {
+ case O_TYPE:
+ i = strtol(cb->arg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
- if (!strcasecmp(optarg, BPDU_TYPE_CONFIG_STRING))
+ if (!strcasecmp(cb->arg, BPDU_TYPE_CONFIG_STRING))
stpinfo->type = BPDU_TYPE_CONFIG;
- else if (!strcasecmp(optarg, BPDU_TYPE_TCN_STRING))
+ else if (!strcasecmp(cb->arg, BPDU_TYPE_TCN_STRING))
stpinfo->type = BPDU_TYPE_TCN;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-type argument");
} else
stpinfo->type = i;
break;
- case EBT_STP_FLAGS:
- i = strtol(optarg, &end, 0);
+ case O_FLAGS:
+ i = strtol(cb->arg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
- if (!strcasecmp(optarg, FLAG_TC_STRING))
+ if (!strcasecmp(cb->arg, FLAG_TC_STRING))
stpinfo->config.flags = FLAG_TC;
- else if (!strcasecmp(optarg, FLAG_TC_ACK_STRING))
+ else if (!strcasecmp(cb->arg, FLAG_TC_ACK_STRING))
stpinfo->config.flags = FLAG_TC_ACK;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-flags argument");
} else
stpinfo->config.flags = i;
break;
- case EBT_STP_ROOTPRIO:
- if (parse_range(argv[optind-1], &(stpinfo->config.root_priol),
- &(stpinfo->config.root_priou), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-prio range");
+ case O_RADDR:
+ memcpy(stpinfo->config.root_addr, cb->val.ethermac, ETH_ALEN);
+ memcpy(stpinfo->config.root_addrmsk,
+ cb->val.ethermacmask, ETH_ALEN);
break;
- case EBT_STP_ROOTCOST:
- if (parse_range(argv[optind-1], &(stpinfo->config.root_costl),
- &(stpinfo->config.root_costu), 4, 0, 0xffffffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-cost range");
+ case O_SADDR:
+ memcpy(stpinfo->config.sender_addr, cb->val.ethermac, ETH_ALEN);
+ memcpy(stpinfo->config.sender_addrmsk,
+ cb->val.ethermacmask, ETH_ALEN);
break;
- case EBT_STP_SENDERPRIO:
- if (parse_range(argv[optind-1], &(stpinfo->config.sender_priol),
- &(stpinfo->config.sender_priou), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-prio range");
+
+#define RANGE_ASSIGN(name, fname, val) { \
+ stpinfo->config.fname##l = val[0]; \
+ stpinfo->config.fname##u = cb->nvals > 1 ? val[1] : val[0]; \
+ if (val[1] < val[0]) \
+ xtables_error(PARAMETER_PROBLEM, \
+ "Bad --stp-" name " range"); \
+}
+ case O_RPRIO:
+ RANGE_ASSIGN("root-prio", root_prio, cb->val.u16_range);
break;
- case EBT_STP_PORT:
- if (parse_range(argv[optind-1], &(stpinfo->config.portl),
- &(stpinfo->config.portu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-port-range");
+ case O_RCOST:
+ RANGE_ASSIGN("root-cost", root_cost, cb->val.u32_range);
break;
- case EBT_STP_MSGAGE:
- if (parse_range(argv[optind-1], &(stpinfo->config.msg_agel),
- &(stpinfo->config.msg_ageu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-msg-age range");
+ case O_SPRIO:
+ RANGE_ASSIGN("sender-prio", sender_prio, cb->val.u16_range);
break;
- case EBT_STP_MAXAGE:
- if (parse_range(argv[optind-1], &(stpinfo->config.max_agel),
- &(stpinfo->config.max_ageu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-max-age range");
+ case O_PORT:
+ RANGE_ASSIGN("port", port, cb->val.u16_range);
break;
- case EBT_STP_HELLOTIME:
- if (parse_range(argv[optind-1], &(stpinfo->config.hello_timel),
- &(stpinfo->config.hello_timeu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-hello-time range");
+ case O_MSGAGE:
+ RANGE_ASSIGN("msg-age", msg_age, cb->val.u16_range);
break;
- case EBT_STP_FWDD:
- if (parse_range(argv[optind-1], &(stpinfo->config.forward_delayl),
- &(stpinfo->config.forward_delayu), 2, 0, 0xffff))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-forward-delay range");
+ case O_MAXAGE:
+ RANGE_ASSIGN("max-age", max_age, cb->val.u16_range);
break;
- case EBT_STP_ROOTADDR:
- if (xtables_parse_mac_and_mask(argv[optind-1],
- stpinfo->config.root_addr,
- stpinfo->config.root_addrmsk))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-addr address");
+ case O_HTIME:
+ RANGE_ASSIGN("hello-time", hello_time, cb->val.u16_range);
break;
- case EBT_STP_SENDERADDR:
- if (xtables_parse_mac_and_mask(argv[optind-1],
- stpinfo->config.sender_addr,
- stpinfo->config.sender_addrmsk))
- xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-addr address");
+ case O_FWDD:
+ RANGE_ASSIGN("forward-delay", forward_delay, cb->val.u16_range);
break;
- default:
- xtables_error(PARAMETER_PROBLEM, "Unknown stp option");
+#undef RANGE_ASSIGN
}
- return 1;
}
static void brstp_print(const void *ip, const struct xt_entry_match *match,
@@ -257,7 +181,7 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match,
const struct ebt_stp_config_info *c = &(stpinfo->config);
int i;
- for (i = 0; i < STP_NUMOPS; i++) {
+ for (i = 0; (1 << i) < EBT_STP_MASK; i++) {
if (!(stpinfo->bitmask & (1 << i)))
continue;
printf("--%s %s", brstp_opts[i].name,
@@ -308,9 +232,9 @@ static struct xtables_match brstp_match = {
.family = NFPROTO_BRIDGE,
.size = sizeof(struct ebt_stp_info),
.help = brstp_print_help,
- .parse = brstp_parse,
+ .x6_parse = brstp_parse,
.print = brstp_print,
- .extra_opts = brstp_opts,
+ .x6_options = brstp_opts
};
void _init(void)
diff --git a/extensions/libebt_stp.t b/extensions/libebt_stp.t
index 17d6c1c0978e3..b3c7e5f3aa8f3 100644
--- a/extensions/libebt_stp.t
+++ b/extensions/libebt_stp.t
@@ -1,13 +1,29 @@
:INPUT,FORWARD,OUTPUT
--stp-type 1;=;OK
+--stp-type ! 1;=;OK
--stp-flags 0x1;--stp-flags topology-change -j CONTINUE;OK
+--stp-flags ! topology-change;=;OK
--stp-root-prio 1 -j ACCEPT;=;OK
+--stp-root-prio ! 1 -j ACCEPT;=;OK
--stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
+--stp-root-addr ! 0d:ea:d0:0b:ee:f0;=;OK
+--stp-root-addr 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
+--stp-root-addr ! 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
--stp-root-cost 1;=;OK
+--stp-root-cost ! 1;=;OK
--stp-sender-prio 1;=;OK
+--stp-sender-prio ! 1;=;OK
--stp-sender-addr de:ad:be:ef:00:00;=;OK
+--stp-sender-addr ! de:ad:be:ef:00:00;=;OK
+--stp-sender-addr de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
+--stp-sender-addr ! de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
--stp-port 1;=;OK
+--stp-port ! 1;=;OK
--stp-msg-age 1;=;OK
+--stp-msg-age ! 1;=;OK
--stp-max-age 1;=;OK
+--stp-max-age ! 1;=;OK
--stp-hello-time 1;=;OK
+--stp-hello-time ! 1;=;OK
--stp-forward-delay 1;=;OK
+--stp-forward-delay ! 1;=;OK
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser
2023-12-20 16:06 ` [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser Phil Sutter
@ 2023-12-20 19:29 ` Jan Engelhardt
2023-12-20 21:47 ` Phil Sutter
0 siblings, 1 reply; 31+ messages in thread
From: Jan Engelhardt @ 2023-12-20 19:29 UTC (permalink / raw)
To: Phil Sutter; +Cc: netfilter-devel
On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
>index 17d6c1c0978e3..b3c7e5f3aa8f3 100644
>--- a/extensions/libebt_stp.t
>+++ b/extensions/libebt_stp.t
>@@ -1,13 +1,29 @@
> :INPUT,FORWARD,OUTPUT
> --stp-type 1;=;OK
>+--stp-type ! 1;=;OK
Is this the normal syntax for .t files, or should this be
`! --stp-stype 1` to avoid the infamous "Using intrapositional negation" warning?
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser
2023-12-20 19:29 ` Jan Engelhardt
@ 2023-12-20 21:47 ` Phil Sutter
0 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 21:47 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel
On Wed, Dec 20, 2023 at 08:29:25PM +0100, Jan Engelhardt wrote:
> On Wednesday 2023-12-20 17:06, Phil Sutter wrote:
>
> >index 17d6c1c0978e3..b3c7e5f3aa8f3 100644
> >--- a/extensions/libebt_stp.t
> >+++ b/extensions/libebt_stp.t
> >@@ -1,13 +1,29 @@
> > :INPUT,FORWARD,OUTPUT
> > --stp-type 1;=;OK
> >+--stp-type ! 1;=;OK
>
> Is this the normal syntax for .t files, or should this be
> `! --stp-stype 1` to avoid the infamous "Using intrapositional negation" warning?
With ebtables, intrapositioned negations are still the default although
extrapositioned ones are accepted. For the tests, I chose to use the
former just so I could use '=' in place of expected output.
Since ebtables-nft now uses the xshared commandline parser, it will
indeed complain about these intrapositioned negations. Guess the time
has come to change how ebtables prints rules and to adjust the test
cases accordingly. Thanks for the reminder!
Cheers, Phil
^ permalink raw reply [flat|nested] 31+ messages in thread
* [iptables PATCH 08/23] extensions: libebt_arpreply: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (6 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 07/23] extensions: libebt_stp: Use guided option parser Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 09/23] extensions: libebt_dnat: " Phil Sutter
` (15 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_arpreply.c | 52 +++++++++++++-----------------------
extensions/libebt_arpreply.t | 4 +++
2 files changed, 22 insertions(+), 34 deletions(-)
diff --git a/extensions/libebt_arpreply.c b/extensions/libebt_arpreply.c
index 80ba2159ff946..1d6ba36a27b03 100644
--- a/extensions/libebt_arpreply.c
+++ b/extensions/libebt_arpreply.c
@@ -10,22 +10,22 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <netinet/ether.h>
#include <linux/netfilter_bridge/ebt_arpreply.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define OPT_REPLY_MAC 0x01
-#define OPT_REPLY_TARGET 0x02
+enum {
+ O_MAC,
+ O_TARGET,
+};
-#define REPLY_MAC '1'
-#define REPLY_TARGET '2'
-static const struct option brarpreply_opts[] = {
- { "arpreply-mac" , required_argument, 0, REPLY_MAC },
- { "arpreply-target" , required_argument, 0, REPLY_TARGET },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brarpreply_opts[] = {
+ { .name = "arpreply-mac" , .id = O_MAC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_arpreply_info, mac) },
+ { .name = "arpreply-target" , .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brarpreply_print_help(void)
@@ -44,31 +44,15 @@ static void brarpreply_init(struct xt_entry_target *target)
replyinfo->target = EBT_DROP;
}
-static int
-brarpreply_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **tg)
-
+static void brarpreply_parse(struct xt_option_call *cb)
{
- struct ebt_arpreply_info *replyinfo = (void *)(*tg)->data;
- struct ether_addr *addr;
-
- switch (c) {
- case REPLY_MAC:
- EBT_CHECK_OPTION(flags, OPT_REPLY_MAC);
- if (!(addr = ether_aton(optarg)))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified --arpreply-mac mac");
- memcpy(replyinfo->mac, addr, ETH_ALEN);
- break;
- case REPLY_TARGET:
- EBT_CHECK_OPTION(flags, OPT_REPLY_TARGET);
- if (ebt_fill_target(optarg, (unsigned int *)&replyinfo->target))
- xtables_error(PARAMETER_PROBLEM, "Illegal --arpreply-target target");
- break;
+ struct ebt_arpreply_info *replyinfo = cb->data;
- default:
- return 0;
- }
- return 1;
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&replyinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --arpreply-target target");
}
static void brarpreply_print(const void *ip, const struct xt_entry_target *t, int numeric)
@@ -90,9 +74,9 @@ static struct xtables_target arpreply_target = {
.size = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
.help = brarpreply_print_help,
- .parse = brarpreply_parse,
+ .x6_parse = brarpreply_parse,
.print = brarpreply_print,
- .extra_opts = brarpreply_opts,
+ .x6_options = brarpreply_opts,
};
void _init(void)
diff --git a/extensions/libebt_arpreply.t b/extensions/libebt_arpreply.t
index 6734501a106b5..66103e16dcd42 100644
--- a/extensions/libebt_arpreply.t
+++ b/extensions/libebt_arpreply.t
@@ -1,4 +1,8 @@
:PREROUTING
*nat
+-j arpreply;=;FAIL
+-p ARP -i foo -j arpreply;-p ARP -i foo -j arpreply --arpreply-mac 00:00:00:00:00:00;OK
-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff --arpreply-target ACCEPT;=;OK
-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff;=;OK
+-p ARP -j arpreply ! --arpreply-mac de:ad:00:be:ee:ff;;FAIL
+-p ARP -j arpreply --arpreply-mac de:ad:00:be:ee:ff ! --arpreply-target ACCEPT;;FAIL
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 09/23] extensions: libebt_dnat: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (7 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 08/23] extensions: libebt_arpreply: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 10/23] extensions: libebt_ip6: " Phil Sutter
` (14 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_dnat.c | 64 +++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 37 deletions(-)
diff --git a/extensions/libebt_dnat.c b/extensions/libebt_dnat.c
index 9f5f721ea79d2..447ff105b5ac5 100644
--- a/extensions/libebt_dnat.c
+++ b/extensions/libebt_dnat.c
@@ -9,21 +9,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAT_D '1'
-#define NAT_D_TARGET '2'
-static const struct option brdnat_opts[] =
+enum {
+ O_DST,
+ O_TARGET,
+};
+
+static const struct xt_option_entry brdnat_opts[] =
{
- { "to-destination", required_argument, 0, NAT_D },
- { "to-dst" , required_argument, 0, NAT_D },
- { "dnat-target" , required_argument, 0, NAT_D_TARGET },
- { 0 }
+ { .name = "to-destination", .id = O_DST, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "to-dst" , .id = O_DST, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "dnat-target" , .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brdnat_print_help(void)
@@ -31,7 +35,8 @@ static void brdnat_print_help(void)
printf(
"dnat options:\n"
" --to-dst address : MAC address to map destination to\n"
- " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
+ " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
+ " (standard target is ACCEPT)\n");
}
static void brdnat_init(struct xt_entry_target *target)
@@ -41,35 +46,20 @@ static void brdnat_init(struct xt_entry_target *target)
natinfo->target = EBT_ACCEPT;
}
-#define OPT_DNAT 0x01
-#define OPT_DNAT_TARGET 0x02
-static int brdnat_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brdnat_parse(struct xt_option_call *cb)
{
- struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
- struct ether_addr *addr;
-
- switch (c) {
- case NAT_D:
- EBT_CHECK_OPTION(flags, OPT_DNAT);
- if (!(addr = ether_aton(optarg)))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-destination mac");
- memcpy(natinfo->mac, addr, ETH_ALEN);
- break;
- case NAT_D_TARGET:
- EBT_CHECK_OPTION(flags, OPT_DNAT_TARGET);
- if (ebt_fill_target(optarg, (unsigned int *)&natinfo->target))
- xtables_error(PARAMETER_PROBLEM, "Illegal --dnat-target target");
- break;
- default:
- return 0;
- }
- return 1;
+ struct ebt_nat_info *natinfo = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&natinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --dnat-target target");
}
-static void brdnat_final_check(unsigned int flags)
+static void brdnat_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -116,11 +106,11 @@ static struct xtables_target brdnat_target =
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.help = brdnat_print_help,
.init = brdnat_init,
- .parse = brdnat_parse,
- .final_check = brdnat_final_check,
+ .x6_parse = brdnat_parse,
+ .x6_fcheck = brdnat_final_check,
.print = brdnat_print,
.xlate = brdnat_xlate,
- .extra_opts = brdnat_opts,
+ .x6_options = brdnat_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 10/23] extensions: libebt_ip6: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (8 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 09/23] extensions: libebt_dnat: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 11/23] extensions: libebt_ip: " Phil Sutter
` (13 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_ip6.c | 199 +++++++++++++++-------------------------
extensions/libebt_ip6.t | 8 ++
2 files changed, 83 insertions(+), 124 deletions(-)
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index d926e86a585f4..0d7403e72589a 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -18,59 +18,59 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_ip6.h>
#include "libxt_icmp.h"
-#define IP_SOURCE '1'
-#define IP_DEST '2'
-#define IP_TCLASS '3'
-#define IP_PROTO '4'
-#define IP_SPORT '5'
-#define IP_DPORT '6'
-#define IP_ICMP6 '7'
-
-static const struct option brip6_opts[] = {
- { .name = "ip6-source", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip6-src", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip6-destination", .has_arg = true, .val = IP_DEST },
- { .name = "ip6-dst", .has_arg = true, .val = IP_DEST },
- { .name = "ip6-tclass", .has_arg = true, .val = IP_TCLASS },
- { .name = "ip6-protocol", .has_arg = true, .val = IP_PROTO },
- { .name = "ip6-proto", .has_arg = true, .val = IP_PROTO },
- { .name = "ip6-source-port", .has_arg = true, .val = IP_SPORT },
- { .name = "ip6-sport", .has_arg = true, .val = IP_SPORT },
- { .name = "ip6-destination-port",.has_arg = true,.val = IP_DPORT },
- { .name = "ip6-dport", .has_arg = true, .val = IP_DPORT },
- { .name = "ip6-icmp-type", .has_arg = true, .val = IP_ICMP6 },
- XT_GETOPT_TABLEEND,
+/* must correspond to the bit position in EBT_IP6_* defines */
+enum {
+ O_SOURCE = 0,
+ O_DEST,
+ O_TCLASS,
+ O_PROTO,
+ O_SPORT,
+ O_DPORT,
+ O_ICMP6,
+ F_PORT = 1 << O_ICMP6,
+ F_ICMP6 = 1 << O_SPORT | 1 << O_DPORT,
};
-static void
-parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = xtables_strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
- ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
-
- if (ports[0] > ports[1])
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
+static const struct xt_option_entry brip6_opts[] = {
+ { .name = "ip6-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip6-tclass", .id = O_TCLASS, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, tclass) },
+ { .name = "ip6-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, protocol) },
+ { .name = "ip6-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, protocol) },
+ { .name = "ip6-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, sport) },
+ { .name = "ip6-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, sport) },
+ { .name = "ip6-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, dport) },
+ { .name = "ip6-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip6_info, dport) },
+ { .name = "ip6-icmp-type", .id = O_ICMP6, .type = XTTYPE_STRING,
+ .excl = F_ICMP6, .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
+};
static void print_port_range(uint16_t *ports)
{
@@ -127,91 +127,42 @@ static void brip6_print_help(void)
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
}
-/* wrap xtables_ip6parse_any(), ignoring any but the first returned address */
-static void ebt_parse_ip6_address(char *address,
- struct in6_addr *addr, struct in6_addr *msk)
-{
- struct in6_addr *addrp;
- unsigned int naddrs;
-
- xtables_ip6parse_any(address, &addrp, msk, &naddrs);
- if (naddrs != 1)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid IPv6 Address '%s' specified", address);
- memcpy(addr, addrp, sizeof(*addr));
- free(addrp);
-}
-
-#define OPT_SOURCE 0x01
-#define OPT_DEST 0x02
-#define OPT_TCLASS 0x04
-#define OPT_PROTO 0x08
-#define OPT_SPORT 0x10
-#define OPT_DPORT 0x20
-static int
-brip6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brip6_parse(struct xt_option_call *cb)
{
- struct ebt_ip6_info *info = (struct ebt_ip6_info *)(*match)->data;
+ struct ebt_ip6_info *info = cb->data;
unsigned int i;
- char *end;
-
- switch (c) {
- case IP_SOURCE:
- if (invert)
- info->invflags |= EBT_IP6_SOURCE;
- ebt_parse_ip6_address(optarg, &info->saddr, &info->smsk);
- info->bitmask |= EBT_IP6_SOURCE;
- break;
- case IP_DEST:
- if (invert)
- info->invflags |= EBT_IP6_DEST;
- ebt_parse_ip6_address(optarg, &info->daddr, &info->dmsk);
- info->bitmask |= EBT_IP6_DEST;
- break;
- case IP_SPORT:
- if (invert)
- info->invflags |= EBT_IP6_SPORT;
- parse_port_range(NULL, optarg, info->sport);
- info->bitmask |= EBT_IP6_SPORT;
- break;
- case IP_DPORT:
- if (invert)
- info->invflags |= EBT_IP6_DPORT;
- parse_port_range(NULL, optarg, info->dport);
- info->bitmask |= EBT_IP6_DPORT;
- break;
- case IP_ICMP6:
- if (invert)
- info->invflags |= EBT_IP6_ICMP6;
- ebt_parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code);
- info->bitmask |= EBT_IP6_ICMP6;
+
+ /* XXX: overriding afinfo family is dangerous, but
+ * required for XTTYPE_HOSTMASK parsing */
+ xtables_set_nfproto(NFPROTO_IPV6);
+ xtables_option_parse(cb);
+ xtables_set_nfproto(NFPROTO_BRIDGE);
+
+ info->bitmask |= 1 << cb->entry->id;
+ info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
+
+ switch (cb->entry->id) {
+ case O_SOURCE:
+ for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
+ cb->val.haddr.all[i] &= cb->val.hmask.all[i];
+ info->saddr = cb->val.haddr.in6;
+ info->smsk = cb->val.hmask.in6;
break;
- case IP_TCLASS:
- if (invert)
- info->invflags |= EBT_IP6_TCLASS;
- if (!xtables_strtoui(optarg, &end, &i, 0, 255))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified IPv6 traffic class '%s'", optarg);
- info->tclass = i;
- info->bitmask |= EBT_IP6_TCLASS;
+ case O_DEST:
+ for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
+ cb->val.haddr.all[i] &= cb->val.hmask.all[i];
+ info->daddr = cb->val.haddr.in6;
+ info->dmsk = cb->val.hmask.in6;
break;
- case IP_PROTO:
- if (invert)
- info->invflags |= EBT_IP6_PROTO;
- info->protocol = xtables_parse_protocol(optarg);
- info->bitmask |= EBT_IP6_PROTO;
+ case O_ICMP6:
+ ebt_parse_icmpv6(cb->arg, info->icmpv6_type, info->icmpv6_code);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
}
-static void brip6_final_check(unsigned int flags)
+static void brip6_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -441,11 +392,11 @@ static struct xtables_match brip6_match = {
.size = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.help = brip6_print_help,
- .parse = brip6_parse,
- .final_check = brip6_final_check,
+ .x6_parse = brip6_parse,
+ .x6_fcheck = brip6_final_check,
.print = brip6_print,
.xlate = brip6_xlate,
- .extra_opts = brip6_opts,
+ .x6_options = brip6_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t
index fa1038af25649..19358431d7ca0 100644
--- a/extensions/libebt_ip6.t
+++ b/extensions/libebt_ip6.t
@@ -2,14 +2,22 @@
-p ip6 --ip6-src ! dead::beef/64 -j ACCEPT;-p IPv6 --ip6-src ! dead::/64 -j ACCEPT;OK
-p IPv6 --ip6-dst dead:beef::/64 -j ACCEPT;=;OK
-p IPv6 --ip6-dst f00:ba::;=;OK
+-p IPv6 --ip6-dst ! f00:ba::;=;OK
+-p IPv6 --ip6-src 10.0.0.1;;FAIL
-p IPv6 --ip6-tclass 0xFF;=;OK
+-p IPv6 --ip6-tclass ! 0xFF;=;OK
-p IPv6 --ip6-proto tcp --ip6-dport 22;=;OK
-p IPv6 --ip6-proto tcp --ip6-dport ! 22;=;OK
+-p IPv6 --ip6-proto tcp --ip6-sport ! 22 --ip6-dport 22;=;OK
-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK
-p IPv6 --ip6-proto 253;=;OK
+-p IPv6 --ip6-proto ! 253;=;OK
-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request -j CONTINUE;=;OK
-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request;=;OK
+-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type ! echo-request;=;OK
-p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1;-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type communication-prohibited -j CONTINUE;OK
-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type ! 1:10/0:255;=;OK
--ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
! -p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
+-p IPv6 --ip6-proto tcp --ip6-sport 22 --ip6-icmp-type echo-request;;FAIL
+-p IPv6 --ip6-proto tcp --ip6-dport 22 --ip6-icmp-type echo-request;;FAIL
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 11/23] extensions: libebt_ip: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (9 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 10/23] extensions: libebt_ip6: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 12/23] extensions: libebt_log: " Phil Sutter
` (12 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_ip.c | 199 ++++++++++++++++-------------------------
extensions/libebt_ip.t | 8 ++
2 files changed, 84 insertions(+), 123 deletions(-)
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 97ec4160942da..350dbcb6abb09 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -16,7 +16,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <inttypes.h>
#include <xtables.h>
@@ -24,30 +23,56 @@
#include "libxt_icmp.h"
-#define IP_SOURCE '1'
-#define IP_DEST '2'
-#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
-#define IP_PROTO '4'
-#define IP_SPORT '5'
-#define IP_DPORT '6'
-#define IP_EBT_ICMP '7'
-#define IP_EBT_IGMP '8'
-
-static const struct option brip_opts[] = {
- { .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip-destination", .has_arg = true, .val = IP_DEST },
- { .name = "ip-dst", .has_arg = true, .val = IP_DEST },
- { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
- { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
- { .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
- { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
- { .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
- { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
- { .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
- { .name = "ip-icmp-type", .has_arg = true, .val = IP_EBT_ICMP },
- { .name = "ip-igmp-type", .has_arg = true, .val = IP_EBT_IGMP },
- XT_GETOPT_TABLEEND,
+/* must correspond to the bit position in EBT_IP6_* defines */
+enum {
+ O_SOURCE = 0,
+ O_DEST,
+ O_TOS,
+ O_PROTO,
+ O_SPORT,
+ O_DPORT,
+ O_ICMP,
+ O_IGMP,
+ F_PORT = 1 << O_ICMP | 1 << O_IGMP,
+ F_ICMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_IGMP,
+ F_IGMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_ICMP,
+};
+
+static const struct xt_option_entry brip_opts[] = {
+ { .name = "ip-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-tos", .id = O_TOS, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, tos) },
+ { .name = "ip-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-icmp-type", .id = O_ICMP, .type = XTTYPE_STRING,
+ .excl = F_ICMP, .flags = XTOPT_INVERT },
+ { .name = "ip-igmp-type", .id = O_IGMP, .type = XTTYPE_STRING,
+ .excl = F_IGMP, .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
static void brip_print_help(void)
@@ -69,30 +94,6 @@ static void brip_print_help(void)
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
}
-static void
-parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = xtables_strdup(portstring);
-
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
- ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
-
- if (ports[0] > ports[1])
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
/* original code from ebtables: useful_functions.c */
static void print_icmp_code(uint8_t *code)
{
@@ -130,86 +131,38 @@ static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
print_icmp_code(code);
}
-static int
-brip_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brip_parse(struct xt_option_call *cb)
{
- struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
- unsigned int ipnr;
-
- switch (c) {
- case IP_SOURCE:
- if (invert)
- info->invflags |= EBT_IP_SOURCE;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->saddr = ipaddr->s_addr;
- info->smsk = ipmask.s_addr;
- free(ipaddr);
- info->bitmask |= EBT_IP_SOURCE;
- break;
- case IP_DEST:
- if (invert)
- info->invflags |= EBT_IP_DEST;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->daddr = ipaddr->s_addr;
- info->dmsk = ipmask.s_addr;
- free(ipaddr);
- info->bitmask |= EBT_IP_DEST;
- break;
- case IP_SPORT:
- if (invert)
- info->invflags |= EBT_IP_SPORT;
- parse_port_range(NULL, optarg, info->sport);
- info->bitmask |= EBT_IP_SPORT;
- break;
- case IP_DPORT:
- if (invert)
- info->invflags |= EBT_IP_DPORT;
- parse_port_range(NULL, optarg, info->dport);
- info->bitmask |= EBT_IP_DPORT;
- break;
- case IP_EBT_ICMP:
- if (invert)
- info->invflags |= EBT_IP_ICMP;
- ebt_parse_icmp(optarg, info->icmp_type, info->icmp_code);
- info->bitmask |= EBT_IP_ICMP;
+ struct ebt_ip_info *info = cb->data;
+
+ xtables_option_parse(cb);
+
+ info->bitmask |= 1 << cb->entry->id;
+ info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
+
+ switch (cb->entry->id) {
+ case O_SOURCE:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->saddr = cb->val.haddr.ip;
+ info->smsk = cb->val.hmask.ip;
break;
- case IP_EBT_IGMP:
- if (invert)
- info->invflags |= EBT_IP_IGMP;
- ebt_parse_igmp(optarg, info->igmp_type);
- info->bitmask |= EBT_IP_IGMP;
+ case O_DEST:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->daddr = cb->val.haddr.ip;
+ info->dmsk = cb->val.hmask.ip;
break;
- case IP_EBT_TOS: {
- uintmax_t tosvalue;
-
- if (invert)
- info->invflags |= EBT_IP_TOS;
- if (!xtables_strtoul(optarg, NULL, &tosvalue, 0, 255))
- xtables_error(PARAMETER_PROBLEM,
- "Problem with specified IP tos");
- info->tos = tosvalue;
- info->bitmask |= EBT_IP_TOS;
- }
+ case O_ICMP:
+ ebt_parse_icmp(cb->arg, info->icmp_type, info->icmp_code);
break;
- case IP_PROTO:
- if (invert)
- info->invflags |= EBT_IP_PROTO;
- info->protocol = xtables_parse_protocol(optarg);
- info->bitmask |= EBT_IP_PROTO;
+ case O_IGMP:
+ ebt_parse_igmp(cb->arg, info->igmp_type);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
}
-static void brip_final_check(unsigned int flags)
+static void brip_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -496,11 +449,11 @@ static struct xtables_match brip_match = {
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
.help = brip_print_help,
- .parse = brip_parse,
- .final_check = brip_final_check,
+ .x6_parse = brip_parse,
+ .x6_fcheck = brip_final_check,
.print = brip_print,
.xlate = brip_xlate,
- .extra_opts = brip_opts,
+ .x6_options = brip_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t
index 8be5dfbb22309..f6012df4c264e 100644
--- a/extensions/libebt_ip.t
+++ b/extensions/libebt_ip.t
@@ -1,13 +1,21 @@
:INPUT,FORWARD,OUTPUT
-p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 --ip-src ! 192.168.0.0/24 -j ACCEPT;OK
-p IPv4 --ip-dst 10.0.0.1;=;OK
+-p IPv4 --ip-dst ! 10.0.0.1;=;OK
-p IPv4 --ip-tos 0xFF;=;OK
-p IPv4 --ip-tos ! 0xFF;=;OK
-p IPv4 --ip-proto tcp --ip-dport 22;=;OK
-p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK
-p IPv4 --ip-proto 253;=;OK
+-p IPv4 --ip-proto ! 253;=;OK
-p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK
-p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK
-p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp --ip-icmp-type ! 1:10/0:255 -j CONTINUE;OK
--ip-proto icmp --ip-icmp-type 1/1;=;FAIL
! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL
+! -p ip --ip-proto tcp --ip-sport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-sport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto icmp --ip-icmp-type echo-reply --ip-igmp-type membership-query;;FAIL
+-p IPv4 --ip-proto icmp --ip-icmp-type ! echo-reply;=;OK
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 12/23] extensions: libebt_log: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (10 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 11/23] extensions: libebt_ip: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 13/23] extensions: libebt_mark: " Phil Sutter
` (11 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_log.c | 121 ++++++++++------------------------------
1 file changed, 30 insertions(+), 91 deletions(-)
diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
index 9f8d158956802..dc2357c022bf0 100644
--- a/extensions/libebt_log.c
+++ b/extensions/libebt_log.c
@@ -14,19 +14,11 @@
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_log.h>
#define LOG_DEFAULT_LEVEL LOG_INFO
-#define LOG_PREFIX '1'
-#define LOG_LEVEL '2'
-#define LOG_ARP '3'
-#define LOG_IP '4'
-#define LOG_LOG '5'
-#define LOG_IP6 '6'
-
struct code {
char *c_name;
int c_val;
@@ -43,26 +35,26 @@ static struct code eight_priority[] = {
{ "debug", LOG_DEBUG }
};
-static int name_to_loglevel(const char *arg)
-{
- int i;
-
- for (i = 0; i < 8; i++)
- if (!strcmp(arg, eight_priority[i].c_name))
- return eight_priority[i].c_val;
-
- /* return bad loglevel */
- return 9;
-}
+enum {
+ /* first three must correspond with bit pos in respective EBT_LOG_* */
+ O_LOG_IP = 0,
+ O_LOG_ARP = 1,
+ O_LOG_IP6 = 3,
+ O_LOG_PREFIX,
+ O_LOG_LEVEL,
+ O_LOG_LOG,
+};
-static const struct option brlog_opts[] = {
- { .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX },
- { .name = "log-level", .has_arg = true, .val = LOG_LEVEL },
- { .name = "log-arp", .has_arg = false, .val = LOG_ARP },
- { .name = "log-ip", .has_arg = false, .val = LOG_IP },
- { .name = "log", .has_arg = false, .val = LOG_LOG },
- { .name = "log-ip6", .has_arg = false, .val = LOG_IP6 },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brlog_opts[] = {
+ { .name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, prefix) },
+ { .name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, loglevel) },
+ { .name = "log-arp", .id = O_LOG_ARP, .type = XTTYPE_NONE },
+ { .name = "log-ip", .id = O_LOG_IP, .type = XTTYPE_NONE },
+ { .name = "log", .id = O_LOG_LOG, .type = XTTYPE_NONE },
+ { .name = "log-ip6", .id = O_LOG_IP6, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brlog_help(void)
@@ -87,73 +79,21 @@ static void brlog_init(struct xt_entry_target *t)
{
struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
- loginfo->bitmask = 0;
- loginfo->prefix[0] = '\0';
loginfo->loglevel = LOG_NOTICE;
}
-static unsigned int log_chk_inv(int inv, unsigned int bit, const char *suffix)
-{
- if (inv)
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --log%s", suffix);
- return bit;
-}
-
-static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brlog_parse(struct xt_option_call *cb)
{
- struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
- long int i;
- char *end;
-
- switch (c) {
- case LOG_PREFIX:
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!` after --log-prefix");
- if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- xtables_error(PARAMETER_PROBLEM,
- "Prefix too long");
- if (strchr(optarg, '\"'))
- xtables_error(PARAMETER_PROBLEM,
- "Use of \\\" is not allowed"
- " in the prefix");
- strcpy((char *)loginfo->prefix, (char *)optarg);
+ struct ebt_log_info *loginfo = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LOG_IP:
+ case O_LOG_ARP:
+ case O_LOG_IP6:
+ loginfo->bitmask |= 1 << cb->entry->id;
break;
- case LOG_LEVEL:
- i = strtol(optarg, &end, 16);
- if (*end != '\0' || i < 0 || i > 7)
- loginfo->loglevel = name_to_loglevel(optarg);
- else
- loginfo->loglevel = i;
-
- if (loginfo->loglevel == 9)
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the log-level");
- break;
- case LOG_IP:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP, "-ip");
- break;
- case LOG_ARP:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_ARP, "-arp");
- break;
- case LOG_LOG:
- loginfo->bitmask |= log_chk_inv(invert, 0, "");
- break;
- case LOG_IP6:
- loginfo->bitmask |= log_chk_inv(invert, EBT_LOG_IP6, "-ip6");
- break;
- default:
- return 0;
}
-
- *flags |= loginfo->bitmask;
- return 1;
-}
-
-static void brlog_final_check(unsigned int flags)
-{
}
static void brlog_print(const void *ip, const struct xt_entry_target *target,
@@ -204,11 +144,10 @@ static struct xtables_target brlog_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
.init = brlog_init,
.help = brlog_help,
- .parse = brlog_parse,
- .final_check = brlog_final_check,
+ .x6_parse = brlog_parse,
.print = brlog_print,
.xlate = brlog_xlate,
- .extra_opts = brlog_opts,
+ .x6_options = brlog_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 13/23] extensions: libebt_mark: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (11 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 12/23] extensions: libebt_log: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 14/23] extensions: libebt_nflog: " Phil Sutter
` (10 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_mark.c | 140 +++++++++++++++------------------------
1 file changed, 54 insertions(+), 86 deletions(-)
diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c
index 40e49618e0215..0dc598fe1009d 100644
--- a/extensions/libebt_mark.c
+++ b/extensions/libebt_mark.c
@@ -12,27 +12,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_mark_t.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define MARK_TARGET '1'
-#define MARK_SETMARK '2'
-#define MARK_ORMARK '3'
-#define MARK_ANDMARK '4'
-#define MARK_XORMARK '5'
-static const struct option brmark_opts[] = {
- { .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
+enum {
+ O_SET_MARK = 0,
+ O_AND_MARK,
+ O_OR_MARK,
+ O_XOR_MARK,
+ O_MARK_TARGET,
+ F_SET_MARK = 1 << O_SET_MARK,
+ F_AND_MARK = 1 << O_AND_MARK,
+ F_OR_MARK = 1 << O_OR_MARK,
+ F_XOR_MARK = 1 << O_XOR_MARK,
+ F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK | F_XOR_MARK,
+};
+
+static const struct xt_option_entry brmark_opts[] = {
+ { .name = "mark-target",.id = O_MARK_TARGET, .type = XTTYPE_STRING },
/* an oldtime messup, we should have always used the scheme
* <extension-name>-<option> */
- { .name = "set-mark", .has_arg = true, .val = MARK_SETMARK },
- { .name = "mark-set", .has_arg = true, .val = MARK_SETMARK },
- { .name = "mark-or", .has_arg = true, .val = MARK_ORMARK },
- { .name = "mark-and", .has_arg = true, .val = MARK_ANDMARK },
- { .name = "mark-xor", .has_arg = true, .val = MARK_XORMARK },
- XT_GETOPT_TABLEEND,
+ { .name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-set", .id = O_SET_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-or", .id = O_OR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-and", .id = O_AND_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ { .name = "mark-xor", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
+ .excl = F_ANY },
+ XTOPT_TABLEEND,
};
static void brmark_print_help(void)
@@ -54,83 +66,39 @@ static void brmark_init(struct xt_entry_target *target)
info->mark = 0;
}
-#define OPT_MARK_TARGET 0x01
-#define OPT_MARK_SETMARK 0x02
-#define OPT_MARK_ORMARK 0x04
-#define OPT_MARK_ANDMARK 0x08
-#define OPT_MARK_XORMARK 0x10
-
-static int
-brmark_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brmark_parse(struct xt_option_call *cb)
{
- struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)
- (*target)->data;
- char *end;
- uint32_t mask;
-
- switch (c) {
- case MARK_TARGET:
- { unsigned int tmp;
- EBT_CHECK_OPTION(flags, OPT_MARK_TARGET);
- if (ebt_fill_target(optarg, &tmp))
+ static const unsigned long target_orval[] = {
+ [O_SET_MARK] = MARK_SET_VALUE,
+ [O_AND_MARK] = MARK_AND_VALUE,
+ [O_OR_MARK] = MARK_OR_VALUE,
+ [O_XOR_MARK] = MARK_XOR_VALUE,
+ };
+ struct ebt_mark_t_info *info = cb->data;
+ unsigned int tmp;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_MARK_TARGET:
+ if (ebt_fill_target(cb->arg, &tmp))
xtables_error(PARAMETER_PROBLEM,
"Illegal --mark-target target");
/* the 4 lsb are left to designate the target */
info->target = (info->target & ~EBT_VERDICT_BITS) |
(tmp & EBT_VERDICT_BITS);
- }
- return 1;
- case MARK_SETMARK:
- EBT_CHECK_OPTION(flags, OPT_MARK_SETMARK);
- mask = (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
- if (*flags & mask)
- xtables_error(PARAMETER_PROBLEM,
- "--mark-set cannot be used together with"
- " specific --mark option");
- info->target = (info->target & EBT_VERDICT_BITS) |
- MARK_SET_VALUE;
- break;
- case MARK_ORMARK:
- EBT_CHECK_OPTION(flags, OPT_MARK_ORMARK);
- mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
- if (*flags & mask)
- xtables_error(PARAMETER_PROBLEM,
- "--mark-or cannot be used together with"
- " specific --mark option");
- info->target = (info->target & EBT_VERDICT_BITS) |
- MARK_OR_VALUE;
- break;
- case MARK_ANDMARK:
- EBT_CHECK_OPTION(flags, OPT_MARK_ANDMARK);
- mask = (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK);
- if (*flags & mask)
- xtables_error(PARAMETER_PROBLEM,
- "--mark-and cannot be used together with"
- " specific --mark option");
- info->target = (info->target & EBT_VERDICT_BITS) |
- MARK_AND_VALUE;
- break;
- case MARK_XORMARK:
- EBT_CHECK_OPTION(flags, OPT_MARK_XORMARK);
- mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK);
- if (*flags & mask)
- xtables_error(PARAMETER_PROBLEM,
- "--mark-xor cannot be used together with"
- " specific --mark option");
- info->target = (info->target & EBT_VERDICT_BITS) |
- MARK_XOR_VALUE;
+ return;
+ case O_SET_MARK:
+ case O_OR_MARK:
+ case O_AND_MARK:
+ case O_XOR_MARK:
break;
default:
- return 0;
+ return;
}
/* mutual code */
- info->mark = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'",
- optarg);
-
- return 1;
+ info->mark = cb->val.u32;
+ info->target = (info->target & EBT_VERDICT_BITS) |
+ target_orval[cb->entry->id];
}
static void brmark_print(const void *ip, const struct xt_entry_target *target,
@@ -156,9 +124,9 @@ static void brmark_print(const void *ip, const struct xt_entry_target *target,
printf(" --mark-target %s", ebt_target_name(tmp));
}
-static void brmark_final_check(unsigned int flags)
+static void brmark_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify some option");
}
@@ -215,11 +183,11 @@ static struct xtables_target brmark_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
.help = brmark_print_help,
.init = brmark_init,
- .parse = brmark_parse,
- .final_check = brmark_final_check,
+ .x6_parse = brmark_parse,
+ .x6_fcheck = brmark_final_check,
.print = brmark_print,
.xlate = brmark_xlate,
- .extra_opts = brmark_opts,
+ .x6_options = brmark_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 14/23] extensions: libebt_nflog: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (12 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 13/23] extensions: libebt_mark: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 15/23] extensions: libebt_snat: " Phil Sutter
` (9 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_nflog.c | 82 +++++++++------------------------------
1 file changed, 18 insertions(+), 64 deletions(-)
diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c
index 762d6d5d8bbe2..48cd53218bf08 100644
--- a/extensions/libebt_nflog.c
+++ b/extensions/libebt_nflog.c
@@ -16,27 +16,30 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#include <linux/netfilter_bridge/ebt_nflog.h>
enum {
- NFLOG_GROUP = 0x1,
- NFLOG_PREFIX = 0x2,
- NFLOG_RANGE = 0x4,
- NFLOG_THRESHOLD = 0x8,
- NFLOG_NFLOG = 0x16,
+ O_GROUP = 0,
+ O_PREFIX,
+ O_RANGE,
+ O_THRESHOLD,
+ O_NFLOG,
};
-static const struct option brnflog_opts[] = {
- { .name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP},
- { .name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX},
- { .name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE},
- { .name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD},
- { .name = "nflog", .has_arg = false, .val = NFLOG_NFLOG},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brnflog_opts[] = {
+ { .name = "nflog-group", .id = O_GROUP, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, group) },
+ { .name = "nflog-prefix", .id = O_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, prefix) },
+ { .name = "nflog-range", .id = O_RANGE, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, len) },
+ { .name = "nflog-threshold", .id = O_THRESHOLD, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, threshold) },
+ { .name = "nflog", .id = O_NFLOG, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brnflog_help(void)
@@ -59,55 +62,6 @@ static void brnflog_init(struct xt_entry_target *t)
info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD;
}
-static int brnflog_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct ebt_nflog_info *info = (struct ebt_nflog_info *)(*target)->data;
- unsigned int i;
-
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "The use of '!' makes no sense for the"
- " nflog watcher");
-
- switch (c) {
- case NFLOG_PREFIX:
- EBT_CHECK_OPTION(flags, NFLOG_PREFIX);
- if (strlen(optarg) > EBT_NFLOG_PREFIX_SIZE - 1)
- xtables_error(PARAMETER_PROBLEM,
- "Prefix too long for nflog-prefix");
- strncpy(info->prefix, optarg, EBT_NFLOG_PREFIX_SIZE);
- break;
- case NFLOG_GROUP:
- EBT_CHECK_OPTION(flags, NFLOG_GROUP);
- if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "--nflog-group must be a number!");
- info->group = i;
- break;
- case NFLOG_RANGE:
- EBT_CHECK_OPTION(flags, NFLOG_RANGE);
- if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "--nflog-range must be a number!");
- info->len = i;
- break;
- case NFLOG_THRESHOLD:
- EBT_CHECK_OPTION(flags, NFLOG_THRESHOLD);
- if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "--nflog-threshold must be a number!");
- info->threshold = i;
- break;
- case NFLOG_NFLOG:
- EBT_CHECK_OPTION(flags, NFLOG_NFLOG);
- break;
- default:
- return 0;
- }
- return 1;
-}
-
static void
brnflog_print(const void *ip, const struct xt_entry_target *target,
int numeric)
@@ -153,10 +107,10 @@ static struct xtables_target brnflog_watcher = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
.init = brnflog_init,
.help = brnflog_help,
- .parse = brnflog_parse,
+ .x6_parse = xtables_option_parse,
.print = brnflog_print,
.xlate = brnflog_xlate,
- .extra_opts = brnflog_opts,
+ .x6_options = brnflog_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 15/23] extensions: libebt_snat: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (13 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 14/23] extensions: libebt_nflog: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 16/23] extensions: libebt_redirect: " Phil Sutter
` (8 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_snat.c | 74 +++++++++++++++++-----------------------
extensions/libebt_snat.t | 2 ++
2 files changed, 34 insertions(+), 42 deletions(-)
diff --git a/extensions/libebt_snat.c b/extensions/libebt_snat.c
index c1124bf32d1e5..1dc738fa5ca36 100644
--- a/extensions/libebt_snat.c
+++ b/extensions/libebt_snat.c
@@ -9,23 +9,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netinet/ether.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAT_S '1'
-#define NAT_S_TARGET '2'
-#define NAT_S_ARP '3'
-static const struct option brsnat_opts[] =
+enum {
+ O_SRC,
+ O_TARGET,
+ O_ARP,
+};
+
+static const struct xt_option_entry brsnat_opts[] =
{
- { "to-source" , required_argument, 0, NAT_S },
- { "to-src" , required_argument, 0, NAT_S },
- { "snat-target" , required_argument, 0, NAT_S_TARGET },
- { "snat-arp" , no_argument, 0, NAT_S_ARP },
- { 0 }
+ { .name = "to-source", .id = O_SRC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "to-src", .id = O_SRC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
+ { .name = "snat-target", .id = O_TARGET, .type = XTTYPE_STRING },
+ { .name = "snat-arp", .id = O_ARP, .type = XTTYPE_NONE },
+ XTOPT_TABLEEND,
};
static void brsnat_print_help(void)
@@ -44,43 +48,29 @@ static void brsnat_init(struct xt_entry_target *target)
natinfo->target = EBT_ACCEPT;
}
-#define OPT_SNAT 0x01
-#define OPT_SNAT_TARGET 0x02
-#define OPT_SNAT_ARP 0x04
-static int brsnat_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brsnat_parse(struct xt_option_call *cb)
{
- struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
- struct ether_addr *addr;
-
- switch (c) {
- case NAT_S:
- EBT_CHECK_OPTION(flags, OPT_SNAT);
- if (!(addr = ether_aton(optarg)))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-source mac");
- memcpy(natinfo->mac, addr, ETH_ALEN);
- break;
- case NAT_S_TARGET:
- { unsigned int tmp;
- EBT_CHECK_OPTION(flags, OPT_SNAT_TARGET);
- if (ebt_fill_target(optarg, &tmp))
- xtables_error(PARAMETER_PROBLEM, "Illegal --snat-target target");
- natinfo->target = (natinfo->target & ~EBT_VERDICT_BITS) | (tmp & EBT_VERDICT_BITS);
- }
+ struct ebt_nat_info *natinfo = cb->data;
+ unsigned int tmp;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TARGET:
+ if (ebt_fill_target(cb->arg, &tmp))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --snat-target target");
+ natinfo->target &= ~EBT_VERDICT_BITS;
+ natinfo->target |= tmp & EBT_VERDICT_BITS;
break;
- case NAT_S_ARP:
- EBT_CHECK_OPTION(flags, OPT_SNAT_ARP);
+ case O_ARP:
natinfo->target ^= NAT_ARP_BIT;
break;
- default:
- return 0;
}
- return 1;
}
-static void brsnat_final_check(unsigned int flags)
+static void brsnat_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -133,11 +123,11 @@ static struct xtables_target brsnat_target =
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.help = brsnat_print_help,
.init = brsnat_init,
- .parse = brsnat_parse,
- .final_check = brsnat_final_check,
+ .x6_parse = brsnat_parse,
+ .x6_fcheck = brsnat_final_check,
.print = brsnat_print,
.xlate = brsnat_xlate,
- .extra_opts = brsnat_opts,
+ .x6_options = brsnat_opts,
};
void _init(void)
diff --git a/extensions/libebt_snat.t b/extensions/libebt_snat.t
index 639b13f300c9d..f5d02340fc576 100644
--- a/extensions/libebt_snat.t
+++ b/extensions/libebt_snat.t
@@ -2,3 +2,5 @@
*nat
-o someport -j snat --to-source a:b:c:d:e:f;-o someport -j snat --to-src 0a:0b:0c:0d:0e:0f --snat-target ACCEPT;OK
-o someport+ -j snat --to-src de:ad:00:be:ee:ff --snat-target CONTINUE;=;OK
+-j snat;;FAIL
+-j snat --to-src de:ad:00:be:ee:ff;-j snat --to-src de:ad:00:be:ee:ff --snat-target ACCEPT;OK
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 16/23] extensions: libebt_redirect: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (14 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 15/23] extensions: libebt_snat: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 17/23] extensions: libebt_802_3: " Phil Sutter
` (7 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_redirect.c | 40 +++++++++++++++---------------------
1 file changed, 17 insertions(+), 23 deletions(-)
diff --git a/extensions/libebt_redirect.c b/extensions/libebt_redirect.c
index 7821935e137aa..a44dbaec6cc8b 100644
--- a/extensions/libebt_redirect.c
+++ b/extensions/libebt_redirect.c
@@ -9,17 +9,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_redirect.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define REDIRECT_TARGET '1'
-static const struct option brredir_opts[] =
+enum {
+ O_TARGET,
+};
+
+static const struct xt_option_entry brredir_opts[] =
{
- { "redirect-target", required_argument, 0, REDIRECT_TARGET },
- { 0 }
+ { .name = "redirect-target", .id = O_TARGET, .type = XTTYPE_STRING },
+ XTOPT_TABLEEND,
};
static void brredir_print_help(void)
@@ -37,23 +39,15 @@ static void brredir_init(struct xt_entry_target *target)
redirectinfo->target = EBT_ACCEPT;
}
-#define OPT_REDIRECT_TARGET 0x01
-static int brredir_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void brredir_parse(struct xt_option_call *cb)
{
- struct ebt_redirect_info *redirectinfo =
- (struct ebt_redirect_info *)(*target)->data;
-
- switch (c) {
- case REDIRECT_TARGET:
- EBT_CHECK_OPTION(flags, OPT_REDIRECT_TARGET);
- if (ebt_fill_target(optarg, (unsigned int *)&redirectinfo->target))
- xtables_error(PARAMETER_PROBLEM, "Illegal --redirect-target target");
- break;
- default:
- return 0;
- }
- return 1;
+ struct ebt_redirect_info *redirectinfo = cb->data;
+
+ xtables_option_parse(cb);
+ if (cb->entry->id == O_TARGET &&
+ ebt_fill_target(cb->arg, (unsigned int *)&redirectinfo->target))
+ xtables_error(PARAMETER_PROBLEM,
+ "Illegal --redirect-target target");
}
static void brredir_print(const void *ip, const struct xt_entry_target *target, int numeric)
@@ -97,10 +91,10 @@ static struct xtables_target brredirect_target = {
.userspacesize = XT_ALIGN(sizeof(struct ebt_redirect_info)),
.help = brredir_print_help,
.init = brredir_init,
- .parse = brredir_parse,
+ .x6_parse = brredir_parse,
.print = brredir_print,
.xlate = brredir_xlate,
- .extra_opts = brredir_opts,
+ .x6_options = brredir_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 17/23] extensions: libebt_802_3: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (15 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 16/23] extensions: libebt_redirect: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 18/23] extensions: libebt_vlan: " Phil Sutter
` (6 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_802_3.c | 74 ++++++++++-----------------------------
extensions/libebt_802_3.t | 2 ++
2 files changed, 21 insertions(+), 55 deletions(-)
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
index 8cbcdcea4912f..26a7725cd0074 100644
--- a/extensions/libebt_802_3.c
+++ b/extensions/libebt_802_3.c
@@ -13,17 +13,20 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_802_3.h>
-#define _802_3_SAP '1'
-#define _802_3_TYPE '2'
-
-static const struct option br802_3_opts[] = {
- { .name = "802_3-sap", .has_arg = true, .val = _802_3_SAP },
- { .name = "802_3-type", .has_arg = true, .val = _802_3_TYPE },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry br802_3_opts[] =
+{
+ { .name = "802_3-sap", .id = EBT_802_3_SAP,
+ .type = XTTYPE_UINT8, .base = 16,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_802_3_info, sap) },
+ { .name = "802_3-type", .id = EBT_802_3_TYPE,
+ .type = XTTYPE_UINT16, .base = 16,
+ .flags = XTOPT_INVERT | XTOPT_PUT | XTOPT_NBO,
+ XTOPT_POINTER(struct ebt_802_3_info, type) },
+ XTOPT_TABLEEND,
};
static void br802_3_print_help(void)
@@ -36,52 +39,14 @@ static void br802_3_print_help(void)
" Type implies SAP value 0xaa\n");
}
-static int
-br802_3_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void br802_3_parse(struct xt_option_call *cb)
{
- struct ebt_802_3_info *info = (struct ebt_802_3_info *) (*match)->data;
- unsigned int i;
- char *end;
-
- switch (c) {
- case _802_3_SAP:
- if (invert)
- info->invflags |= EBT_802_3_SAP;
- i = strtoul(optarg, &end, 16);
- if (i > 255 || *end != '\0')
- xtables_error(PARAMETER_PROBLEM,
- "Problem with specified "
- "sap hex value, %x",i);
- info->sap = i; /* one byte, so no byte order worries */
- info->bitmask |= EBT_802_3_SAP;
- break;
- case _802_3_TYPE:
- if (invert)
- info->invflags |= EBT_802_3_TYPE;
- i = strtoul(optarg, &end, 16);
- if (i > 65535 || *end != '\0') {
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the specified "
- "type hex value, %x",i);
- }
- info->type = htons(i);
- info->bitmask |= EBT_802_3_TYPE;
- break;
- default:
- return 0;
- }
+ struct ebt_802_3_info *info = cb->data;
- *flags |= info->bitmask;
- return 1;
-}
-
-static void
-br802_3_final_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "You must specify proper arguments");
+ xtables_option_parse(cb);
+ info->bitmask |= cb->entry->id;
+ if (cb->invert)
+ info->invflags |= cb->entry->id;
}
static void br802_3_print(const void *ip, const struct xt_entry_match *match,
@@ -112,10 +77,9 @@ static struct xtables_match br802_3_match =
.size = XT_ALIGN(sizeof(struct ebt_802_3_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
.help = br802_3_print_help,
- .parse = br802_3_parse,
- .final_check = br802_3_final_check,
+ .x6_parse = br802_3_parse,
.print = br802_3_print,
- .extra_opts = br802_3_opts,
+ .x6_options = br802_3_opts,
};
void _init(void)
diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t
index a138f35d2c756..2e4945b388830 100644
--- a/extensions/libebt_802_3.t
+++ b/extensions/libebt_802_3.t
@@ -1,5 +1,7 @@
:INPUT,FORWARD,OUTPUT
--802_3-sap ! 0x0a -j CONTINUE;=;FAIL
--802_3-type 0x000a -j RETURN;=;FAIL
+-p Length --802_3-sap 0x0a -j CONTINUE;=;OK
-p Length --802_3-sap ! 0x0a -j CONTINUE;=;OK
-p Length --802_3-type 0x000a -j RETURN;=;OK
+-p Length --802_3-type ! 0x000a -j RETURN;=;OK
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 18/23] extensions: libebt_vlan: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (16 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 17/23] extensions: libebt_802_3: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 19/23] extensions: libebt_arp: " Phil Sutter
` (5 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_vlan.c | 102 +++++++++++++--------------------------
1 file changed, 34 insertions(+), 68 deletions(-)
diff --git a/extensions/libebt_vlan.c b/extensions/libebt_vlan.c
index fa697921068dc..7f5aa8cd474d6 100644
--- a/extensions/libebt_vlan.c
+++ b/extensions/libebt_vlan.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <ctype.h>
#include <xtables.h>
#include <netinet/if_ether.h>
@@ -18,29 +17,19 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define NAME_VLAN_ID "id"
-#define NAME_VLAN_PRIO "prio"
-#define NAME_VLAN_ENCAP "encap"
-
-#define VLAN_ID '1'
-#define VLAN_PRIO '2'
-#define VLAN_ENCAP '3'
-
-static const struct option brvlan_opts[] = {
- {"vlan-id" , required_argument, NULL, VLAN_ID},
- {"vlan-prio" , required_argument, NULL, VLAN_PRIO},
- {"vlan-encap", required_argument, NULL, VLAN_ENCAP},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brvlan_opts[] =
+{
+ { .name = "vlan-id", .id = EBT_VLAN_ID, .type = XTTYPE_UINT16,
+ .max = 4094, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_vlan_info, id) },
+ { .name = "vlan-prio", .id = EBT_VLAN_PRIO, .type = XTTYPE_UINT8,
+ .max = 7, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_vlan_info, prio) },
+ { .name = "vlan-encap", .id = EBT_VLAN_ENCAP, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
-/*
- * option inverse flags definition
- */
-#define OPT_VLAN_ID 0x01
-#define OPT_VLAN_PRIO 0x02
-#define OPT_VLAN_ENCAP 0x04
-#define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP)
-
static void brvlan_print_help(void)
{
printf(
@@ -50,57 +39,34 @@ static void brvlan_print_help(void)
"--vlan-encap [!] encap : Encapsulated frame protocol (hexadecimal or name)\n");
}
-static int
-brvlan_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brvlan_parse(struct xt_option_call *cb)
{
- struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) (*match)->data;
+ struct ebt_vlan_info *vlaninfo = cb->data;
struct xt_ethertypeent *ethent;
char *end;
- struct ebt_vlan_info local;
-
- switch (c) {
- case VLAN_ID:
- EBT_CHECK_OPTION(flags, OPT_VLAN_ID);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_ID;
- local.id = strtoul(optarg, &end, 10);
- if (local.id > 4094 || *end != '\0')
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-id range ('%s')", optarg);
- vlaninfo->id = local.id;
- vlaninfo->bitmask |= EBT_VLAN_ID;
- break;
- case VLAN_PRIO:
- EBT_CHECK_OPTION(flags, OPT_VLAN_PRIO);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_PRIO;
- local.prio = strtoul(optarg, &end, 10);
- if (local.prio >= 8 || *end != '\0')
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-prio range ('%s')", optarg);
- vlaninfo->prio = local.prio;
- vlaninfo->bitmask |= EBT_VLAN_PRIO;
- break;
- case VLAN_ENCAP:
- EBT_CHECK_OPTION(flags, OPT_VLAN_ENCAP);
- if (invert)
- vlaninfo->invflags |= EBT_VLAN_ENCAP;
- local.encap = strtoul(optarg, &end, 16);
+
+ xtables_option_parse(cb);
+
+ vlaninfo->bitmask |= cb->entry->id;
+ if (cb->invert)
+ vlaninfo->invflags |= cb->entry->id;
+
+ if (cb->entry->id == EBT_VLAN_ENCAP) {
+ vlaninfo->encap = strtoul(cb->arg, &end, 16);
if (*end != '\0') {
- ethent = xtables_getethertypebyname(optarg);
+ ethent = xtables_getethertypebyname(cb->arg);
if (ethent == NULL)
- xtables_error(PARAMETER_PROBLEM, "Unknown --vlan-encap value ('%s')", optarg);
- local.encap = ethent->e_ethertype;
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown --vlan-encap value ('%s')",
+ cb->arg);
+ vlaninfo->encap = ethent->e_ethertype;
}
- if (local.encap < ETH_ZLEN)
- xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-encap range ('%s')", optarg);
- vlaninfo->encap = htons(local.encap);
- vlaninfo->bitmask |= EBT_VLAN_ENCAP;
- break;
- default:
- return 0;
-
+ if (vlaninfo->encap < ETH_ZLEN)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid --vlan-encap range ('%s')",
+ cb->arg);
+ vlaninfo->encap = htons(vlaninfo->encap);
}
- return 1;
}
static void brvlan_print(const void *ip, const struct xt_entry_match *match,
@@ -144,10 +110,10 @@ static struct xtables_match brvlan_match = {
.size = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.help = brvlan_print_help,
- .parse = brvlan_parse,
+ .x6_parse = brvlan_parse,
.print = brvlan_print,
.xlate = brvlan_xlate,
- .extra_opts = brvlan_opts,
+ .x6_options = brvlan_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 19/23] extensions: libebt_arp: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (17 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 18/23] extensions: libebt_vlan: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 20/23] extensions: libxt_limit: Use guided option parser for NFPROTO_BRIDGE, too Phil Sutter
` (4 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_arp.c | 201 ++++++++++++++--------------------------
extensions/libebt_arp.t | 7 ++
2 files changed, 78 insertions(+), 130 deletions(-)
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index 63a953d4637da..b6d691d8c0b10 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -10,7 +10,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <netinet/ether.h>
@@ -20,26 +19,31 @@
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
-#define ARP_OPCODE '1'
-#define ARP_HTYPE '2'
-#define ARP_PTYPE '3'
-#define ARP_IP_S '4'
-#define ARP_IP_D '5'
-#define ARP_MAC_S '6'
-#define ARP_MAC_D '7'
-#define ARP_GRAT '8'
+/* values must correspond with EBT_ARP_* bit positions */
+enum {
+ O_OPCODE = 0,
+ O_HTYPE,
+ O_PTYPE,
+ O_SRC_IP,
+ O_DST_IP,
+ O_SRC_MAC,
+ O_DST_MAC,
+ O_GRAT,
+};
-static const struct option brarp_opts[] = {
- { "arp-opcode" , required_argument, 0, ARP_OPCODE },
- { "arp-op" , required_argument, 0, ARP_OPCODE },
- { "arp-htype" , required_argument, 0, ARP_HTYPE },
- { "arp-ptype" , required_argument, 0, ARP_PTYPE },
- { "arp-ip-src" , required_argument, 0, ARP_IP_S },
- { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
- { "arp-mac-src" , required_argument, 0, ARP_MAC_S },
- { "arp-mac-dst" , required_argument, 0, ARP_MAC_D },
- { "arp-gratuitous", no_argument, 0, ARP_GRAT },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brarp_opts[] = {
+#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
+ ENTRY("arp-opcode", O_OPCODE, XTTYPE_STRING),
+ ENTRY("arp-op", O_OPCODE, XTTYPE_STRING),
+ ENTRY("arp-htype", O_HTYPE, XTTYPE_STRING),
+ ENTRY("arp-ptype", O_PTYPE, XTTYPE_STRING),
+ ENTRY("arp-ip-src", O_SRC_IP, XTTYPE_HOSTMASK),
+ ENTRY("arp-ip-dst", O_DST_IP, XTTYPE_HOSTMASK),
+ ENTRY("arp-mac-src", O_SRC_MAC, XTTYPE_ETHERMACMASK),
+ ENTRY("arp-mac-dst", O_DST_MAC, XTTYPE_ETHERMACMASK),
+ ENTRY("arp-gratuitous", O_GRAT, XTTYPE_NONE),
+#undef ENTRY
+ XTOPT_TABLEEND
};
/* a few names */
@@ -78,137 +82,74 @@ static void brarp_print_help(void)
" protocol type string: see "XT_PATH_ETHERTYPES"\n");
}
-#define OPT_OPCODE 0x01
-#define OPT_HTYPE 0x02
-#define OPT_PTYPE 0x04
-#define OPT_IP_S 0x08
-#define OPT_IP_D 0x10
-#define OPT_MAC_S 0x20
-#define OPT_MAC_D 0x40
-#define OPT_GRAT 0x80
-
-static int
-brarp_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brarp_parse(struct xt_option_call *cb)
{
- struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
+ struct ebt_arp_info *arpinfo = cb->data;
+ struct xt_ethertypeent *ent;
long int i;
char *end;
- unsigned char *maddr;
- unsigned char *mmask;
- unsigned int ipnr;
- switch (c) {
- case ARP_OPCODE:
- EBT_CHECK_OPTION(flags, OPT_OPCODE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_OPCODE;
- i = strtol(optarg, &end, 10);
+
+ xtables_option_parse(cb);
+
+ arpinfo->bitmask |= 1 << cb->entry->id;
+ if (cb->invert)
+ arpinfo->invflags |= 1 << cb->entry->id;
+
+ switch (cb->entry->id) {
+ case O_OPCODE:
+ i = strtol(cb->arg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
- if (!strcasecmp(opcodes[i], optarg))
+ if (!strcasecmp(opcodes[i], cb->arg))
break;
if (i == ARRAY_SIZE(opcodes))
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP opcode");
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP opcode");
i++;
}
arpinfo->opcode = htons(i);
- arpinfo->bitmask |= EBT_ARP_OPCODE;
break;
-
- case ARP_HTYPE:
- EBT_CHECK_OPTION(flags, OPT_HTYPE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_HTYPE;
- i = strtol(optarg, &end, 10);
+ case O_HTYPE:
+ i = strtol(cb->arg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
- if (!strcasecmp("Ethernet", argv[optind - 1]))
+ if (!strcasecmp("Ethernet", cb->arg))
i = 1;
else
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP hardware type");
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP hardware type");
}
arpinfo->htype = htons(i);
- arpinfo->bitmask |= EBT_ARP_HTYPE;
break;
- case ARP_PTYPE: {
- uint16_t proto;
-
- EBT_CHECK_OPTION(flags, OPT_PTYPE);
- if (invert)
- arpinfo->invflags |= EBT_ARP_PTYPE;
-
- i = strtol(optarg, &end, 16);
- if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
- struct xt_ethertypeent *ent;
-
- ent = xtables_getethertypebyname(argv[optind - 1]);
- if (!ent)
- xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP "
- "protocol type");
- proto = ent->e_ethertype;
-
- } else
- proto = i;
- arpinfo->ptype = htons(proto);
- arpinfo->bitmask |= EBT_ARP_PTYPE;
- break;
- }
-
- case ARP_IP_S:
- case ARP_IP_D:
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- if (c == ARP_IP_S) {
- EBT_CHECK_OPTION(flags, OPT_IP_S);
- arpinfo->saddr = ipaddr->s_addr;
- arpinfo->smsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_SRC_IP;
- } else {
- EBT_CHECK_OPTION(flags, OPT_IP_D);
- arpinfo->daddr = ipaddr->s_addr;
- arpinfo->dmsk = ipmask.s_addr;
- arpinfo->bitmask |= EBT_ARP_DST_IP;
- }
- free(ipaddr);
- if (invert) {
- if (c == ARP_IP_S)
- arpinfo->invflags |= EBT_ARP_SRC_IP;
- else
- arpinfo->invflags |= EBT_ARP_DST_IP;
+ case O_PTYPE:
+ i = strtol(cb->arg, &end, 16);
+ if (i >= 0 && i < (0x1 << 16) && *end == '\0') {
+ arpinfo->ptype = htons(i);
+ break;
}
+ ent = xtables_getethertypebyname(cb->arg);
+ if (!ent)
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with specified ARP protocol type");
+ arpinfo->ptype = htons(ent->e_ethertype);
break;
- case ARP_MAC_S:
- case ARP_MAC_D:
- if (c == ARP_MAC_S) {
- EBT_CHECK_OPTION(flags, OPT_MAC_S);
- maddr = arpinfo->smaddr;
- mmask = arpinfo->smmsk;
- arpinfo->bitmask |= EBT_ARP_SRC_MAC;
- } else {
- EBT_CHECK_OPTION(flags, OPT_MAC_D);
- maddr = arpinfo->dmaddr;
- mmask = arpinfo->dmmsk;
- arpinfo->bitmask |= EBT_ARP_DST_MAC;
- }
- if (invert) {
- if (c == ARP_MAC_S)
- arpinfo->invflags |= EBT_ARP_SRC_MAC;
- else
- arpinfo->invflags |= EBT_ARP_DST_MAC;
- }
- if (xtables_parse_mac_and_mask(optarg, maddr, mmask))
- xtables_error(PARAMETER_PROBLEM, "Problem with ARP MAC address argument");
+ case O_SRC_IP:
+ arpinfo->saddr = cb->val.haddr.ip & cb->val.hmask.ip;
+ arpinfo->smsk = cb->val.hmask.ip;
+ break;
+ case O_DST_IP:
+ arpinfo->daddr = cb->val.haddr.ip & cb->val.hmask.ip;
+ arpinfo->dmsk = cb->val.hmask.ip;
+ break;
+ case O_SRC_MAC:
+ memcpy(arpinfo->smaddr, cb->val.ethermac, ETH_ALEN);
+ memcpy(arpinfo->smmsk, cb->val.ethermacmask, ETH_ALEN);
break;
- case ARP_GRAT:
- EBT_CHECK_OPTION(flags, OPT_GRAT);
- arpinfo->bitmask |= EBT_ARP_GRAT;
- if (invert)
- arpinfo->invflags |= EBT_ARP_GRAT;
+ case O_DST_MAC:
+ memcpy(arpinfo->dmaddr, cb->val.ethermac, ETH_ALEN);
+ memcpy(arpinfo->dmmsk, cb->val.ethermacmask, ETH_ALEN);
break;
- default:
- return 0;
}
- return 1;
}
static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric)
@@ -279,9 +220,9 @@ static struct xtables_match brarp_match = {
.size = XT_ALIGN(sizeof(struct ebt_arp_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_arp_info)),
.help = brarp_print_help,
- .parse = brarp_parse,
+ .x6_parse = brarp_parse,
.print = brarp_print,
- .extra_opts = brarp_opts,
+ .x6_options = brarp_opts,
};
void _init(void)
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
index 96fbce906107c..c8e874e83c513 100644
--- a/extensions/libebt_arp.t
+++ b/extensions/libebt_arp.t
@@ -1,7 +1,11 @@
:INPUT,FORWARD,OUTPUT
-p ARP --arp-op Request;=;OK
+-p ARP --arp-op ! Request;=;OK
+-p ARP --arp-htype Ethernet;-p ARP --arp-htype 1;OK
+-p ARP --arp-htype 1;=;OK
-p ARP --arp-htype ! 1;=;OK
-p ARP --arp-ptype 0x2;=;OK
+-p ARP --arp-ptype ! 0x2;=;OK
-p ARP --arp-ip-src 1.2.3.4;=;OK
-p ARP ! --arp-ip-dst 1.2.3.4;-p ARP --arp-ip-dst ! 1.2.3.4 -j CONTINUE;OK
-p ARP --arp-ip-src ! 0.0.0.0;=;OK
@@ -10,6 +14,9 @@
-p ARP --arp-ip-src ! 1.2.3.4/255.255.255.0;-p ARP --arp-ip-src ! 1.2.3.0/24;OK
-p ARP --arp-ip-src ! 1.2.3.4/255.0.255.255;-p ARP --arp-ip-src ! 1.0.3.4/255.0.255.255;OK
-p ARP --arp-mac-src 00:de:ad:be:ef:00;=;OK
+-p ARP --arp-mac-src ! 00:de:ad:be:ef:00;=;OK
-p ARP --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
+-p ARP --arp-mac-dst ! de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
-p ARP --arp-gratuitous;=;OK
+-p ARP ! --arp-gratuitous;=;OK
--arp-htype 1;=;FAIL
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 20/23] extensions: libxt_limit: Use guided option parser for NFPROTO_BRIDGE, too
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (18 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 19/23] extensions: libebt_arp: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 21/23] extensions: libebt_pkttype: Use guided option parser Phil Sutter
` (3 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libxt_limit.c | 50 ++--------------------------------------
1 file changed, 2 insertions(+), 48 deletions(-)
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index e6ec67f302688..63f3289d82c22 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -7,7 +7,6 @@
#define _DEFAULT_SOURCE 1
#define _ISOC99_SOURCE 1
#include <errno.h>
-#include <getopt.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -202,44 +201,6 @@ static int limit_xlate_eb(struct xt_xlate *xl,
return 1;
}
-#define FLAG_LIMIT 0x01
-#define FLAG_LIMIT_BURST 0x02
-#define ARG_LIMIT '1'
-#define ARG_LIMIT_BURST '2'
-
-static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
-{
- struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data;
- uintmax_t num;
-
- switch (c) {
- case ARG_LIMIT:
- EBT_CHECK_OPTION(flags, FLAG_LIMIT);
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --limit");
- if (!parse_rate(optarg, &r->avg))
- xtables_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- break;
- case ARG_LIMIT_BURST:
- EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST);
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --limit-burst");
- if (!xtables_strtoul(optarg, NULL, &num, 0, 10000))
- xtables_error(PARAMETER_PROBLEM,
- "bad --limit-burst `%s'", optarg);
- r->burst = num;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
static void brlimit_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
@@ -250,13 +211,6 @@ static void brlimit_print(const void *ip, const struct xt_entry_match *match,
printf(" --limit-burst %u ", r->burst);
}
-static const struct option brlimit_opts[] =
-{
- { .name = "limit", .has_arg = true, .val = ARG_LIMIT },
- { .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST },
- XT_GETOPT_TABLEEND,
-};
-
static struct xtables_match limit_match[] = {
{
.family = NFPROTO_UNSPEC,
@@ -280,9 +234,9 @@ static struct xtables_match limit_match[] = {
.userspacesize = offsetof(struct xt_rateinfo, prev),
.help = limit_help,
.init = limit_init,
- .parse = brlimit_parse,
+ .x6_parse = limit_parse,
.print = brlimit_print,
- .extra_opts = brlimit_opts,
+ .x6_options = limit_opts,
.xlate = limit_xlate_eb,
},
};
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 21/23] extensions: libebt_pkttype: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (19 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 20/23] extensions: libxt_limit: Use guided option parser for NFPROTO_BRIDGE, too Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 22/23] extensions: libebt_mark_m: " Phil Sutter
` (2 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Not much to gain here. Maybe implement number parsing with fallback to
get rid of that part from extension parsers?
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_pkttype.c | 45 +++++++++++++++++++------------------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/extensions/libebt_pkttype.c b/extensions/libebt_pkttype.c
index 4e2d19de7983b..b01b83a1f1f45 100644
--- a/extensions/libebt_pkttype.c
+++ b/extensions/libebt_pkttype.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/if_packet.h>
@@ -25,10 +24,14 @@ static const char *classes[] = {
"fastroute",
};
-static const struct option brpkttype_opts[] =
-{
- { "pkttype-type" , required_argument, 0, '1' },
- { 0 }
+enum {
+ O_TYPE,
+};
+
+static const struct xt_option_entry brpkttype_opts[] = {
+ { .name = "pkttype-type", .id = O_TYPE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
static void brpkttype_print_help(void)
@@ -40,37 +43,35 @@ static void brpkttype_print_help(void)
}
-static int brpkttype_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brpkttype_parse(struct xt_option_call *cb)
{
- struct ebt_pkttype_info *ptinfo = (struct ebt_pkttype_info *)(*match)->data;
- char *end;
+ struct ebt_pkttype_info *ptinfo = cb->data;
long int i;
+ char *end;
+
+ xtables_option_parse(cb);
- switch (c) {
- case '1':
- if (invert)
- ptinfo->invert = 1;
- i = strtol(optarg, &end, 16);
+ switch (cb->entry->id) {
+ case O_TYPE:
+ ptinfo->invert = cb->invert;
+ i = strtol(cb->arg, &end, 16);
if (*end != '\0') {
for (i = 0; i < ARRAY_SIZE(classes); i++) {
- if (!strcasecmp(optarg, classes[i]))
+ if (!strcasecmp(cb->arg, classes[i]))
break;
}
if (i >= ARRAY_SIZE(classes))
- xtables_error(PARAMETER_PROBLEM, "Could not parse class '%s'", optarg);
+ xtables_error(PARAMETER_PROBLEM,
+ "Could not parse class '%s'",
+ cb->arg);
}
if (i < 0 || i > 255)
xtables_error(PARAMETER_PROBLEM, "Problem with specified pkttype class");
ptinfo->pkt_type = (uint8_t)i;
break;
- default:
- return 0;
}
- return 1;
}
-
static void brpkttype_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data;
@@ -107,10 +108,10 @@ static struct xtables_match brpkttype_match = {
.size = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
.help = brpkttype_print_help,
- .parse = brpkttype_parse,
+ .x6_parse = brpkttype_parse,
.print = brpkttype_print,
.xlate = brpkttype_xlate,
- .extra_opts = brpkttype_opts,
+ .x6_options = brpkttype_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 22/23] extensions: libebt_mark_m: Use guided option parser
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (20 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 21/23] extensions: libebt_pkttype: Use guided option parser Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2023-12-20 16:06 ` [iptables PATCH 23/23] extensions: libxt_HMARK: Review HMARK_parse() Phil Sutter
2024-01-10 15:09 ` [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
Can't use XTTYPE_MARKMASK32 here because in 'val/mask', 'val' is
optional. Would have to extend xtopt_parse_markmask() to accept this,
maybe guarded by a new XTOPT_ flag to avoid unexpected changes in
behaviour?
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libebt_mark_m.c | 58 +++++++++++++++-----------------------
1 file changed, 22 insertions(+), 36 deletions(-)
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index 178c9ecef94da..f17fe99ab18ef 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -12,15 +12,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_mark_m.h>
-#define MARK '1'
+enum {
+ O_MARK = 0,
+};
-static const struct option brmark_m_opts[] = {
- { .name = "mark", .has_arg = true, .val = MARK },
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry brmark_m_opts[] = {
+ { .name = "mark", .id = O_MARK, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT | XTOPT_MAND },
+ XTOPT_TABLEEND,
};
static void brmark_m_print_help(void)
@@ -30,45 +32,30 @@ static void brmark_m_print_help(void)
"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
}
-#define OPT_MARK 0x01
-static int
-brmark_m_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brmark_m_parse(struct xt_option_call *cb)
{
- struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)
- (*match)->data;
+ struct ebt_mark_m_info *info = cb->data;
char *end;
- switch (c) {
- case MARK:
- if (invert)
- info->invert = 1;
- info->mark = strtoul(optarg, &end, 0);
+ xtables_option_parse(cb);
+
+ switch (cb->entry->id) {
+ case O_MARK:
+ info->invert = cb->invert;
+ info->mark = strtoul(cb->arg, &end, 0);
info->bitmask = EBT_MARK_AND;
if (*end == '/') {
- if (end == optarg)
+ if (end == cb->arg)
info->bitmask = EBT_MARK_OR;
info->mask = strtoul(end+1, &end, 0);
} else {
- info->mask = 0xffffffff;
+ info->mask = UINT32_MAX;
}
- if (*end != '\0' || end == optarg)
+ if (*end != '\0' || end == cb->arg)
xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
- optarg);
+ cb->arg);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
-}
-
-static void brmark_m_final_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "You must specify proper arguments");
}
static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
@@ -101,7 +88,7 @@ static int brmark_m_xlate(struct xt_xlate *xl,
if (info->bitmask == EBT_MARK_OR) {
xt_xlate_add(xl, "and 0x%x %s0 ", (uint32_t)info->mask,
info->invert ? "" : "!= ");
- } else if (info->mask != 0xffffffffU) {
+ } else if (info->mask != UINT32_MAX) {
xt_xlate_add(xl, "and 0x%x %s0x%x ", (uint32_t)info->mask,
op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
} else {
@@ -119,11 +106,10 @@ static struct xtables_match brmark_m_match = {
.size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.help = brmark_m_print_help,
- .parse = brmark_m_parse,
- .final_check = brmark_m_final_check,
+ .x6_parse = brmark_m_parse,
.print = brmark_m_print,
.xlate = brmark_m_xlate,
- .extra_opts = brmark_m_opts,
+ .x6_options = brmark_m_opts,
};
void _init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* [iptables PATCH 23/23] extensions: libxt_HMARK: Review HMARK_parse()
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (21 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 22/23] extensions: libebt_mark_m: " Phil Sutter
@ 2023-12-20 16:06 ` Phil Sutter
2024-01-10 15:09 ` [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2023-12-20 16:06 UTC (permalink / raw)
To: netfilter-devel
* With XTOPT_NBO support in UINT types, the manual byteorder conversion
calls are no longer needed
* Setting bits in cb->xflags is done by xtables_option_parse() already
* Since O_HMARK_* values match XT_HMARK_* ones, all but the O_HMARK_TYPE
case fold together into a single default one
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
extensions/libxt_HMARK.c | 60 ++++++----------------------------------
1 file changed, 9 insertions(+), 51 deletions(-)
diff --git a/extensions/libxt_HMARK.c b/extensions/libxt_HMARK.c
index 94aebe9af8353..83ce5003a1886 100644
--- a/extensions/libxt_HMARK.c
+++ b/extensions/libxt_HMARK.c
@@ -41,6 +41,7 @@ static void HMARK_help(void)
#define hi struct xt_hmark_info
+/* values must match XT_HMARK_* ones (apart from O_HMARK_TYPE) */
enum {
O_HMARK_SADDR_MASK,
O_HMARK_DADDR_MASK,
@@ -88,32 +89,32 @@ static const struct xt_option_entry HMARK_opts[] = {
{ .name = "hmark-sport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.p16.src)
},
{ .name = "hmark-dport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.p16.dst)
},
{ .name = "hmark-spi-mask",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI_MASK,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_mask.v32)
},
{ .name = "hmark-sport",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.p16.src)
},
{ .name = "hmark-dport",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.p16.dst)
},
{ .name = "hmark-spi",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI,
- .flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
+ .flags = XTOPT_PUT | XTOPT_NBO, XTOPT_POINTER(hi, port_set.v32)
},
{ .name = "hmark-proto-mask",
.type = XTTYPE_UINT16,
@@ -211,53 +212,10 @@ static void HMARK_parse(struct xt_option_call *cb, int plen)
case O_HMARK_TYPE:
hmark_parse_type(cb);
break;
- case O_HMARK_SADDR_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
- break;
- case O_HMARK_DADDR_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
- break;
- case O_HMARK_SPI:
- info->port_set.v32 = htonl(cb->val.u32);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI);
- break;
- case O_HMARK_SPORT:
- info->port_set.p16.src = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
- break;
- case O_HMARK_DPORT:
- info->port_set.p16.dst = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
- break;
- case O_HMARK_SPORT_MASK:
- info->port_mask.p16.src = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
- break;
- case O_HMARK_DPORT_MASK:
- info->port_mask.p16.dst = htons(cb->val.u16);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
- break;
- case O_HMARK_SPI_MASK:
- info->port_mask.v32 = htonl(cb->val.u32);
- info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
- break;
- case O_HMARK_PROTO_MASK:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
- break;
- case O_HMARK_RND:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
- break;
- case O_HMARK_MODULUS:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
- break;
- case O_HMARK_OFFSET:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
- break;
- case O_HMARK_CT:
- info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
+ default:
+ info->flags |= XT_HMARK_FLAG(cb->entry->id);
break;
}
- cb->xflags |= (1 << cb->entry->id);
}
static void HMARK_ip4_parse(struct xt_option_call *cb)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread* Re: [iptables PATCH 00/23] Guided option parser for ebtables
2023-12-20 16:06 [iptables PATCH 00/23] Guided option parser for ebtables Phil Sutter
` (22 preceding siblings ...)
2023-12-20 16:06 ` [iptables PATCH 23/23] extensions: libxt_HMARK: Review HMARK_parse() Phil Sutter
@ 2024-01-10 15:09 ` Phil Sutter
23 siblings, 0 replies; 31+ messages in thread
From: Phil Sutter @ 2024-01-10 15:09 UTC (permalink / raw)
To: netfilter-devel; +Cc: Jan Engelhardt
On Wed, Dec 20, 2023 at 05:06:13PM +0100, Phil Sutter wrote:
> The first part of this series deals with guided option parser itself,
> fixing a bug in patch 1 and adding features in patches 2-4 in
> preparation for ebtables' guided option parser support enabled in patch
> 5. The remaining patches then convert ebtables extensions apart from the
> last one which significantly reduces parser code in libxt_HMARK.c using
> the new parser features.
>
> Phil Sutter (23):
[...]
> 27 files changed, 757 insertions(+), 1305 deletions(-)
Series applied after fixing up the variable type in patch 2.
^ permalink raw reply [flat|nested] 31+ messages in thread