summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/internal.h1
-rw-r--r--src/libnftables.map2
-rw-r--r--src/mxml.c46
-rw-r--r--src/set.c140
-rw-r--r--src/set_elem.c85
5 files changed, 273 insertions, 1 deletions
diff --git a/src/internal.h b/src/internal.h
index 47cd635..1970c9c 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -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
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..84514da 100644
--- a/src/mxml.c
+++ b/src/mxml.c
@@ -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
diff --git a/src/set.c b/src/set.c
index b729195..4b0ec6a 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,144 @@ 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;
+ char *name;
+ char *table;
+ int version;
+ int family;
+ char *family_str;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (strcmp(tree->value.opaque, "set") != 0)
+ goto err;
+
+ if (nft_mxml_num_parse(tree, "set_xml_version", MXML_DESCEND_FIRST,
+ BASE_DEC, &version, NFT_TYPE_S32) != 0)
+ goto err;
+
+ if (version != NFT_SET_XML_VERSION)
+ goto err;
+
+ name = (char *)nft_mxml_str_parse(tree, "set_name",
+ MXML_DESCEND_FIRST);
+ if (name == NULL)
+ goto err;
+
+ if (s->name)
+ free(s->name);
+
+ s->name = name;
+ s->flags |= (1 << NFT_SET_ATTR_NAME);
+
+ table = (char *)nft_mxml_str_parse(tree, "set_table",
+ MXML_DESCEND_FIRST);
+ if (table == NULL)
+ goto err;
+
+ if (s->table)
+ free(s->table);
+
+ s->table = strdup(table);
+ s->flags |= (1 << NFT_SET_ATTR_TABLE);
+
+ family_str = (char *)nft_mxml_str_parse(tree, "family",
+ MXML_DESCEND_FIRST);
+ if (family_str == NULL)
+ goto err;
+
+ family = nft_str2family(family_str);
+
+ if (family < 0)
+ goto err;
+
+ 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 err;
+
+ 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 err;
+
+ 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 err;
+
+ 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 err;
+
+ 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 err;
+
+ 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_mxml_set_elem_parse(node);
+ if (elem == NULL)
+ goto err;
+
+ list_add_tail(&elem->head, &s->element_list);
+ }
+
+ mxmlDelete(tree);
+ return 0;
+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..5325373 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,90 @@ 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;
+ mxml_node_t *node;
+ 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) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ if (nft_mxml_num_parse(tree, "set_elem_flags", MXML_DESCEND_FIRST,
+ BASE_DEC, &e->set_elem_flags,
+ NFT_TYPE_U32) != 0)
+ goto err;
+
+ e->flags |= (1 << NFT_SET_ELEM_ATTR_FLAGS);
+
+ if (nft_mxml_data_reg_parse(tree, "set_elem_key",
+ &e->key) != DATA_VALUE)
+ goto err;
+
+ e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY);
+
+ /* <set_elem_data> is not mandatory */
+ node = mxmlFindElement(tree, tree, "set_elem_data", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node != NULL && node->child != NULL) {
+ 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 err;
+ }
+ }
+
+ mxmlDelete(tree);
+ return 0;
+
+err:
+ 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;