#include "nft-bridge.h"
#include "nft.h"
+void ebt_cs_clean(struct ebtables_command_state *cs)
+{
+ struct ebt_match *m, *nm;
+
+ xtables_rule_matches_free(&cs->matches);
+
+ for (m = cs->match_list; m;) {
+ nm = m->next;
+ if (!m->ismatch)
+ free(m->u.watcher->t);
+ free(m);
+ m = nm;
+ }
+}
+
/* 0: default, print only 2 digits if necessary
* 2: always print 2 digits, a printed mac address
* then always has the same length
static int nft_bridge_add(struct nft_rule *r, void *data)
{
struct ebtables_command_state *cs = data;
- struct xtables_rule_match *matchp;
+ struct ebt_match *iter;
struct ebt_entry *fw = &cs->fw;
uint32_t op;
char *addr;
add_compat(r, fw->ethproto, fw->invflags);
- for (matchp = cs->matches; matchp; matchp = matchp->next) {
- if (add_match(r, matchp->match->m) < 0)
- break;
+ for (iter = cs->match_list; iter; iter = iter->next) {
+ if (iter->ismatch) {
+ if (add_match(r, iter->u.match->m))
+ break;
+ } else {
+ if (add_target(r, iter->u.watcher->t))
+ break;
+ }
}
if (add_counters(r, cs->counters.pcnt, cs->counters.bcnt) < 0)
cs->jumpto = jumpto;
}
+static void parse_watcher(void *object, struct ebt_match **match_list,
+ bool ismatch)
+{
+ struct ebt_match *m;
+
+ m = calloc(1, sizeof(struct ebt_match));
+ if (m == NULL)
+ xtables_error(OTHER_PROBLEM, "Can't allocate memory");
+
+ if (ismatch)
+ m->u.match = object;
+ else
+ m->u.watcher = object;
+
+ m->ismatch = ismatch;
+ if (*match_list == NULL)
+ *match_list = m;
+ else
+ (*match_list)->next = m;
+}
+
+static void nft_bridge_parse_match(struct xtables_match *m, void *data)
+{
+ struct ebtables_command_state *cs = data;
+
+ parse_watcher(m, &cs->match_list, true);
+}
+
static void nft_bridge_parse_target(struct xtables_target *t, void *data)
{
struct ebtables_command_state *cs = data;
+ /* harcoded names :-( */
+ if (strcmp(t->name, "log") == 0) {
+ parse_watcher(t, &cs->match_list, false);
+ return;
+ }
+
cs->target = t;
}
static void nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
unsigned int format)
{
- struct xtables_rule_match *matchp;
+ struct xtables_match *matchp;
+ struct xtables_target *watcherp;
+ struct ebt_match *m;
struct ebtables_command_state cs = {};
char *addr;
print_iface(cs.fw.out);
}
- for (matchp = cs.matches; matchp; matchp = matchp->next) {
- if (matchp->match->print != NULL) {
- matchp->match->print(&cs.fw, matchp->match->m,
- format & FMT_NUMERIC);
+ for (m = cs.match_list; m; m = m->next) {
+ if (m->ismatch) {
+ matchp = m->u.match;
+ if (matchp->print != NULL) {
+ matchp->print(&cs.fw, matchp->m,
+ format & FMT_NUMERIC);
+ }
+ } else {
+ watcherp = m->u.watcher;
+ if (watcherp->print != NULL) {
+ watcherp->print(&cs.fw, watcherp->t,
+ format & FMT_NUMERIC);
+ }
}
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
+
+ ebt_cs_clean(&cs);
}
static bool nft_bridge_is_same(const void *data_a, const void *data_b)
.parse_meta = nft_bridge_parse_meta,
.parse_payload = nft_bridge_parse_payload,
.parse_immediate = nft_bridge_parse_immediate,
+ .parse_match = nft_bridge_parse_match,
.parse_target = nft_bridge_parse_target,
.print_table_header = nft_bridge_print_table_header,
.print_header = nft_bridge_print_header,
xtables_error(OTHER_PROBLEM, "Can't alloc memory");
}
-static void ebt_load_matches(void)
+static void ebt_load_watcher(const char *name)
+{
+ struct xtables_target *watcher;
+ size_t size;
+
+ watcher = xtables_find_target(name, XTF_LOAD_MUST_SUCCEED);
+ if (!watcher)
+ xtables_error(OTHER_PROBLEM,
+ "Unable to load %s watcher", name);
+
+ size = XT_ALIGN(sizeof(struct xt_entry_target)) + watcher->size;
+
+ watcher->t = xtables_calloc(1, size);
+ watcher->t->u.target_size = size;
+ strncpy(watcher->t->u.user.name, name,
+ sizeof(watcher->t->u.user.name));
+ watcher->t->u.user.name[sizeof(watcher->t->u.user.name)-1] = '\0';
+ watcher->t->u.user.revision = watcher->revision;
+
+ xs_init_target(watcher);
+
+ opts = merge_options(opts, watcher->extra_opts,
+ &watcher->option_offset);
+ if (opts == NULL)
+ xtables_error(OTHER_PROBLEM, "Can't alloc memory");
+}
+
+static void ebt_load_match_extensions(void)
{
opts = ebt_original_options;
ebt_load_match("802_3");
ebt_load_match("ip");
ebt_load_match("mark_m");
+
+ ebt_load_watcher("log");
}
static void ebt_add_match(struct xtables_match *m,
- struct xtables_rule_match **rule_matches)
+ struct ebtables_command_state *cs)
{
- struct xtables_rule_match *i;
+ struct xtables_rule_match *i, **rule_matches = &cs->matches;
struct xtables_match *newm;
+ struct ebt_match *newnode;
/* match already in rule_matches, skip inclusion */
for (i = *rule_matches; i; i = i->next) {
"Unable to add match %s", m->name);
newm->mflags = m->mflags;
+
+ /* glue code for watchers */
+ newnode = calloc(1, sizeof(struct ebt_match));
+ if (newnode == NULL)
+ xtables_error(OTHER_PROBLEM, "Unable to alloc memory");
+
+ newnode->ismatch = true;
+ newnode->u.match = newm;
+
+ if (cs->match_list == NULL)
+ cs->match_list = newnode;
+ else
+ cs->match_list->next = newnode;
+}
+
+static void ebt_add_watcher(struct xtables_target *watcher,
+ struct ebtables_command_state *cs)
+{
+ struct ebt_match *i, *newnode;
+
+ for (i = cs->match_list; i; i = i->next) {
+ if (i->ismatch)
+ continue;
+ if (strcmp(i->u.watcher->name, watcher->name) == 0) {
+ i->u.watcher->tflags |= watcher->tflags;
+ return;
+ }
+ }
+
+ newnode = calloc(1, sizeof(struct ebt_match));
+ if (newnode == NULL)
+ xtables_error(OTHER_PROBLEM, "Unable to alloc memory");
+
+ newnode->u.watcher = watcher;
+
+ if (cs->match_list == NULL)
+ cs->match_list = newnode;
+ else
+ cs->match_list->next = newnode;
}
/* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
int rule_nr_end = 0;
int ret = 0;
unsigned int flags = 0;
- struct xtables_target *t;
+ struct xtables_target *t, *w;
struct xtables_match *m;
struct ebtables_command_state cs;
char command = 'h';
int exec_style = EXEC_STYLE_PRG;
int selected_chain = -1;
struct xtables_rule_match *xtrm_i;
+ struct ebt_match *match;
memset(&cs, 0, sizeof(cs));
cs.argv = argv;
* don't use '-m matchname' and the match can't loaded dinamically when
* the user calls it.
*/
- ebt_load_matches();
+ ebt_load_match_extensions();
/* clear mflags in case do_commandeb gets called a second time
* (we clear the global list of all matches for security)*/
/* Is it a match_option? */
for (m = xtables_matches; m; m = m->next) {
if (m->parse(c - m->option_offset, argv, ebt_invert, &m->mflags, NULL, &m->m)) {
- ebt_add_match(m, &cs.matches);
+ ebt_add_match(m, &cs);
goto check_extension;
}
}
/* Is it a watcher option? */
- /*for (w = ebt_watchers; w; w = w->next)
- if (w->parse(c - w->option_offset, argv, argc, new_entry, &w->flags, &w->w))
- break;
-
+ for (w = xtables_targets; w; w = w->next) {
+ if (w->parse(c - w->option_offset, argv,
+ ebt_invert, &w->tflags,
+ NULL, &w->t)) {
+ ebt_add_watcher(w, &cs);
+ goto check_extension;
+ }
+ }
+ /*
if (w == NULL && c == '?')
ebt_print_error2("Unknown argument: '%s'", argv[optind - 1], (char)optopt, (char)c);
else if (w == NULL) {
for (xtrm_i = cs.matches; xtrm_i; xtrm_i = xtrm_i->next)
xtables_option_mfcall(xtrm_i->match);
+ for (match = cs.match_list; match; match = match->next) {
+ if (match->ismatch)
+ continue;
+
+ xtables_option_tfcall(match->u.watcher);
+ }
+
if (cs.target != NULL)
xtables_option_tfcall(cs.target);
}
if (replace->nentries)
ebt_deliver_counters(replace);*/
+
+ ebt_cs_clean(&cs);
return ret;
}