netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support
@ 2015-02-09 12:16 Arturo Borrero Gonzalez
  2015-02-09 12:16 ` [ebtables-compat PATCH 2/2] ebtables-compat: add log watcher extension Arturo Borrero Gonzalez
  2015-02-11 15:16 ` [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Pablo Neira Ayuso
  0 siblings, 2 replies; 3+ messages in thread
From: Arturo Borrero Gonzalez @ 2015-02-09 12:16 UTC (permalink / raw)
  To: netfilter-devel; +Cc: giuseppelng, pablo

ebtables watchers are targets which always return EBT_CONTINUE.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 iptables/nft-bridge.c |   86 ++++++++++++++++++++++++++++++++++++-----
 iptables/nft-bridge.h |   13 ++++++
 iptables/nft-shared.c |    5 ++
 iptables/nft-shared.h |    1 
 iptables/xtables-eb.c |  104 ++++++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 190 insertions(+), 19 deletions(-)

diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 62aab04..4392d28 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -22,6 +22,21 @@
 #include "nft-bridge.h"
 #include "nft.h"
 
+void ebt_cs_clean(struct ebtables_command_state *cs)
+{
+	struct 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
@@ -139,7 +154,7 @@ static int _add_action(struct nft_rule *r, struct ebtables_command_state *cs)
 static int nft_bridge_add(struct nft_rule *r, void *data)
 {
 	struct ebtables_command_state *cs = data;
-	struct xtables_rule_match *matchp;
+	struct match *iter;
 	struct ebt_entry *fw = &cs->fw;
 	uint32_t op;
 	char *addr;
@@ -189,9 +204,14 @@ static int nft_bridge_add(struct nft_rule *r, void *data)
 
 	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)
@@ -296,10 +316,44 @@ static void nft_bridge_parse_immediate(const char *jumpto, bool nft_goto,
 	cs->jumpto = jumpto;
 }
 
+static void parse_watcher(void *object, struct match **match_list,
+			  bool ismatch)
+{
+	struct match *m;
+
+	m = calloc(1, sizeof(struct 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;
 }
 
@@ -382,7 +436,9 @@ static void nft_bridge_print_header(unsigned int format, const char *chain,
 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 match *m;
 	struct ebtables_command_state cs = {};
 	char *addr;
 
@@ -456,10 +512,19 @@ static void nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
 		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);
+			}
 		}
 	}
 
@@ -476,6 +541,8 @@ static void nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
 
 	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)
@@ -567,6 +634,7 @@ struct nft_family_ops nft_family_ops_bridge = {
 	.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,
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
index cd63c11..8dc6c9a 100644
--- a/iptables/nft-bridge.h
+++ b/iptables/nft-bridge.h
@@ -93,10 +93,21 @@ struct ebt_entry {
 	unsigned char out_mask[IFNAMSIZ];
 };
 
+/* trick for ebtables-compat, since watchers are targets */
+struct match {
+	struct match				*next;
+	union {
+		struct xtables_match		*match;
+		struct xtables_target		*watcher;
+	} u;
+	bool					ismatch;
+};
+
 struct ebtables_command_state {
 	struct ebt_entry fw;
 	struct xtables_target *target;
 	struct xtables_rule_match *matches;
+	struct match *match_list;
 	const char *jumpto;
 	struct xt_counters counters;
 	int invert;
@@ -155,4 +166,6 @@ static inline const char *ebt_target_name(unsigned int verdict)
 	*flags |= mask;						\
 })								\
 
+void ebt_cs_clean(struct ebtables_command_state *cs);
+
 #endif
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 76984e8..620da3e 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -328,6 +328,7 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
 	struct xtables_match *match;
 	struct xtables_rule_match **matches;
 	struct xt_entry_match *m;
+	struct nft_family_ops *ops;
 
 	switch (ctx->family) {
 	case NFPROTO_IPV4:
@@ -359,6 +360,10 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
 	strcpy(m->u.user.name, match->name);
 
 	match->m = m;
+
+	ops = nft_family_ops_lookup(ctx->family);
+	if (ops->parse_match != NULL)
+		ops->parse_match(match, nft_get_data(ctx));
 }
 
 void print_proto(uint16_t proto, int invert)
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 33582aa..fbce5b5 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -97,6 +97,7 @@ struct nft_family_ops {
 			    struct xtables_args *args);
 	void (*post_parse)(int command, struct iptables_command_state *cs,
 			   struct xtables_args *args);
+	void (*parse_match)(struct xtables_match *m, void *data);
 	void (*parse_target)(struct xtables_target *t, void *data);
 	bool (*rule_find)(struct nft_family_ops *ops, struct nft_rule *r,
 			  void *data);
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index db1717c..7f3c1e6 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -610,19 +610,49 @@ static void ebt_load_match(const char *name)
 		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 match *newnode;
 
 	/* match already in rule_matches, skip inclusion */
 	for (i = *rule_matches; i; i = i->next) {
@@ -638,6 +668,45 @@ static void ebt_add_match(struct xtables_match *m,
 			      "Unable to add match %s", m->name);
 
 	newm->mflags = m->mflags;
+
+	/* glue code for watchers */
+	newnode = calloc(1, sizeof(struct 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 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 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. */
@@ -651,7 +720,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
 	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';
@@ -660,6 +729,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
 	int exec_style = EXEC_STYLE_PRG;
 	int selected_chain = -1;
 	struct xtables_rule_match *xtrm_i;
+	struct match *miter;
 
 	memset(&cs, 0, sizeof(cs));
 	cs.argv = argv;
@@ -676,7 +746,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
 	 * 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)*/
@@ -1164,16 +1234,21 @@ big_iface_length:
 			/* 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) {
@@ -1216,6 +1291,13 @@ check_extension:
 		for (xtrm_i = cs.matches; xtrm_i; xtrm_i = xtrm_i->next)
 			xtables_option_mfcall(xtrm_i->match);
 
+		for (miter = cs.match_list; miter; miter = miter->next) {
+			if (miter->ismatch)
+				continue;
+
+			xtables_option_tfcall(miter->u.watcher);
+		}
+
 		if (cs.target != NULL)
 			xtables_option_tfcall(cs.target);
 	}
@@ -1278,5 +1360,7 @@ check_extension:
 
 		if (replace->nentries)
 			ebt_deliver_counters(replace);*/
+
+	ebt_cs_clean(&cs);
 	return ret;
 }


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [ebtables-compat PATCH 2/2] ebtables-compat: add log watcher extension
  2015-02-09 12:16 [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Arturo Borrero Gonzalez
@ 2015-02-09 12:16 ` Arturo Borrero Gonzalez
  2015-02-11 15:16 ` [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Arturo Borrero Gonzalez @ 2015-02-09 12:16 UTC (permalink / raw)
  To: netfilter-devel; +Cc: giuseppelng, pablo

This patch adds the log 'watcher' extension.

The work was started by Giuseppe Longo <giuseppelng@gmail.com> and finised
by me.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 extensions/libebt_log.c |  197 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 197 insertions(+)
 create mode 100644 extensions/libebt_log.c

diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
new file mode 100644
index 0000000..0799185
--- /dev/null
+++ b/extensions/libebt_log.c
@@ -0,0 +1,197 @@
+/*
+ * Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the
+ * xtables-compat environment in 2015.
+ *
+ */
+
+#include <stdio.h>
+#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'
+
+typedef struct _code {
+	char *c_name;
+	int c_val;
+} CODE;
+
+static CODE eight_priority[] = {
+	{ "emerg", LOG_EMERG },
+	{ "alert", LOG_ALERT },
+	{ "crit", LOG_CRIT },
+	{ "error", LOG_ERR },
+	{ "warning", LOG_WARNING },
+	{ "notice", LOG_NOTICE },
+	{ "info", LOG_INFO },
+	{ "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;
+}
+
+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 void brlog_help(void)
+{
+	int i;
+
+	printf(
+"log options:\n"
+"--log               : use this if you're not specifying anything\n"
+"--log-level level   : level = [1-8] or a string\n"
+"--log-prefix prefix : max. %d chars.\n"
+"--log-ip            : put ip info. in the log for ip packets\n"
+"--log-arp           : put (r)arp info. in the log for (r)arp packets\n"
+"--log-ip6           : put ip6 info. in the log for ip6 packets\n"
+	, EBT_LOG_PREFIX_SIZE - 1);
+	for (i = 0; i < 8; i++)
+		printf("%d = %s\n", eight_priority[i].c_val,
+				    eight_priority[i].c_name);
+}
+
+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 int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
+		       const void *entry, struct xt_entry_target **target)
+{
+	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);
+		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:
+		if (invert)
+			xtables_error(PARAMETER_PROBLEM,
+				      "Unexpected `!' after --log-ip");
+		loginfo->bitmask |= EBT_LOG_IP;
+		break;
+	case LOG_ARP:
+		if (invert)
+			xtables_error(PARAMETER_PROBLEM,
+				      "Unexpected `!' after --log-arp");
+		loginfo->bitmask |= EBT_LOG_ARP;
+	case LOG_LOG:
+		if (invert)
+			xtables_error(PARAMETER_PROBLEM,
+				      "Unexpected `!' after --log");
+		break;
+	case LOG_IP6:
+		if (invert)
+			xtables_error(PARAMETER_PROBLEM,
+				      "Unexpected `!' after --log-ip6");
+		loginfo->bitmask |= EBT_LOG_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,
+			int numeric)
+{
+	struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
+
+	printf("--log-level %s --log-prefix \"%s\"",
+		eight_priority[loginfo->loglevel].c_name,
+		loginfo->prefix);
+
+	if (loginfo->bitmask & EBT_LOG_IP)
+		printf(" --log-ip");
+	if (loginfo->bitmask & EBT_LOG_ARP)
+		printf(" --log-arp");
+	if (loginfo->bitmask & EBT_LOG_IP6)
+		printf(" --log-ip6");
+	printf(" ");
+}
+
+static struct xtables_target brlog_target = {
+	.name		= "log",
+	.revision	= 0,
+	.version	= XTABLES_VERSION,
+	.family		= NFPROTO_BRIDGE,
+	.size		= XT_ALIGN(sizeof(struct ebt_log_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct ebt_log_info)),
+	.init		= brlog_init,
+	.help		= brlog_help,
+	.parse		= brlog_parse,
+	.final_check	= brlog_final_check,
+	.print		= brlog_print,
+	.extra_opts	= brlog_opts,
+};
+
+void _init(void)
+{
+	xtables_register_target(&brlog_target);
+}


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support
  2015-02-09 12:16 [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Arturo Borrero Gonzalez
  2015-02-09 12:16 ` [ebtables-compat PATCH 2/2] ebtables-compat: add log watcher extension Arturo Borrero Gonzalez
@ 2015-02-11 15:16 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2015-02-11 15:16 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, giuseppelng

On Mon, Feb 09, 2015 at 01:16:12PM +0100, Arturo Borrero Gonzalez wrote:
> ebtables watchers are targets which always return EBT_CONTINUE.

Patch 1/2 and 2/2 applied, thanks.

I'm going to merge the ebtables-compat branch to master, so we can
include this in the next release.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-02-11 15:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-09 12:16 [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Arturo Borrero Gonzalez
2015-02-09 12:16 ` [ebtables-compat PATCH 2/2] ebtables-compat: add log watcher extension Arturo Borrero Gonzalez
2015-02-11 15:16 ` [ebtables-compat PATCH 1/2] ebtables-compat: add watchers support Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).