From e87d2f9ef8a4a298de5514b30ec2d43d3c90a644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Neira=20Ayuso?= Date: Mon, 6 Jan 2014 00:51:14 +0100 Subject: src: new error reporting approach for XML/JSON parsers I have added a new structure for reporting some errors in parser that we can't cover with errno. In this patch, we have three errors that we can't cover with errno: NFT_PARSE_EBADINPUT : Bad XML/JSON format in the input NFT_PARSE_EMISSINGNODE : Missing node in our input NFT_PARSE_EBADTYPE : Wrong type value in a node Signed-off-by: Alvaro Neira Ayuso Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 21 deletions(-) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index 82156b7..bd09bb3 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -22,13 +22,18 @@ #include #ifdef XML_PARSING -mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename) +mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename, + struct nft_parse_err *err) { mxml_node_t *tree; tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK); - if (tree == NULL) + if (tree == NULL) { + err->error = NFT_PARSE_EBADINPUT; + err->line = 0; + err->column = 0; goto err; + } if (strcmp(tree->value.opaque, treename) == 0) return tree; @@ -39,7 +44,8 @@ err: return NULL; } -struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node) +struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node, + struct nft_parse_err *err) { mxml_node_t *tree; struct nft_rule_expr *e; @@ -48,8 +54,11 @@ struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node) int ret; expr_name = mxmlElementGetAttr(node, "type"); - if (expr_name == NULL) + if (expr_name == NULL) { + err->node_name = "type"; + err->error = NFT_PARSE_EMISSINGNODE; goto err; + } e = nft_rule_expr_alloc(expr_name); if (e == NULL) @@ -65,7 +74,7 @@ struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node) if (tree == NULL) goto err_expr; - ret = e->ops->xml_parse(e, tree); + ret = e->ops->xml_parse(e, tree, err); mxmlDelete(tree); return ret < 0 ? NULL : e; @@ -77,20 +86,24 @@ err: return NULL; } -int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t flags) +int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t flags, + struct nft_parse_err *err) { mxml_node_t *node; uint64_t val; node = mxmlFindElement(tree, tree, reg_name, NULL, NULL, flags); if (node == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; errno = EINVAL; goto err; } if (nft_strtoi(node->child->value.opaque, BASE_DEC, &val, - NFT_TYPE_U64) != 0) + NFT_TYPE_U64) != 0) { + err->error = NFT_PARSE_EBADTYPE; goto err; + } if (val > NFT_REG_MAX) { errno = ERANGE; @@ -98,73 +111,101 @@ int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t flags) } return val; err: + err->node_name = reg_name; return -1; } int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name, - union nft_data_reg *data_reg, uint16_t flags) + union nft_data_reg *data_reg, uint16_t flags, + struct nft_parse_err *err) { mxml_node_t *node; node = mxmlFindElement(tree, tree, node_name, NULL, NULL, MXML_DESCEND_FIRST); if (node == NULL || node->child == NULL) { - if (!(flags & NFT_XML_OPT)) + if (!(flags & NFT_XML_OPT)) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = node_name; errno = EINVAL; + } return DATA_NONE; } - return nft_data_reg_xml_parse(data_reg, node); + return nft_data_reg_xml_parse(data_reg, node, err); } 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, uint16_t flags) + enum nft_type type, uint16_t flags, + struct nft_parse_err *err) { mxml_node_t *node = NULL; + int ret; node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags); if (node == NULL || node->child == NULL) { - if (!(flags & NFT_XML_OPT)) + if (!(flags & NFT_XML_OPT)) { errno = EINVAL; - + err->node_name = node_name; + err->error = NFT_PARSE_EMISSINGNODE; + } return -1; } - return nft_strtoi(node->child->value.opaque, base, number, type); + + ret = nft_strtoi(node->child->value.opaque, base, number, type); + + if (ret != 0) { + err->error = NFT_PARSE_EBADTYPE; + err->node_name = node_name; + } + return ret; } const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name, - uint32_t mxml_flags, uint16_t flags) + uint32_t mxml_flags, uint16_t flags, + struct nft_parse_err *err) { mxml_node_t *node; + const char *ret; node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags); if (node == NULL || node->child == NULL) { - if (!(flags & NFT_XML_OPT)) + if (!(flags & NFT_XML_OPT)) { errno = EINVAL; - + err->node_name = node_name; + err->error = NFT_PARSE_EMISSINGNODE; + } return NULL; } - return node->child->value.opaque; + ret = node->child->value.opaque; + if (ret == NULL) { + err->node_name = node_name; + err->error = NFT_PARSE_EBADTYPE; + } + return ret; } int nft_mxml_family_parse(mxml_node_t *tree, const char *node_name, - uint32_t mxml_flags, uint16_t flags) + uint32_t mxml_flags, uint16_t flags, + struct nft_parse_err *err) { const char *family_str; int family; family_str = nft_mxml_str_parse(tree, node_name, mxml_flags, - flags); + flags, err); if (family_str == NULL) return -1; family = nft_str2family(family_str); - if (family < 0) + if (family < 0) { + err->node_name = node_name; errno = EAFNOSUPPORT; + } return family; } -- cgit v1.2.3 From 7cf3f99d7a4673644dd56984dc418daae48c6dd9 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Tue, 7 Jan 2014 12:47:16 +0100 Subject: mxml: add error reference of the top node We know the top node we are building. Let the user also know it. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index bd09bb3..bc0f084 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -30,16 +30,19 @@ mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename, tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK); if (tree == NULL) { err->error = NFT_PARSE_EBADINPUT; - err->line = 0; - err->column = 0; goto err; } if (strcmp(tree->value.opaque, treename) == 0) return tree; + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = treename; + mxmlDelete(tree); err: + err->line = 0; + err->column = 0; errno = EINVAL; return NULL; } -- cgit v1.2.3 From fc423ae81487e906141f700c7b3515328ff62b7c Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Thu, 9 Jan 2014 12:19:06 +0100 Subject: src: rework and generalize the build/parse system The intention behind this patch is to prepare the introduction of the new API that will allow us to parse files that contain the rule-sets expressed in XML/JSON format. This adds the NFT_PARSE_BUFFER that indicates that the input is provided in a buffer, which is what we currently support. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index bc0f084..575383c 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -22,12 +22,19 @@ #include #ifdef XML_PARSING -mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename, - struct nft_parse_err *err) +mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename, + struct nft_parse_err *err, enum nft_parse_input input) { mxml_node_t *tree; - tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK); + switch (input) { + case NFT_PARSE_BUFFER: + tree = mxmlLoadString(NULL, data, MXML_OPAQUE_CALLBACK); + break; + default: + goto err; + } + if (tree == NULL) { err->error = NFT_PARSE_EBADINPUT; goto err; -- cgit v1.2.3 From d34f0c0508f08a84f4351f2a9369e85ccccfe5a0 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Thu, 9 Jan 2014 12:19:12 +0100 Subject: src: add interface to parse from file This patch adds a new API to parse rule-set expressed in XML/JSON from a file. A new enum nft_parse_input type is added for this purpose. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index 575383c..ddbd01b 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -31,6 +31,9 @@ mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename, case NFT_PARSE_BUFFER: tree = mxmlLoadString(NULL, data, MXML_OPAQUE_CALLBACK); break; + case NFT_PARSE_FILE: + tree = mxmlLoadFile(NULL, (FILE *)data, MXML_OPAQUE_CALLBACK); + break; default: goto err; } -- cgit v1.2.3 From 16c04f3be3f9596f065a75fad2cfb8a37ab53b24 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Wed, 15 Jan 2014 11:42:17 +0100 Subject: mxml: add optional/mandatory flag to nft_mxml_reg_parse There are some cases where a reg is not mandatory, for example: * dreg in lookup * dreg/sreg in meta (last version) So, lets change the function nft_mxml_reg_parse() to add an optional/mandatory flag. dreg in lookup is optional as stated at: net/netfilter/nft_lookup.c:nft_lookup_init() Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index ddbd01b..4988502 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -99,30 +99,34 @@ err: return NULL; } -int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t flags, +int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t *reg, + uint32_t mxmlflags, uint32_t flags, struct nft_parse_err *err) { mxml_node_t *node; - uint64_t val; - node = mxmlFindElement(tree, tree, reg_name, NULL, NULL, flags); + node = mxmlFindElement(tree, tree, reg_name, NULL, NULL, mxmlflags); if (node == NULL) { - err->error = NFT_PARSE_EMISSINGNODE; - errno = EINVAL; - goto err; + if (!(flags & NFT_XML_OPT)) { + err->error = NFT_PARSE_EMISSINGNODE; + errno = EINVAL; + goto err; + } + return -1; } - if (nft_strtoi(node->child->value.opaque, BASE_DEC, &val, - NFT_TYPE_U64) != 0) { + if (nft_strtoi(node->child->value.opaque, BASE_DEC, reg, + NFT_TYPE_U32) != 0) { err->error = NFT_PARSE_EBADTYPE; goto err; } - if (val > NFT_REG_MAX) { + if (*reg > NFT_REG_MAX) { errno = ERANGE; goto err; } - return val; + + return 0; err: err->node_name = reg_name; return -1; -- cgit v1.2.3 From 59e949294f4688bafe44b7def2972987224520c8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 20 Jan 2014 10:26:57 +0100 Subject: rename library to libnftnl We plan to use this library name for the higher layer library. Signed-off-by: Pablo Neira Ayuso --- src/mxml.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/mxml.c') diff --git a/src/mxml.c b/src/mxml.c index 4988502..b2cb95e 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -15,11 +15,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #ifdef XML_PARSING mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename, -- cgit v1.2.3