All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.