summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-10-07 22:23:59 +0200
committerPhil Sutter <phil@nwl.cc>2024-01-10 16:07:31 +0100
commit24bb57d3f52ac1ae87f92ba567032bda9a749c62 (patch)
tree416f52e534484f60580e2fb5544a117c6390c09b
parent955654c4fc34cf3ff4e64d3340c124b17605ae34 (diff)
ebtables: Support for guided option parser
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.
-rw-r--r--iptables/xtables-eb.c108
1 files changed, 51 insertions, 57 deletions
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index c3cf1c2c..e8cdd7ea 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\" "