All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] conntrack: minor cleanup
@ 2013-09-03 15:28 Florian Westphal
  2013-09-03 15:28 ` [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar Florian Westphal
  2013-09-03 15:28 ` [PATCH 3/3] conntrack: allow adding/deleting labels from conntrack entries Florian Westphal
  0 siblings, 2 replies; 4+ messages in thread
From: Florian Westphal @ 2013-09-03 15:28 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Rename get_table to generic "optional argument handling" helper,
so it can be re-used in upcoming patch.

While at it, avoid copy&paste of "labelmap" handling.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/conntrack.c |   41 +++++++++++++++++++----------------------
 1 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index 7d2a365..2567c08 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -890,20 +890,20 @@ add_command(unsigned int *cmd, const int newcmd)
 	*cmd |= newcmd;
 }
 
-static char *get_table(int argc, char *argv[])
+static char *get_optional_arg(int argc, char *argv[])
 {
-	char *table = NULL;
+	char *arg = NULL;
 
 	/* Nasty bug or feature in getopt_long ?
 	 * It seems that it behaves badly with optional arguments.
 	 * Fortunately, I just stole the fix from iptables ;) */
 	if (optarg)
-		return 0;
+		return arg;
 	else if (optind < argc && argv[optind][0] != '-' &&
 		 argv[optind][0] != '!')
-		table = argv[optind++];
+		arg = argv[optind++];
 
-	return table;
+	return arg;
 }
 
 enum {
@@ -915,7 +915,7 @@ enum {
 
 static unsigned int check_type(int argc, char *argv[])
 {
-	const char *table = get_table(argc, argv);
+	const char *table = get_optional_arg(argc, argv);
 
 	/* default to conntrack subsystem if nothing has been specified. */
 	if (table == NULL)
@@ -1818,6 +1818,15 @@ static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data)
 
 static struct ctproto_handler *h;
 
+static void labelmap_init(void)
+{
+	if (labelmap)
+		return;
+	labelmap = nfct_labelmap_new(NULL);
+	if (!labelmap)
+		perror("nfct_labelmap_new");
+}
+
 int main(int argc, char *argv[])
 {
 	int c, cmd;
@@ -1970,12 +1979,8 @@ int main(int argc, char *argv[])
 		case 'o':
 			options |= CT_OPT_OUTPUT;
 			parse_parameter(optarg, &output_mask, PARSE_OUTPUT);
-			if (output_mask & _O_CL) {
-				if (!labelmap)
-					labelmap = nfct_labelmap_new(NULL);
-				if (!labelmap)
-					perror("nfct_labelmap_new");
-			}
+			if (output_mask & _O_CL)
+				labelmap_init();
 			break;
 		case 'z':
 			options |= CT_OPT_ZERO;
@@ -1987,12 +1992,7 @@ int main(int argc, char *argv[])
 
 			options |= opt2type[c];
 
-			if (optarg)
-				continue;
-			else if (optind < argc && argv[optind][0] != '-'
-				 && argv[optind][0] != '!')
-				tmp = argv[optind++];
-
+			tmp = get_optional_arg(argc, argv);
 			if (tmp == NULL)
 				continue;
 
@@ -2023,10 +2023,7 @@ int main(int argc, char *argv[])
 			options |= opt2type[c];
 			char *optarg2 = strdup(optarg);
 
-			if (!labelmap)
-				labelmap = nfct_labelmap_new(NULL);
-			if (!labelmap)
-				exit_error(OTHER_PROBLEM, "unable to open labelmap file");
+			labelmap_init();
 
 			unsigned int max = parse_label_get_max(optarg);
 			struct nfct_bitmask * b = nfct_bitmask_new(max);
-- 
1.7.8.6


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

* [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar
  2013-09-03 15:28 [PATCH 1/3] conntrack: minor cleanup Florian Westphal
@ 2013-09-03 15:28 ` Florian Westphal
  2013-09-03 21:11   ` Pablo Neira Ayuso
  2013-09-03 15:28 ` [PATCH 3/3] conntrack: allow adding/deleting labels from conntrack entries Florian Westphal
  1 sibling, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2013-09-03 15:28 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Its more straightforward to use -l foo -l bar when only wanting
to see conntracks that have both labels set.

It also simplifies things a lot.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 conntrack.8     |    7 ++--
 src/conntrack.c |  106 ++++++++++++++++++++++++------------------------------
 2 files changed, 51 insertions(+), 62 deletions(-)

diff --git a/conntrack.8 b/conntrack.8
index f273434..6410e5b 100644
--- a/conntrack.8
+++ b/conntrack.8
@@ -144,10 +144,11 @@ the MARK value into the ctmark.
 Otherwise, the mask is logically ANDed with the existing mark before the comparision.
 In "--create" mode, the mask is ignored.
 .TP
-.BI "-l, --label " "LABEL,..."
-Specify the conntrack labels.
+.BI "-l, --label " "LABEL"
+Specify a conntrack label.
 This option is only available in conjunction with "-L, --dump" or "-E, --event".
-Match entries whose labels matches at least those specified as arguments.
+Match entries whose labels match at least those specified.
+Use multiple -l commands to specify multiple labels that need to be set.
 .TP
 .BI "-c, --secmark " "SECMARK"
 Specify the conntrack selinux security mark.
diff --git a/src/conntrack.c b/src/conntrack.c
index 2567c08..4548169 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -829,59 +829,6 @@ parse_u32_mask(const char *arg, struct u32_mask *m)
 		m->mask = ~0;
 }
 
-static int
-get_label(char *name)
-{
-	int bit = nfct_labelmap_get_bit(labelmap, name);
-	if (bit < 0)
-		exit_error(PARAMETER_PROBLEM, "unknown label '%s'", name);
-	return bit;
-}
-
-static void
-set_label(struct nfct_bitmask *b, char *name)
-{
-	int bit = get_label(name);
-	nfct_bitmask_set_bit(b, bit);
-}
-
-static unsigned int
-set_max_label(char *name, unsigned int current_max)
-{
-	int bit = get_label(name);
-	if ((unsigned int) bit > current_max)
-		return (unsigned int) bit;
-	return current_max;
-}
-
-static unsigned int
-parse_label_get_max(char *arg)
-{
-	unsigned int max = 0;
-	char *parse;
-
-	while ((parse = strchr(arg, ',')) != NULL) {
-		parse[0] = '\0';
-		max = set_max_label(arg, max);
-		arg = &parse[1];
-	}
-
-	max = set_max_label(arg, max);
-	return max;
-}
-
-static void
-parse_label(struct nfct_bitmask *b, char *arg)
-{
-	char * parse;
-	while ((parse = strchr(arg, ',')) != NULL) {
-		parse[0] = '\0';
-		set_label(b, arg);
-		arg = &parse[1];
-	}
-	set_label(b, arg);
-}
-
 static void
 add_command(unsigned int *cmd, const int newcmd)
 {
@@ -1827,6 +1774,49 @@ static void labelmap_init(void)
 		perror("nfct_labelmap_new");
 }
 
+static void merge_bitmasks(struct nfct_bitmask **current,
+			  struct nfct_bitmask *src)
+{
+	unsigned int i;
+
+	if (*current == NULL) {
+		*current = src;
+		return;
+	}
+
+	/* "current" must be the larger bitmask object */
+	if (nfct_bitmask_maxbit(src) > nfct_bitmask_maxbit(*current)) {
+		struct nfct_bitmask *tmp = *current;
+		*current = src;
+		src = tmp;
+	}
+
+	for (i = 0; i <= nfct_bitmask_maxbit(src); i++) {
+		if (nfct_bitmask_test_bit(src, i))
+			nfct_bitmask_set_bit(*current, i);
+		nfct_bitmask_destroy(src);
+		return;
+	}
+
+	nfct_bitmask_destroy(src);
+}
+
+static struct nfct_bitmask *name_to_bitmask(const char *name)
+{
+	int bit;
+	struct nfct_bitmask *b;
+
+	bit = nfct_labelmap_get_bit(labelmap, name);
+	if (bit < 0)
+		exit_error(PARAMETER_PROBLEM, "unknown label '%s'", name);
+
+	b = nfct_bitmask_new(bit);
+	if (!b)
+		exit_error(OTHER_PROBLEM, "out of memory");
+	nfct_bitmask_set_bit(b, bit);
+	return b;
+}
+
 int main(int argc, char *argv[])
 {
 	int c, cmd;
@@ -2021,16 +2011,14 @@ int main(int argc, char *argv[])
 			break;
 		case 'l':
 			options |= opt2type[c];
-			char *optarg2 = strdup(optarg);
 
 			labelmap_init();
 
-			unsigned int max = parse_label_get_max(optarg);
-			struct nfct_bitmask * b = nfct_bitmask_new(max);
+			struct nfct_bitmask *b;
+			b = name_to_bitmask(optarg);
+			/* join "-l foo -l bar" into single bitmask object */
+			merge_bitmasks(&tmpl.label, b);
 
-			parse_label(b, optarg2);
-			tmpl.label = b;
-			free(optarg2);
 			break;
 		case 'a':
 			fprintf(stderr, "WARNING: ignoring -%c, "
-- 
1.7.8.6


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

* [PATCH 3/3] conntrack: allow adding/deleting labels from conntrack entries
  2013-09-03 15:28 [PATCH 1/3] conntrack: minor cleanup Florian Westphal
  2013-09-03 15:28 ` [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar Florian Westphal
@ 2013-09-03 15:28 ` Florian Westphal
  1 sibling, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2013-09-03 15:28 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Clemence Faure, Florian Westphal

From: Clemence Faure <clemence.faure@sophos.com>

new options "--label-add" and "--label-delete" to alter connlabels
assigned to a connection.

Signed-off-by: Clemence Faure <clemence.faure@sophos.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 conntrack.8         |   10 +++-
 include/conntrack.h |    2 +-
 src/conntrack.c     |  152 ++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 137 insertions(+), 27 deletions(-)

diff --git a/conntrack.8 b/conntrack.8
index 6410e5b..6910fc9 100644
--- a/conntrack.8
+++ b/conntrack.8
@@ -146,9 +146,17 @@ In "--create" mode, the mask is ignored.
 .TP
 .BI "-l, --label " "LABEL"
 Specify a conntrack label.
-This option is only available in conjunction with "-L, --dump" or "-E, --event".
+This option is only available in conjunction with "-L, --dump", "-E, --event", or "-U --update".
 Match entries whose labels match at least those specified.
 Use multiple -l commands to specify multiple labels that need to be set.
+Match entries whose labels matches at least those specified as arguments.
+.BI "--label-add " "LABEL"
+Specify the conntrack labels to add to to the selected conntracks.
+This option is only available in conjunction with "-I, --create" or "-U, --update".
+.BI "--label-del " "[LABEL]"
+Specify the conntrack label to delete from the selected conntracks.
+If no label is given, all labels are deleted.
+This option is only available in conjunction with "-U, --update".
 .TP
 .BI "-c, --secmark " "SECMARK"
 Specify the conntrack selinux security mark.
diff --git a/include/conntrack.h b/include/conntrack.h
index 6cd9962..c2a0c8f 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -10,7 +10,7 @@
 #include <netinet/in.h>
 
 #define NUMBER_OF_CMD   19
-#define NUMBER_OF_OPT   25
+#define NUMBER_OF_OPT   27
 
 struct ctproto_handler {
 	struct list_head 	head;
diff --git a/src/conntrack.c b/src/conntrack.c
index 4548169..d9b5a86 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -82,6 +82,9 @@ static struct {
 
 	/* Allows filtering by ctlabels */
 	struct nfct_bitmask *label;
+
+	/* Allows setting/removing specific ctlabels */
+	struct nfct_bitmask *label_modify;
 } tmpl;
 
 static int alloc_tmpl_objects(void)
@@ -109,6 +112,8 @@ static void free_tmpl_objects(void)
 		nfexp_destroy(tmpl.exp);
 	if (tmpl.label)
 		nfct_bitmask_destroy(tmpl.label);
+	if (tmpl.label_modify)
+		nfct_bitmask_destroy(tmpl.label_modify);
 }
 
 enum ct_command {
@@ -255,6 +260,12 @@ enum ct_options {
 
 	CT_OPT_LABEL_BIT	= 24,
 	CT_OPT_LABEL		= (1 << CT_OPT_LABEL_BIT),
+
+	CT_OPT_ADD_LABEL_BIT	= 25,
+	CT_OPT_ADD_LABEL		= (1 << CT_OPT_ADD_LABEL_BIT),
+
+	CT_OPT_DEL_LABEL_BIT	= 26,
+	CT_OPT_DEL_LABEL		= (1 << CT_OPT_DEL_LABEL_BIT),
 };
 /* If you add a new option, you have to update NUMBER_OF_OPT in conntrack.h */
 
@@ -289,6 +300,8 @@ static const char *optflags[NUMBER_OF_OPT] = {
 	[CT_OPT_ANY_NAT_BIT]	= "any-nat",
 	[CT_OPT_ZONE_BIT]	= "zone",
 	[CT_OPT_LABEL_BIT]	= "label",
+	[CT_OPT_ADD_LABEL_BIT]	= "label-add",
+	[CT_OPT_DEL_LABEL_BIT]	= "label-del",
 };
 
 static struct option original_opts[] = {
@@ -330,12 +343,14 @@ static struct option original_opts[] = {
 	{"any-nat", 2, 0, 'j'},
 	{"zone", 1, 0, 'w'},
 	{"label", 1, 0, 'l'},
+	{"label-add", 1, 0, '<'},
+	{"label-del", 2, 0, '>'},
 	{0, 0, 0, 0}
 };
 
 static const char *getopt_str = ":L::I::U::D::G::E::F::hVs:d:r:q:"
 				"p:t:u:e:a:z[:]:{:}:m:i:f:o:n::"
-				"g::c:b:C::Sj::w:l:";
+				"g::c:b:C::Sj::w:l:<:>::";
 
 /* Table of legal combinations of commands and options.  If any of the
  * given commands make an option legal, that option is legal (applies to
@@ -350,26 +365,26 @@ static const char *getopt_str = ":L::I::U::D::G::E::F::hVs:d:r:q:"
 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Linux vs FreeBSD" */
 {
-          /*   s d r q p t u z e [ ] { } a m i f n g o c b j w l*/
-/*CT_LIST*/   {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,2},
-/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0},
-/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0},
-/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2,0},
-/*CT_GET*/    {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0},
-/*CT_FLUSH*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_EVENT*/  {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2},
-/*VERSION*/   {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*HELP*/      {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_LIST*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0},
-/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_GET*/   {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0},
-/*CT_COUNT*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*CT_STATS*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*EXP_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+          /*   s d r q p t u z e [ ] { } a m i f n g o c b j w l < > */
+/*CT_LIST*/   {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,2,0,0},
+/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,2,0},
+/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,2,2,2},
+/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2,2,0,0},
+/*CT_GET*/    {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0},
+/*CT_FLUSH*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*CT_EVENT*/  {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2,0,0},
+/*VERSION*/   {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*HELP*/      {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_LIST*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0},
+/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_GET*/   {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0},
+/*CT_COUNT*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*CT_STATS*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*EXP_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 };
 
 static const int cmd2type[][2] = {
@@ -402,6 +417,8 @@ static const int opt2type[] = {
 	['j']	= CT_OPT_ANY_NAT,
 	['w']	= CT_OPT_ZONE,
 	['l']	= CT_OPT_LABEL,
+	['<']	= CT_OPT_ADD_LABEL,
+	['>']	= CT_OPT_DEL_LABEL,
 };
 
 static const int opt2family_attr[][2] = {
@@ -425,6 +442,8 @@ static const int opt2attr[] = {
 	['i']	= ATTR_ID,
 	['w']	= ATTR_ZONE,
 	['l']	= ATTR_CONNLABELS,
+	['<']	= ATTR_CONNLABELS,
+	['>']	= ATTR_CONNLABELS,
 };
 
 static char exit_msg[NUMBER_OF_CMD][64] = {
@@ -472,6 +491,11 @@ static const char usage_expectation_parameters[] =
 	"  --mask-src ip\t\tSource mask address\n"
 	"  --mask-dst ip\t\tDestination mask address\n";
 
+static const char usage_update_parameters[] =
+	"Updating parameters and options:\n"
+	"  --label-add label\tAdd label\n"
+	"  --label-del label\tDelete label\n";
+
 static const char usage_parameters[] =
 	"Common parameters and options:\n"
 	"  -s, --orig-src ip\t\tSource address from original direction\n"
@@ -992,6 +1016,7 @@ usage(char *prog)
 	fprintf(stdout, "\n%s", usage_tables);
 	fprintf(stdout, "\n%s", usage_conntrack_parameters);
 	fprintf(stdout, "\n%s", usage_expectation_parameters);
+	fprintf(stdout, "\n%s", usage_update_parameters);
 	fprintf(stdout, "\n%s\n", usage_parameters);
 }
 
@@ -1296,7 +1321,7 @@ static int print_cb(enum nf_conntrack_msg_type type,
 	if (output_mask & _O_ID)
 		op_flags |= NFCT_OF_ID;
 
-	nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags);
+	nfct_snprintf_labels(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags, labelmap);
 	printf("%s\n", buf);
 
 	return NFCT_CB_CONTINUE;
@@ -1323,6 +1348,55 @@ static void copy_status(struct nf_conntrack *tmp, const struct nf_conntrack *ct)
 	}
 }
 
+static void copy_label(struct nf_conntrack *tmp, const struct nf_conntrack *ct)
+{
+	struct nfct_bitmask *ctb, *newmask;
+	unsigned int i;
+
+	if ((options & (CT_OPT_ADD_LABEL|CT_OPT_DEL_LABEL)) == 0)
+		return;
+
+	nfct_copy_attr(tmp, ct, ATTR_CONNLABELS);
+	ctb = (void *) nfct_get_attr(tmp, ATTR_CONNLABELS);
+
+	if (options & CT_OPT_ADD_LABEL) {
+		if (ctb == NULL) {
+			newmask = nfct_bitmask_clone(tmpl.label_modify);
+			if (newmask)
+				nfct_set_attr(tmp, ATTR_CONNLABELS, newmask);
+			return;
+		}
+
+		for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) {
+			if (nfct_bitmask_test_bit(tmpl.label_modify, i))
+				nfct_bitmask_set_bit(ctb, i);
+		}
+
+		newmask = nfct_bitmask_clone(tmpl.label_modify);
+		if (newmask)
+			nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask);
+	} else if (ctb != NULL) {
+		/* CT_OPT_DEL_LABEL */
+		if (tmpl.label_modify == NULL) {
+			newmask = nfct_bitmask_new(0);
+			if (newmask)
+				nfct_set_attr(tmp, ATTR_CONNLABELS, newmask);
+			return;
+		}
+
+		for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) {
+			if (nfct_bitmask_test_bit(tmpl.label_modify, i))
+				nfct_bitmask_unset_bit(ctb, i);
+		}
+
+		newmask = nfct_bitmask_clone(tmpl.label_modify);
+		if (newmask)
+			nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask);
+		else
+			nfct_attr_unset(tmp, ATTR_CONNLABELS);
+	}
+}
+
 static int update_cb(enum nf_conntrack_msg_type type,
 		     struct nf_conntrack *ct,
 		     void *data)
@@ -1342,6 +1416,9 @@ static int update_cb(enum nf_conntrack_msg_type type,
 	if (options & CT_OPT_TUPLE_REPL && !nfct_cmp(obj, ct, NFCT_CMP_REPL))
 		return NFCT_CB_CONTINUE;
 
+	if (filter_label(ct))
+		return NFCT_CB_CONTINUE;
+
 	tmp = nfct_new();
 	if (tmp == NULL)
 		exit_error(OTHER_PROBLEM, "out of memory");
@@ -1350,6 +1427,7 @@ static int update_cb(enum nf_conntrack_msg_type type,
 	nfct_copy(tmp, obj, NFCT_CP_META);
 	copy_mark(tmp, ct, &tmpl.mark);
 	copy_status(tmp, ct);
+	copy_label(tmp, ct);
 
 	/* do not send NFCT_Q_UPDATE if ct appears unchanged */
 	if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) {
@@ -2010,14 +2088,33 @@ int main(int argc, char *argv[])
 			tmpl.filter_mark_kernel.mask = tmpl.mark.mask;
 			break;
 		case 'l':
+		case '<':
+		case '>':
 			options |= opt2type[c];
 
+			if ((options & (CT_OPT_DEL_LABEL|CT_OPT_ADD_LABEL)) ==
+			    (CT_OPT_DEL_LABEL|CT_OPT_ADD_LABEL))
+				exit_error(OTHER_PROBLEM, "cannot use --label-add and "
+							"--label-del at the same time");
+
+			if (c == '>') { /* ADD */
+				char *tmp = get_optional_arg(argc, argv);
+				if (tmp == NULL) /* delete all labels */
+					break;
+				optarg = tmp;
+			}
+
 			labelmap_init();
 
 			struct nfct_bitmask *b;
-			b = name_to_bitmask(optarg);
-			/* join "-l foo -l bar" into single bitmask object */
-			merge_bitmasks(&tmpl.label, b);
+			if (c == 'l') {
+				b = name_to_bitmask(optarg);
+				/* join "-l foo -l bar" into single bitmask object */
+				merge_bitmasks(&tmpl.label, b);
+			} else {
+				b = name_to_bitmask(optarg);
+				merge_bitmasks(&tmpl.label_modify, b);
+			}
 
 			break;
 		case 'a':
@@ -2176,6 +2273,11 @@ int main(int argc, char *argv[])
 		if (options & CT_OPT_MARK)
 			nfct_set_attr_u32(tmpl.ct, ATTR_MARK, tmpl.mark.value);
 
+		if (options & CT_OPT_ADD_LABEL) {
+			void *clone = nfct_bitmask_clone(tmpl.label);
+			nfct_set_attr(tmpl.ct, ATTR_CONNLABELS, clone);
+		}
+
 		cth = nfct_open(CONNTRACK, 0);
 		if (!cth)
 			exit_error(OTHER_PROBLEM, "Can't open handler");
-- 
1.7.8.6


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

* Re: [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar
  2013-09-03 15:28 ` [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar Florian Westphal
@ 2013-09-03 21:11   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2013-09-03 21:11 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Tue, Sep 03, 2013 at 05:28:41PM +0200, Florian Westphal wrote:
> Its more straightforward to use -l foo -l bar when only wanting
> to see conntracks that have both labels set.
> 
> It also simplifies things a lot.

We need to keep the old syntax, 1.4.2 already supports -l foo,bar so
we cannot delete it.

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

end of thread, other threads:[~2013-09-03 21:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-03 15:28 [PATCH 1/3] conntrack: minor cleanup Florian Westphal
2013-09-03 15:28 ` [PATCH 2/3] conntrack: favor multiple -l options over -l foo,bar Florian Westphal
2013-09-03 21:11   ` Pablo Neira Ayuso
2013-09-03 15:28 ` [PATCH 3/3] conntrack: allow adding/deleting labels from conntrack entries Florian Westphal

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.