All of lore.kernel.org
 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 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.