Skip to contentSkip to conversation

set: XML parse

PATCH Superseded Arturo Borrero Gonzalez 2 participants 2 messages Jul 26, 2013 netfilter

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 set: XML parse

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>

---
v1: initial version.
v2: - let helper version set errno.
- Move set_elem parsing to a helper function.
- <set_elem_data> is now optional.
- realistic testsfiles, also with IPv6 data.

 tests/nft-parsing-test.c  |   10 ++++++++++
 tests/xmlfiles/73-set.xml |   36 ++++++++++++++++++++++++++++++++++++
 tests/xmlfiles/74-set.xml |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)
 create mode 100644 tests/xmlfiles/73-set.xml
 create mode 100644 tests/xmlfiles/74-set.xml
include/libnftables/set.h +9 -0
index 6023d50..4fc3a8d 100644
@@ -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);
src/internal.h +1 -0
index 47cd635..1970c9c 100644
@@ -36,6 +36,7 @@ union nft_data_reg;
 int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name, union nft_data_reg *data_reg);
 int nft_mxml_num_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_flags, int base, void *number, enum nft_type type);
 const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_flags);
+struct nft_set_elem *nft_mxml_set_elem_parse(mxml_node_t *node);
 #endif
 
 #ifdef JSON_PARSING
src/libnftables.map +2 -0
index f2084d9..614c705 100644
@@ -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;
src/mxml.c +46 -0

56 lines not on this page · raw message

src/set.c +137 -0

149 lines not on this page · raw message

src/set_elem.c +84 -1

98 lines not on this page · raw message

tests/nft-parsing-test.c +10 -0
index 83a627c..0734f07 100644
@@ -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>
@@ -62,6 +63,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;
@@ -102,6 +104,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;
tests/xmlfiles/73-set.xml new file +36 -0
new file mode 100644
index 0000000..debcc27
@@ -0,0 +1,36 @@
+<set name="set0" table="filter" version="0">
+	<family>ip</family>
+	<set_flags>0</set_flags>
+	<key_type>0</key_type>
+	<key_len>0</key_len>
+	<data_type>0</data_type>
+	<data_len>0</data_len>
+	<set_elem>
+		<set_elem_flags>0</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0x0300a8c0</data0>
+			</data_reg>
+		</set_elem_key>
+	</set_elem>
+	<set_elem>
+		<set_elem_flags>0</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0x0200a8c0</data0>
+			</data_reg>
+		</set_elem_key>
+	</set_elem>
+	<set_elem>
+		<set_elem_flags>0</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>4</len>
+				<data0>0x0100a8c0</data0>
+			</data_reg>
+		</set_elem_key>
+	</set_elem>
+</set>
+<!-- nft add rule ip filter test ip daddr { 192.168.0.1, 192.168.0.2, 192.168.0.3 } tcp dport 443 counter accept -->
tests/xmlfiles/74-set.xml new file +33 -0
new file mode 100644
index 0000000..1ebb548
@@ -0,0 +1,33 @@
+<set name="set0" table="filter" version="0">
+	<family>ip6</family>
+	<set_flags>0</set_flags>
+	<key_type>0</key_type>
+	<key_len>0</key_len>
+	<data_type>0</data_type>
+	<data_len>0</data_len>
+	<set_elem>
+		<set_elem_flags>0</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>16</len>
+				<data0>0xc09a002a</data0>
+				<data1>0x2700cac1</data1>
+				<data2>0x00000000</data2>
+				<data3>0x70010000</data3>
+			</data_reg>
+		</set_elem_key>
+	</set_elem>
+	<set_elem>
+		<set_elem_flags>0</set_elem_flags>
+		<set_elem_key>
+			<data_reg type="value">
+				<len>16</len>
+				<data0>0xc09a002a</data0>
+				<data1>0x2700cac1</data1>
+				<data2>0x00000000</data2>
+				<data3>0x50010000</data3>
+			</data_reg>
+		</set_elem_key>
+	</set_elem>
+</set>
+<!-- nft add rule ip6 filter test ip6 daddr { 2a00:9ac0:c1ca:27::150, 2a00:9ac0:c1ca:27::170, } counter accept -->

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

#1 lore raw
Quoted 192 lines · Arturo Borrero Gonzalez

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>

---
v1: initial version.
v2: - let helper version set errno.
- Move set_elem parsing to a helper function.
- <set_elem_data> is now optional.
- realistic testsfiles, also with IPv6 data.

 tests/nft-parsing-test.c  |   10 ++++++++++
 tests/xmlfiles/73-set.xml |   36 ++++++++++++++++++++++++++++++++++++
 tests/xmlfiles/74-set.xml |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)
 create mode 100644 tests/xmlfiles/73-set.xml
 create mode 100644 tests/xmlfiles/74-set.xml
include/libnftables/set.h +9 -0
index 6023d50..4fc3a8d 100644
@@ -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);
src/internal.h +1 -0
index 47cd635..1970c9c 100644
@@ -36,6 +36,7 @@ union nft_data_reg;
 int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name, union nft_data_reg *data_reg);
 int nft_mxml_num_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_flags, int base, void *number, enum nft_type type);
 const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_flags);
+struct nft_set_elem *nft_mxml_set_elem_parse(mxml_node_t *node);
 #endif
 
 #ifdef JSON_PARSING
src/libnftables.map +2 -0
index f2084d9..614c705 100644
@@ -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;
src/mxml.c +46 -0
index f812bf6..84514da 100644
@@ -17,6 +17,7 @@
 #include <linux/netfilter/nf_tables.h>
 #include <libnftables/rule.h>
 #include <libnftables/expr.h>
+#include <libnftables/set.h>
 
 #ifdef XML_PARSING
 struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node)
@@ -165,4 +166,49 @@ const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name,
 	return strdup(node->child->value.opaque);
 }
 
+struct nft_set_elem *nft_mxml_set_elem_parse(mxml_node_t *node)
+{
+	mxml_node_t *save;
+	char *set_elem_str;
+	struct nft_set_elem *elem;
+
+	if (node == NULL)
+		goto einval;
+
+	if (strcmp(node->value.opaque, "set_elem") != 0)
+		goto einval;
+
+	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);
+	node->next = save;
+
+	if (set_elem_str == NULL) {
+		free(elem);
+		goto enomem;
+	}
+
+	if (nft_set_elem_parse(elem, NFT_SET_PARSE_XML,
+			       set_elem_str) != 0) {
+		free(set_elem_str);
+		free(elem);
+		return NULL;
+	}
+
+	free(set_elem_str);
+
+	return elem;
+einval:
+	errno = EINVAL;
+	return NULL;
+enomem:
+	errno = ENOMEM;
+	return NULL;
+}
 #endif
src/set.c +16 -0
index ef15527..891bd08 100644
@@ -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,141 @@ 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;
+	mxml_node_t *node = NULL;
+	struct nft_set_elem *elem;
+	int version;
+	int family;
+	char *family_str;
+
+	tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+	if (tree == NULL) {
+		errno = EINVAL;
+		return -1;

src/set.c int nft_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s) · line 329

Quoted 10 lines
src/set.c +10 -0
+	}
+
+	if (strcmp(tree->value.opaque, "set") != 0)
+		goto err;
+
+	if (mxmlElementGetAttr(tree, "version") == NULL)
+		goto err;
+
+	if (nft_strtoi(mxmlElementGetAttr(tree, "version"), 10, &version,
+		       NFT_TYPE_U64) != 0)

I noticed that we cannot use nft_mxml_num_parse here because it's an attribute.

My proposal is:

1) make patch to convert XML attributes to XML nodes in sets.
2) make a patch to add the XML parsing for sets, now using the existing helper functions that we have.

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