netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [libnftables PATCH 1/2] src: utils: add verdict2str
@ 2013-07-25 20:20 Arturo Borrero Gonzalez
  2013-07-25 20:20 ` [libnftables PATCH 2/2] set: XML parse Arturo Borrero Gonzalez
  2013-07-25 20:33 ` [libnftables PATCH 1/2] src: utils: add verdict2str Pablo Neira Ayuso
  0 siblings, 2 replies; 4+ messages in thread
From: Arturo Borrero Gonzalez @ 2013-07-25 20:20 UTC (permalink / raw)
  To: netfilter-devel

Add verdict2str() and str2verdict() helper functions and use in XML.

I've followed nft_verdict_init() in net/netfilter/nf_tables_api.c

While at it, I've fixed a small style issue in the data_reg JSON output and a
bug in the data_reg XML parser:
The parser walked the top level tree, instead of single <data_reg> node.
This patch fixes it. Introduced at: 51370f0 src: add support for XML parsing.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 src/expr/data_reg.c |   54 ++++++++++++++++++++++-----------------------------
 src/internal.h      |    2 ++
 src/utils.c         |   49 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index b290b96..85c441e 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -31,8 +31,8 @@ static int nft_data_reg_verdict_xml_parse(union nft_data_reg *reg, char *xml)
 {
 	mxml_node_t *tree = NULL;
 	mxml_node_t *node = NULL;
-	char *endptr;
-	long int tmp;
+	int verdict;
+	const char *verdict_str;
 
 	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
 	if (tree == NULL)
@@ -47,33 +47,30 @@ static int nft_data_reg_verdict_xml_parse(union nft_data_reg *reg, char *xml)
 	}
 
 	/* Get and validate <data_reg type="verdict" >*/
-	if (mxmlElementGetAttr(tree, "type") == NULL) {
+	if (mxmlElementGetAttr(node, "type") == NULL) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
-	if (strcmp(mxmlElementGetAttr(tree, "type"), "verdict") != 0) {
+	if (strcmp(mxmlElementGetAttr(node, "type"), "verdict") != 0) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
 	/* Get and set <verdict> */
-	node = mxmlFindElement(tree, tree, "verdict", NULL, NULL,
-			       MXML_DESCEND_FIRST);
-	if (node == NULL) {
+	verdict_str = nft_mxml_str_parse(tree, "verdict", MXML_DESCEND);
+	if (verdict_str == NULL) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
-	errno = 0;
-	tmp = strtoll(node->child->value.opaque, &endptr, 10);
-	if (tmp > INT_MAX || tmp < INT_MIN || errno != 0
-						|| strlen(endptr) > 0) {
+	verdict = nft_str2verdict(verdict_str);
+	if (verdict < 0) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
-	reg->verdict = tmp;
+	reg->verdict = (uint32_t)verdict;
 
 	mxmlDelete(tree);
 	return 0;
@@ -97,34 +94,27 @@ static int nft_data_reg_chain_xml_parse(union nft_data_reg *reg, char *xml)
 	}
 
 	/* Get and validate <data_reg type="chain" >*/
-	if (mxmlElementGetAttr(tree, "type") == NULL) {
+	if (mxmlElementGetAttr(node, "type") == NULL) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
-	if (strcmp(mxmlElementGetAttr(tree, "type"), "chain") != 0) {
+	if (strcmp(mxmlElementGetAttr(node, "type"), "chain") != 0) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
 	/* Get and set <chain> */
-	node = mxmlFindElement(tree, tree, "chain", NULL, NULL, MXML_DESCEND);
-	if (node == NULL) {
-		mxmlDelete(tree);
-		return -1;
-	}
+	if (reg->chain)
+		free(reg->chain);
 
-	/* no max len value to validate? */
-	if (strlen(node->child->value.opaque) < 1) {
+	reg->chain = (char *)nft_mxml_str_parse(tree, "chain",
+						MXML_DESCEND);
+	if (reg->chain == NULL) {
 		mxmlDelete(tree);
 		return -1;
 	}
 
-	if (reg->chain)
-		free(reg->chain);
-
-	reg->chain = strdup(node->child->value.opaque);
-
 	mxmlDelete(tree);
 	return 0;
 }
@@ -346,13 +336,15 @@ int nft_data_reg_snprintf(char *buf, size_t size, union nft_data_reg *reg,
 		case NFT_RULE_O_XML:
 			return snprintf(buf, size,
 					"<data_reg type=\"verdict\">"
-						"<verdict>%d</verdict>"
-					"</data_reg>", reg->verdict);
+						"<verdict>%s</verdict>"
+					"</data_reg>",
+					nft_verdict2str(reg->verdict));
 		case NFT_RULE_O_JSON:
 			return snprintf(buf, size,
-					"\"data_reg\": { \"type\" : \"verdict\", "
-						"\"verdict\" : %d"
-					"}", reg->verdict);
+					"\"data_reg\": {"
+						"\"type\" : \"verdict\", "
+						"\"verdict\" : \"%s\""
+					"}", nft_verdict2str(reg->verdict));
 		default:
 			break;
 		}
diff --git a/src/internal.h b/src/internal.h
index fc78233..b846814 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -49,6 +49,8 @@ const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name, uint32_
 const char *nft_family2str(uint32_t family);
 int nft_str2family(const char *family);
 int nft_strtoi(const char *string, int base, void *number, enum nft_type type);
+const char *nft_verdict2str(uint32_t verdict);
+int nft_str2verdict(const char *verdict);
 
 struct expr_ops;
 
diff --git a/src/utils.c b/src/utils.c
index 4a0bb9c..2cdf4bf 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -17,6 +17,9 @@
 #include <errno.h>
 #include <inttypes.h>
 
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+
 const char *nft_family2str(uint32_t family)
 {
 	switch (family) {
@@ -117,3 +120,49 @@ int nft_strtoi(const char *string, int base, void *out, enum nft_type type)
 
 	return 0;
 }
+
+const char *nft_verdict2str(uint32_t verdict)
+{
+	switch (verdict) {
+	case NF_ACCEPT:
+		return "accept";
+	case NF_DROP:
+		return "drop";
+	case NF_QUEUE:
+		return "queue";
+	case NFT_CONTINUE:
+		return "continue";
+	case NFT_BREAK:
+		return "break";
+	case NFT_RETURN:
+		return "return";
+	case NFT_JUMP:
+		return "jump";
+	case NFT_GOTO:
+		return "goto";
+	default:
+		return "unknown";
+	}
+}
+
+int nft_str2verdict(const char *verdict)
+{
+	if (strcmp(verdict, "accept") == 0)
+		return NF_ACCEPT;
+	else if (strcmp(verdict, "drop") == 0)
+		return NF_DROP;
+	else if (strcmp(verdict, "queue") == 0)
+		return NF_QUEUE;
+	else if (strcmp(verdict, "continue") == 0)
+		return NFT_CONTINUE;
+	else if (strcmp(verdict, "break") == 0)
+		return NFT_BREAK;
+	else if (strcmp(verdict, "return") == 0)
+		return NFT_RETURN;
+	else if (strcmp(verdict, "jump") == 0)
+		return NFT_JUMP;
+	else if (strcmp(verdict, "goto") == 0)
+		return NFT_GOTO;
+
+	return -1;
+}


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

* [libnftables PATCH 2/2] set: XML parse
  2013-07-25 20:20 [libnftables PATCH 1/2] src: utils: add verdict2str Arturo Borrero Gonzalez
@ 2013-07-25 20:20 ` Arturo Borrero Gonzalez
  2013-07-25 20:49   ` Pablo Neira Ayuso
  2013-07-25 20:33 ` [libnftables PATCH 1/2] src: utils: add verdict2str Pablo Neira Ayuso
  1 sibling, 1 reply; 4+ messages in thread
From: Arturo Borrero Gonzalez @ 2013-07-25 20:20 UTC (permalink / raw)
  To: netfilter-devel

Sets are now parsed, following this previous snprintf pattern:

<set name="xx" table="xx" version="xx">
	<set_flags>uint32_t</set_flags>
	<key_type>uint32_t</key_type>
	<key_len>size_t</key_len>
	<data_type>uint32_t</data_type>
	<data_len>size_t</data_len>
	<set_elem>
		<set_elem_flags>uint32_t</set_elem_flags>
		<set_elem_key>
			<data_reg type="value">
				<len></len>
				<dataN></dataN>
			</data_reg>
		</set_elem_key>
		<set_elem_data>
			<data_reg type="xx">
				[...]
			</data_reg>
		</set_elem_data>
	</set_elem>
</set>


Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
---
 include/libnftables/set.h |    9 ++
 src/libnftables.map       |    2 +
 src/mxml.c                |    2 -
 src/set.c                 |  174 +++++++++++++++++++++++++++++++++++++++++++++
 src/set_elem.c            |   85 +++++++++++++++++++++-
 tests/nft-parsing-test.c  |   10 +++
 tests/xmlfiles/36-set.xml |   51 +++++++++++++
 7 files changed, 328 insertions(+), 5 deletions(-)
 create mode 100644 tests/xmlfiles/36-set.xml

diff --git a/include/libnftables/set.h b/include/libnftables/set.h
index 6023d50..4fc3a8d 100644
--- a/include/libnftables/set.h
+++ b/include/libnftables/set.h
@@ -52,6 +52,14 @@ struct nft_set *nft_set_list_iter_cur(struct nft_set_list_iter *iter);
 struct nft_set *nft_set_list_iter_next(struct nft_set_list_iter *iter);
 void nft_set_list_iter_destroy(struct nft_set_list_iter *iter);
 
+enum nft_set_parse_type {
+	NFT_SET_PARSE_NONE	= 0,
+	NFT_SET_PARSE_XML,
+	NFT_SET_PARSE_MAX,
+};
+
+int nft_set_parse(struct nft_set *s, enum nft_set_parse_type type, char *data);
+
 /*
  * Set elements
  */
@@ -94,6 +102,7 @@ void nft_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, struct nft_set_elem
 
 int nft_set_elem_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set_elem *s);
 
+int nft_set_elem_parse(struct nft_set_elem *e, enum nft_set_parse_type type, char *data);
 int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *s, uint32_t type, uint32_t flags);
 
 int nft_set_elem_foreach(struct nft_set *s, int (*cb)(struct nft_set_elem *e, void *data), void *data);
diff --git a/src/libnftables.map b/src/libnftables.map
index f2084d9..614c705 100644
--- a/src/libnftables.map
+++ b/src/libnftables.map
@@ -120,6 +120,7 @@ global:
   nft_set_nlmsg_build_hdr;
   nft_set_nlmsg_build_payload;
   nft_set_nlmsg_parse;
+  nft_set_parse;
   nft_set_snprintf;
 
   nft_set_list_alloc;
@@ -149,6 +150,7 @@ global:
   nft_set_elem_nlmsg_build_hdr;
   nft_set_elem_nlmsg_build_payload;
   nft_set_elem_nlmsg_parse;
+  nft_set_elem_parse;
   nft_set_elem_snprintf;
 
   nft_set_elems_nlmsg_build_payload;
diff --git a/src/mxml.c b/src/mxml.c
index f812bf6..3d6ada4 100644
--- a/src/mxml.c
+++ b/src/mxml.c
@@ -111,7 +111,7 @@ int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name,
 	}
 
 	node = mxmlFindElement(node, node, "data_reg", NULL, NULL,
-			       MXML_DESCEND);
+			       MXML_DESCEND_FIRST);
 	if (node == NULL || node->child == NULL) {
 		errno = EINVAL;
 		goto err;
diff --git a/src/set.c b/src/set.c
index ef15527..5e1f8ed 100644
--- a/src/set.c
+++ b/src/set.c
@@ -16,6 +16,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <netinet/in.h>
+#include <limits.h>
+#include <errno.h>
 
 #include <libmnl/libmnl.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -301,6 +303,178 @@ int nft_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s)
 }
 EXPORT_SYMBOL(nft_set_nlmsg_parse);
 
+static int nft_set_xml_parse(struct nft_set *s, char *xml)
+{
+#ifdef XML_PARSING
+	mxml_node_t *tree = NULL;
+	mxml_node_t *node = NULL;
+	mxml_node_t *save = NULL;
+	char *set_elem_str = NULL;
+	struct nft_set_elem *elem;
+	int version;
+	int family;
+
+	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+	if (tree == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (strcmp(tree->value.opaque, "set") != 0)
+		goto einval;
+
+	if (mxmlElementGetAttr(tree, "version") == NULL)
+		goto einval;
+
+	if (nft_strtoi(mxmlElementGetAttr(tree, "version"), 10, &version,
+		       NFT_TYPE_U64) != 0)
+		goto err;
+
+	if (version != NFT_SET_XML_VERSION)
+		goto einval;
+
+	if (mxmlElementGetAttr(tree, "name") == NULL)
+		goto einval;
+
+	if (s->name)
+		free(s->name);
+
+	s->name = strdup(mxmlElementGetAttr(tree, "name"));
+	s->flags |= (1 << NFT_SET_ATTR_NAME);
+
+	if (mxmlElementGetAttr(tree, "table") == NULL)
+		goto einval;
+
+	if (s->table)
+		free(s->table);
+
+	s->table = strdup(mxmlElementGetAttr(tree, "table"));
+	s->flags |= (1 << NFT_SET_ATTR_TABLE);
+
+	node = mxmlFindElement(tree, tree, "family", NULL, NULL,
+			       MXML_DESCEND_FIRST);
+	if (node == NULL)
+		goto einval;
+
+	if (node->child == NULL)
+		goto einval;
+
+	family = nft_str2family(node->child->value.opaque);
+
+	if (family < 0)
+		goto eafnosupport;
+
+	s->family = family;
+
+	s->flags |= (1 << NFT_SET_ATTR_FAMILY);
+
+	if (nft_mxml_num_parse(tree, "set_flags", MXML_DESCEND_FIRST,
+			       BASE_DEC, &s->set_flags, NFT_TYPE_U32) != 0)
+		goto einval;
+
+	s->flags |= (1 << NFT_SET_ATTR_FLAGS);
+
+
+	if (nft_mxml_num_parse(tree, "key_type", MXML_DESCEND_FIRST,
+			       BASE_DEC, &s->key_type, NFT_TYPE_U32) != 0)
+		goto einval;
+
+	s->flags |= (1 << NFT_SET_ATTR_KEY_TYPE);
+
+	if (nft_mxml_num_parse(tree, "key_len", MXML_DESCEND_FIRST,
+			       BASE_DEC, &s->key_type, NFT_TYPE_U32) != 0)
+		goto einval;
+
+	s->flags |= (1 << NFT_SET_ATTR_KEY_LEN);
+
+	if (nft_mxml_num_parse(tree, "data_type", MXML_DESCEND_FIRST,
+			       BASE_DEC, &s->data_type, NFT_TYPE_U32) != 0)
+		goto einval;
+
+	s->flags |= (1 << NFT_SET_ATTR_DATA_TYPE);
+
+	if (nft_mxml_num_parse(tree, "data_len", MXML_DESCEND_FIRST,
+			       BASE_DEC, &s->data_len, NFT_TYPE_U32) != 0)
+		goto einval;
+
+	s->flags |= (1 << NFT_SET_ATTR_DATA_LEN);
+
+	/* Iterate over each <set_elem> */
+	for (node = mxmlFindElement(tree, tree, "set_elem", NULL,
+				    NULL, MXML_DESCEND);
+		node != NULL;
+		node = mxmlFindElement(node, tree, "set_elem", NULL,
+				       NULL, MXML_DESCEND)) {
+
+		elem = nft_set_elem_alloc();
+		if (elem == NULL)
+			goto enomem;
+
+		/* This is a hack for mxml to print just the current node */
+		save = node->next;
+		node->next = NULL;
+
+		set_elem_str = mxmlSaveAllocString(node, MXML_NO_CALLBACK);
+		if (set_elem_str == NULL) {
+			free(elem);
+			goto enomem;
+		}
+
+		if (nft_set_elem_parse(elem, NFT_SET_PARSE_XML,
+				       set_elem_str) != 0) {
+			printf("nft_set_elem_parse err: %s\n", set_elem_str);
+			free(set_elem_str);
+			free(elem);
+			goto err;
+		}
+
+		node->next = save;
+		free(set_elem_str);
+
+		list_add_tail(&elem->head, &s->element_list);
+	}
+
+	mxmlDelete(tree);
+	return 0;
+einval:
+	errno = EINVAL;
+	mxmlDelete(tree);
+	return -1;
+eafnosupport:
+	errno = EAFNOSUPPORT;
+	mxmlDelete(tree);
+	return -1;
+enomem:
+	errno = ENOMEM;
+	mxmlDelete(tree);
+	return -1;
+err:
+	mxmlDelete(tree);
+	return -1;
+#else
+	errno = EOPNOTSUPP;
+	return -1;
+#endif
+}
+
+int nft_set_parse(struct nft_set *s, enum nft_set_parse_type type, char *data)
+{
+	int ret;
+
+	switch (type) {
+	case NFT_SET_PARSE_XML:
+		ret = nft_set_xml_parse(s, data);
+		break;
+	default:
+		ret = -1;
+		errno = EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_set_parse);
+
 static int nft_set_snprintf_json(char *buf, size_t size, struct nft_set *s,
 				  uint32_t type, uint32_t flags)
 {
diff --git a/src/set_elem.c b/src/set_elem.c
index 4adba91..724c312 100644
--- a/src/set_elem.c
+++ b/src/set_elem.c
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <netinet/in.h>
+#include <errno.h>
 
 #include <libmnl/libmnl.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -374,8 +375,83 @@ int nft_set_elems_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s)
 }
 EXPORT_SYMBOL(nft_set_elems_nlmsg_parse);
 
+static int nft_set_elem_xml_parse(struct nft_set_elem *e, char *xml)
+{
+#ifdef XML_PARSING
+	mxml_node_t *tree = NULL;
+	int set_elem_data;
+
+	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+	if (tree == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (strcmp(tree->value.opaque, "set_elem") != 0)
+		goto einval;
+
+	if (nft_mxml_num_parse(tree, "set_elem_flags", MXML_DESCEND_FIRST,
+			       BASE_DEC, &e->set_elem_flags,
+			       NFT_TYPE_U32) != 0)
+		goto einval;
+
+	e->flags |= (1 << NFT_SET_ELEM_ATTR_FLAGS);
+
+	if (nft_mxml_data_reg_parse(tree, "set_elem_key",
+				    &e->key) != DATA_VALUE)
+		goto einval;
+
+	e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY);
+
+	set_elem_data = nft_mxml_data_reg_parse(tree, "set_elem_data",
+						&e->data);
+	switch (set_elem_data) {
+	case DATA_VALUE:
+		e->flags |= (1 << NFT_SET_ELEM_ATTR_DATA);
+		break;
+	case DATA_VERDICT:
+		e->flags |= (1 << NFT_SET_ELEM_ATTR_VERDICT);
+		break;
+	case DATA_CHAIN:
+		e->flags |= (1 << NFT_SET_ELEM_ATTR_CHAIN);
+		break;
+	default:
+		goto einval;
+	}
+
+	mxmlDelete(tree);
+	return 0;
+
+einval:
+	errno = EINVAL;
+	mxmlDelete(tree);
+	return -1;
+#else
+	errno = EOPNOTSUPP;
+	return -1;
+#endif
+}
+
+int nft_set_elem_parse(struct nft_set_elem *e,
+		       enum nft_set_parse_type type, char *data) {
+	int ret;
+
+	switch (type) {
+	case NFT_SET_PARSE_XML:
+		ret = nft_set_elem_xml_parse(e, data);
+		break;
+	default:
+		errno = EOPNOTSUPP;
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_set_elem_parse);
+
 static int nft_set_elem_snprintf_json(char *buf, size_t size,
-				       struct nft_set_elem *e, uint32_t flags)
+				      struct nft_set_elem *e, uint32_t flags)
 {
 	int ret, len = size, offset = 0, type = -1;
 
@@ -414,8 +490,9 @@ static int nft_set_elem_snprintf_json(char *buf, size_t size,
 	return offset;
 }
 
-static int nft_set_elem_snprintf_default(char *buf, size_t size,
-					 struct nft_set_elem *e)
+static
+int nft_set_elem_snprintf_default(char *buf, size_t size,
+				  struct nft_set_elem *e, uint32_t flags)
 {
 	int ret, len = size, offset = 0, i;
 
@@ -505,7 +582,7 @@ int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *e,
 {
 	switch(type) {
 	case NFT_SET_O_DEFAULT:
-		return nft_set_elem_snprintf_default(buf, size, e);
+		return nft_set_elem_snprintf_default(buf, size, e, flags);
 	case NFT_SET_O_XML:
 		return nft_set_elem_snprintf_xml(buf, size, e, flags);
 	case NFT_SET_O_JSON:
diff --git a/tests/nft-parsing-test.c b/tests/nft-parsing-test.c
index 4fe60c3..c75d97b 100644
--- a/tests/nft-parsing-test.c
+++ b/tests/nft-parsing-test.c
@@ -9,6 +9,7 @@
 #include <libnftables/table.h>
 #include <libnftables/chain.h>
 #include <libnftables/rule.h>
+#include <libnftables/set.h>
 
 #ifdef XML_PARSING
 #include <mxml.h>
@@ -21,6 +22,7 @@ static int test_xml(const char *filename)
 	struct nft_table *t = NULL;
 	struct nft_chain *c = NULL;
 	struct nft_rule *r = NULL;
+	struct nft_set *s = NULL;
 	FILE *fp;
 	mxml_node_t *tree = NULL;;
 	char *xml = NULL;
@@ -61,6 +63,14 @@ static int test_xml(const char *filename)
 
 			nft_rule_free(r);
 		}
+	} else if (strcmp(tree->value.opaque, "set") == 0) {
+		s = nft_set_alloc();
+		if (s != NULL) {
+			if (nft_set_parse(s, NFT_SET_PARSE_XML, xml) == 0)
+				ret = 0;
+
+			nft_set_free(s);
+		}
 	}
 
 	return ret;
diff --git a/tests/xmlfiles/36-set.xml b/tests/xmlfiles/36-set.xml
new file mode 100644
index 0000000..71ca189
--- /dev/null
+++ b/tests/xmlfiles/36-set.xml
@@ -0,0 +1,51 @@
+<set name="set1" table="filter" version="0">
+	<family>ip</family>
+	<set_flags>6</set_flags>
+	<key_type>0</key_type>
+	<key_len>12</key_len>
+	<data_type>0</data_type>
+	<data_len>12</data_len>
+	<set_elem>
+		<set_elem_flags>1</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0xffaabbdd</data0>
+			</data_reg>
+		</set_elem_key>
+		<set_elem_data>
+			<data_reg type="verdict">
+				<verdict>accept</verdict>
+			</data_reg>
+		</set_elem_data>
+	</set_elem>
+	<set_elem>
+		<set_elem_flags>1</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0xffaabb11</data0>
+			</data_reg>
+		</set_elem_key>
+		<set_elem_data>
+			<data_reg type="chain">
+				<chain>test</chain>
+			</data_reg>
+		</set_elem_data>
+	</set_elem>
+	<set_elem>
+		<set_elem_flags>1</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0xffaabb11</data0>
+			</data_reg>
+		</set_elem_key>
+		<set_elem_data>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0xcafecafe</data0>
+			</data_reg>
+		</set_elem_data>
+	</set_elem>
+</set>

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [libnftables PATCH 1/2] src: utils: add verdict2str
  2013-07-25 20:20 [libnftables PATCH 1/2] src: utils: add verdict2str Arturo Borrero Gonzalez
  2013-07-25 20:20 ` [libnftables PATCH 2/2] set: XML parse Arturo Borrero Gonzalez
@ 2013-07-25 20:33 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2013-07-25 20:33 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel

On Thu, Jul 25, 2013 at 10:20:33PM +0200, Arturo Borrero Gonzalez wrote:
> Add verdict2str() and str2verdict() helper functions and use in XML.
> 
> I've followed nft_verdict_init() in net/netfilter/nf_tables_api.c
> 
> While at it, I've fixed a small style issue in the data_reg JSON output and a
> bug in the data_reg XML parser:
> The parser walked the top level tree, instead of single <data_reg> node.
> This patch fixes it. Introduced at: 51370f0 src: add support for XML parsing.

Applied, thanks.

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

* Re: [libnftables PATCH 2/2] set: XML parse
  2013-07-25 20:20 ` [libnftables PATCH 2/2] set: XML parse Arturo Borrero Gonzalez
@ 2013-07-25 20:49   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2013-07-25 20:49 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel

On Thu, Jul 25, 2013 at 10:20:39PM +0200, Arturo Borrero Gonzalez wrote:
> Sets are now parsed, following this previous snprintf pattern:
> 
> <set name="xx" table="xx" version="xx">
> 	<set_flags>uint32_t</set_flags>
> 	<key_type>uint32_t</key_type>
> 	<key_len>size_t</key_len>
> 	<data_type>uint32_t</data_type>
> 	<data_len>size_t</data_len>
> 	<set_elem>
> 		<set_elem_flags>uint32_t</set_elem_flags>
> 		<set_elem_key>
> 			<data_reg type="value">
> 				<len></len>
> 				<dataN></dataN>
> 			</data_reg>
> 		</set_elem_key>
> 		<set_elem_data>
> 			<data_reg type="xx">
> 				[...]
> 			</data_reg>
> 		</set_elem_data>
> 	</set_elem>
> </set>
> 
> 
> Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
> ---
>  include/libnftables/set.h |    9 ++
>  src/libnftables.map       |    2 +
>  src/mxml.c                |    2 -
>  src/set.c                 |  174 +++++++++++++++++++++++++++++++++++++++++++++
>  src/set_elem.c            |   85 +++++++++++++++++++++-
>  tests/nft-parsing-test.c  |   10 +++
>  tests/xmlfiles/36-set.xml |   51 +++++++++++++
>  7 files changed, 328 insertions(+), 5 deletions(-)
>  create mode 100644 tests/xmlfiles/36-set.xml
> 
> diff --git a/include/libnftables/set.h b/include/libnftables/set.h
> index 6023d50..4fc3a8d 100644
> --- a/include/libnftables/set.h
> +++ b/include/libnftables/set.h
> @@ -52,6 +52,14 @@ struct nft_set *nft_set_list_iter_cur(struct nft_set_list_iter *iter);
>  struct nft_set *nft_set_list_iter_next(struct nft_set_list_iter *iter);
>  void nft_set_list_iter_destroy(struct nft_set_list_iter *iter);
>  
> +enum nft_set_parse_type {
> +	NFT_SET_PARSE_NONE	= 0,
> +	NFT_SET_PARSE_XML,
> +	NFT_SET_PARSE_MAX,
> +};
> +
> +int nft_set_parse(struct nft_set *s, enum nft_set_parse_type type, char *data);
> +
>  /*
>   * Set elements
>   */
> @@ -94,6 +102,7 @@ void nft_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, struct nft_set_elem
>  
>  int nft_set_elem_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set_elem *s);
>  
> +int nft_set_elem_parse(struct nft_set_elem *e, enum nft_set_parse_type type, char *data);
>  int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *s, uint32_t type, uint32_t flags);
>  
>  int nft_set_elem_foreach(struct nft_set *s, int (*cb)(struct nft_set_elem *e, void *data), void *data);
> diff --git a/src/libnftables.map b/src/libnftables.map
> index f2084d9..614c705 100644
> --- a/src/libnftables.map
> +++ b/src/libnftables.map
> @@ -120,6 +120,7 @@ global:
>    nft_set_nlmsg_build_hdr;
>    nft_set_nlmsg_build_payload;
>    nft_set_nlmsg_parse;
> +  nft_set_parse;
>    nft_set_snprintf;
>  
>    nft_set_list_alloc;
> @@ -149,6 +150,7 @@ global:
>    nft_set_elem_nlmsg_build_hdr;
>    nft_set_elem_nlmsg_build_payload;
>    nft_set_elem_nlmsg_parse;
> +  nft_set_elem_parse;
>    nft_set_elem_snprintf;
>  
>    nft_set_elems_nlmsg_build_payload;
> diff --git a/src/mxml.c b/src/mxml.c
> index f812bf6..3d6ada4 100644
> --- a/src/mxml.c
> +++ b/src/mxml.c
> @@ -111,7 +111,7 @@ int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name,
>  	}
>  
>  	node = mxmlFindElement(node, node, "data_reg", NULL, NULL,
> -			       MXML_DESCEND);
> +			       MXML_DESCEND_FIRST);
>  	if (node == NULL || node->child == NULL) {
>  		errno = EINVAL;
>  		goto err;
> diff --git a/src/set.c b/src/set.c
> index ef15527..5e1f8ed 100644
> --- a/src/set.c
> +++ b/src/set.c
> @@ -16,6 +16,8 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <netinet/in.h>
> +#include <limits.h>
> +#include <errno.h>
>  
>  #include <libmnl/libmnl.h>
>  #include <linux/netfilter/nfnetlink.h>
> @@ -301,6 +303,178 @@ int nft_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s)
>  }
>  EXPORT_SYMBOL(nft_set_nlmsg_parse);
>  
> +static int nft_set_xml_parse(struct nft_set *s, char *xml)
> +{
> +#ifdef XML_PARSING
> +	mxml_node_t *tree = NULL;

no need to init this variable.

> +	mxml_node_t *node = NULL;
> +	mxml_node_t *save = NULL;
> +	char *set_elem_str = NULL;
> +	struct nft_set_elem *elem;
> +	int version;
> +	int family;
> +
> +	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
> +	if (tree == NULL) {
> +		errno = EINVAL;
> +		return -1;
> +	}
> +
> +	if (strcmp(tree->value.opaque, "set") != 0)
> +		goto einval;
> +
> +	if (mxmlElementGetAttr(tree, "version") == NULL)
> +		goto einval;
> +
> +	if (nft_strtoi(mxmlElementGetAttr(tree, "version"), 10, &version,
> +		       NFT_TYPE_U64) != 0)
> +		goto err;
> +
> +	if (version != NFT_SET_XML_VERSION)
> +		goto einval;
> +
> +	if (mxmlElementGetAttr(tree, "name") == NULL)
> +		goto einval;
> +
> +	if (s->name)
> +		free(s->name);
> +
> +	s->name = strdup(mxmlElementGetAttr(tree, "name"));
> +	s->flags |= (1 << NFT_SET_ATTR_NAME);
> +
> +	if (mxmlElementGetAttr(tree, "table") == NULL)
> +		goto einval;
> +
> +	if (s->table)
> +		free(s->table);
> +
> +	s->table = strdup(mxmlElementGetAttr(tree, "table"));
> +	s->flags |= (1 << NFT_SET_ATTR_TABLE);
> +
> +	node = mxmlFindElement(tree, tree, "family", NULL, NULL,
> +			       MXML_DESCEND_FIRST);
> +	if (node == NULL)
> +		goto einval;
> +
> +	if (node->child == NULL)
> +		goto einval;
> +
> +	family = nft_str2family(node->child->value.opaque);
> +
> +	if (family < 0)
> +		goto eafnosupport;
> +
> +	s->family = family;
> +
> +	s->flags |= (1 << NFT_SET_ATTR_FAMILY);
> +
> +	if (nft_mxml_num_parse(tree, "set_flags", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &s->set_flags, NFT_TYPE_U32) != 0)
> +		goto einval;

nft_mxml_num_parse already sets errno.

> +
> +	s->flags |= (1 << NFT_SET_ATTR_FLAGS);
> +
> +
> +	if (nft_mxml_num_parse(tree, "key_type", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &s->key_type, NFT_TYPE_U32) != 0)
> +		goto einval;
> +
> +	s->flags |= (1 << NFT_SET_ATTR_KEY_TYPE);
> +
> +	if (nft_mxml_num_parse(tree, "key_len", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &s->key_type, NFT_TYPE_U32) != 0)
> +		goto einval;
> +
> +	s->flags |= (1 << NFT_SET_ATTR_KEY_LEN);
> +
> +	if (nft_mxml_num_parse(tree, "data_type", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &s->data_type, NFT_TYPE_U32) != 0)
> +		goto einval;
> +
> +	s->flags |= (1 << NFT_SET_ATTR_DATA_TYPE);
> +
> +	if (nft_mxml_num_parse(tree, "data_len", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &s->data_len, NFT_TYPE_U32) != 0)
> +		goto einval;
> +
> +	s->flags |= (1 << NFT_SET_ATTR_DATA_LEN);
> +
> +	/* Iterate over each <set_elem> */
> +	for (node = mxmlFindElement(tree, tree, "set_elem", NULL,
> +				    NULL, MXML_DESCEND);
> +		node != NULL;
> +		node = mxmlFindElement(node, tree, "set_elem", NULL,
> +				       NULL, MXML_DESCEND)) {
> +
> +		elem = nft_set_elem_alloc();
> +		if (elem == NULL)
> +			goto enomem;

already sets ENOMEM, no need for this.

> +
> +		/* This is a hack for mxml to print just the current node */
> +		save = node->next;
> +		node->next = NULL;
> +
> +		set_elem_str = mxmlSaveAllocString(node, MXML_NO_CALLBACK);
> +		if (set_elem_str == NULL) {
> +			free(elem);
> +			goto enomem;
> +		}
> +
> +		if (nft_set_elem_parse(elem, NFT_SET_PARSE_XML,
> +				       set_elem_str) != 0) {
> +			printf("nft_set_elem_parse err: %s\n", set_elem_str);
> +			free(set_elem_str);
> +			free(elem);
> +			goto err;
> +		}
> +
> +		node->next = save;
> +		free(set_elem_str);
> +
> +		list_add_tail(&elem->head, &s->element_list);
> +	}

Please, move element parsing to another function. Making functions
smaller help maintainability.

> +
> +	mxmlDelete(tree);
> +	return 0;
> +einval:

rename this to err:, now it's the only possible error in this
function.

> +	errno = EINVAL;
> +	mxmlDelete(tree);
> +	return -1;
> +eafnosupport:
> +	errno = EAFNOSUPPORT;
> +	mxmlDelete(tree);
> +	return -1;

no need for this, not nft_family2str sets it.

> +enomem:
> +	errno = ENOMEM;
> +	mxmlDelete(tree);
> +	return -1;

remove this.

> +err:
> +	mxmlDelete(tree);
> +	return -1;
> +#else
> +	errno = EOPNOTSUPP;
> +	return -1;
> +#endif
> +}
> +
> +int nft_set_parse(struct nft_set *s, enum nft_set_parse_type type, char *data)
> +{
> +	int ret;
> +
> +	switch (type) {
> +	case NFT_SET_PARSE_XML:
> +		ret = nft_set_xml_parse(s, data);
> +		break;
> +	default:
> +		ret = -1;
> +		errno = EOPNOTSUPP;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(nft_set_parse);
> +
>  static int nft_set_snprintf_json(char *buf, size_t size, struct nft_set *s,
>  				  uint32_t type, uint32_t flags)
>  {
> diff --git a/src/set_elem.c b/src/set_elem.c
> index 4adba91..724c312 100644
> --- a/src/set_elem.c
> +++ b/src/set_elem.c
> @@ -16,6 +16,7 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <netinet/in.h>
> +#include <errno.h>
>  
>  #include <libmnl/libmnl.h>
>  #include <linux/netfilter/nfnetlink.h>
> @@ -374,8 +375,83 @@ int nft_set_elems_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s)
>  }
>  EXPORT_SYMBOL(nft_set_elems_nlmsg_parse);
>  
> +static int nft_set_elem_xml_parse(struct nft_set_elem *e, char *xml)
> +{
> +#ifdef XML_PARSING
> +	mxml_node_t *tree = NULL;
> +	int set_elem_data;
> +
> +	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
> +	if (tree == NULL) {
> +		errno = EINVAL;
> +		return -1;
> +	}
> +
> +	if (strcmp(tree->value.opaque, "set_elem") != 0)
> +		goto einval;
> +
> +	if (nft_mxml_num_parse(tree, "set_elem_flags", MXML_DESCEND_FIRST,
> +			       BASE_DEC, &e->set_elem_flags,
> +			       NFT_TYPE_U32) != 0)
> +		goto einval;

no need to einval here, num_parse already sets.

> +
> +	e->flags |= (1 << NFT_SET_ELEM_ATTR_FLAGS);
> +
> +	if (nft_mxml_data_reg_parse(tree, "set_elem_key",
> +				    &e->key) != DATA_VALUE)
> +		goto einval;
> +
> +	e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY);
> +
> +	set_elem_data = nft_mxml_data_reg_parse(tree, "set_elem_data",
> +						&e->data);
> +	switch (set_elem_data) {
> +	case DATA_VALUE:
> +		e->flags |= (1 << NFT_SET_ELEM_ATTR_DATA);
> +		break;
> +	case DATA_VERDICT:
> +		e->flags |= (1 << NFT_SET_ELEM_ATTR_VERDICT);
> +		break;
> +	case DATA_CHAIN:
> +		e->flags |= (1 << NFT_SET_ELEM_ATTR_CHAIN);
> +		break;
> +	default:
> +		goto einval;
> +	}
> +
> +	mxmlDelete(tree);
> +	return 0;
> +
> +einval:
> +	errno = EINVAL;
> +	mxmlDelete(tree);
> +	return -1;
> +#else
> +	errno = EOPNOTSUPP;
> +	return -1;
> +#endif
> +}
> +
> +int nft_set_elem_parse(struct nft_set_elem *e,
> +		       enum nft_set_parse_type type, char *data) {
> +	int ret;
> +
> +	switch (type) {
> +	case NFT_SET_PARSE_XML:
> +		ret = nft_set_elem_xml_parse(e, data);
> +		break;
> +	default:
> +		errno = EOPNOTSUPP;
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(nft_set_elem_parse);
> +
>  static int nft_set_elem_snprintf_json(char *buf, size_t size,
> -				       struct nft_set_elem *e, uint32_t flags)
> +				      struct nft_set_elem *e, uint32_t flags)
>  {
>  	int ret, len = size, offset = 0, type = -1;
>  
> @@ -414,8 +490,9 @@ static int nft_set_elem_snprintf_json(char *buf, size_t size,
>  	return offset;
>  }
>  
> -static int nft_set_elem_snprintf_default(char *buf, size_t size,
> -					 struct nft_set_elem *e)
> +static
> +int nft_set_elem_snprintf_default(char *buf, size_t size,
> +				  struct nft_set_elem *e, uint32_t flags)
>  {
>  	int ret, len = size, offset = 0, i;
>  
> @@ -505,7 +582,7 @@ int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *e,
>  {
>  	switch(type) {
>  	case NFT_SET_O_DEFAULT:
> -		return nft_set_elem_snprintf_default(buf, size, e);
> +		return nft_set_elem_snprintf_default(buf, size, e, flags);
>  	case NFT_SET_O_XML:
>  		return nft_set_elem_snprintf_xml(buf, size, e, flags);
>  	case NFT_SET_O_JSON:
> diff --git a/tests/nft-parsing-test.c b/tests/nft-parsing-test.c
> index 4fe60c3..c75d97b 100644
> --- a/tests/nft-parsing-test.c
> +++ b/tests/nft-parsing-test.c
> @@ -9,6 +9,7 @@
>  #include <libnftables/table.h>
>  #include <libnftables/chain.h>
>  #include <libnftables/rule.h>
> +#include <libnftables/set.h>
>  
>  #ifdef XML_PARSING
>  #include <mxml.h>
> @@ -21,6 +22,7 @@ static int test_xml(const char *filename)
>  	struct nft_table *t = NULL;
>  	struct nft_chain *c = NULL;
>  	struct nft_rule *r = NULL;
> +	struct nft_set *s = NULL;
>  	FILE *fp;
>  	mxml_node_t *tree = NULL;;
>  	char *xml = NULL;
> @@ -61,6 +63,14 @@ static int test_xml(const char *filename)
>  
>  			nft_rule_free(r);
>  		}
> +	} else if (strcmp(tree->value.opaque, "set") == 0) {
> +		s = nft_set_alloc();
> +		if (s != NULL) {
> +			if (nft_set_parse(s, NFT_SET_PARSE_XML, xml) == 0)
> +				ret = 0;
> +
> +			nft_set_free(s);
> +		}
>  	}
>  
>  	return ret;
> diff --git a/tests/xmlfiles/36-set.xml b/tests/xmlfiles/36-set.xml
> new file mode 100644
> index 0000000..71ca189
> --- /dev/null
> +++ b/tests/xmlfiles/36-set.xml
> @@ -0,0 +1,51 @@
> +<set name="set1" table="filter" version="0">
> +	<family>ip</family>
> +	<set_flags>6</set_flags>
> +	<key_type>0</key_type>
> +	<key_len>12</key_len>
> +	<data_type>0</data_type>
> +	<data_len>12</data_len>
> +	<set_elem>
> +		<set_elem_flags>1</set_elem_flags>
> +		<set_elem_key>
> +			<data_reg type="value">
> +				<len>4</len>
> +				<data0>0xffaabbdd</data0>
> +			</data_reg>
> +		</set_elem_key>
> +		<set_elem_data>
> +			<data_reg type="verdict">
> +				<verdict>accept</verdict>
> +			</data_reg>
> +		</set_elem_data>
> +	</set_elem>
> +	<set_elem>
> +		<set_elem_flags>1</set_elem_flags>
> +		<set_elem_key>
> +			<data_reg type="value">
> +				<len>4</len>
> +				<data0>0xffaabb11</data0>
> +			</data_reg>
> +		</set_elem_key>
> +		<set_elem_data>
> +			<data_reg type="chain">
> +				<chain>test</chain>
> +			</data_reg>
> +		</set_elem_data>
> +	</set_elem>
> +	<set_elem>
> +		<set_elem_flags>1</set_elem_flags>
> +		<set_elem_key>
> +			<data_reg type="value">
> +				<len>4</len>
> +				<data0>0xffaabb11</data0>
> +			</data_reg>
> +		</set_elem_key>
> +		<set_elem_data>
> +			<data_reg type="value">
> +				<len>4</len>
> +				<data0>0xcafecafe</data0>
> +			</data_reg>
> +		</set_elem_data>
> +	</set_elem>
> +</set>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2013-07-25 20:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-25 20:20 [libnftables PATCH 1/2] src: utils: add verdict2str Arturo Borrero Gonzalez
2013-07-25 20:20 ` [libnftables PATCH 2/2] set: XML parse Arturo Borrero Gonzalez
2013-07-25 20:49   ` Pablo Neira Ayuso
2013-07-25 20:33 ` [libnftables PATCH 1/2] src: utils: add verdict2str 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).