This patch adds API interfaces to parse nft objects from a given stream. I found this useful in `nft', where I'm trying to parse XML/JSON from a file. about the implementation: * a small selector is added in src/internal.h to avoid duplicating so much code. * The ifdef/endif logic in internal.h is reworked, looking for a cleaner file, and also allowing us to use without fear XML/JSON internal datatypes. Examples will be updated in a separated patch, but the test infraestructure is updated, using this new file-parsing approach. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> --- v1: initial release, using a filename/path as input. v2: rework the patch and use a FILE *stream as input. Implement the struct parse_ops and update nft-parsing-test to include tests for this new API. include/libnftables/chain.h | 1 + include/libnftables/rule.h | 1 + include/libnftables/ruleset.h | 1 + include/libnftables/set.h | 2 + include/libnftables/table.h | 1 + src/chain.c | 30 ++++++++++++---- src/internal.h | 45 ++++++++++++++++++++++-- src/jansson.c | 25 +++++++++++++ src/libnftables.map | 6 +++ src/mxml.c | 31 ++++++++++++++++ src/rule.c | 28 +++++++++++---- src/ruleset.c | 30 ++++++++++++---- src/set.c | 29 +++++++++++---- src/set_elem.c | 46 ++++++++++++++++++++++-- src/table.c | 31 ++++++++++++---- tests/jsonfiles/01-table.json | 1 - tests/nft-parsing-test.c | 78 ++++++++++++++++++++++++----------------- 17 files changed, 301 insertions(+), 85 deletions(-) delete mode 100644 tests/jsonfiles/01-table.json diff --git a/include/libnftables/chain.h b/include/libnftables/chain.h index 8b4eab9..2cffd35 100644 --- a/include/libnftables/chain.h +++ b/include/libnftables/chain.h @@ -52,6 +52,7 @@ struct nlmsghdr; void nft_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nft_chain *t); int nft_chain_parse(struct nft_chain *c, enum nft_parse_type type, const char *data); +int nft_chain_fparse(struct nft_chain *c, enum nft_parse_type type, FILE *fp); int nft_chain_snprintf(char *buf, size_t size, struct nft_chain *t, uint32_t type, uint32_t flags); int nft_chain_fprintf(FILE *fp, struct nft_chain *c, uint32_t type, uint32_t flags); diff --git a/include/libnftables/rule.h b/include/libnftables/rule.h index 86dbc17..5f2fa5e 100644 --- a/include/libnftables/rule.h +++ b/include/libnftables/rule.h @@ -48,6 +48,7 @@ struct nlmsghdr; void nft_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nft_rule *t); int nft_rule_parse(struct nft_rule *r, enum nft_parse_type type, const char *data); +int nft_rule_fparse(struct nft_rule *r, enum nft_parse_type type, FILE *fp); int nft_rule_snprintf(char *buf, size_t size, struct nft_rule *t, uint32_t type, uint32_t flags); int nft_rule_fprintf(FILE *fp, struct nft_rule *r, uint32_t type, uint32_t flags); diff --git a/include/libnftables/ruleset.h b/include/libnftables/ruleset.h index 1ec3059..1501fc2 100644 --- a/include/libnftables/ruleset.h +++ b/include/libnftables/ruleset.h @@ -31,6 +31,7 @@ void nft_ruleset_attr_set(struct nft_ruleset *r, uint16_t attr, void *data); const void *nft_ruleset_attr_get(const struct nft_ruleset *r, uint16_t attr); int nft_ruleset_parse(struct nft_ruleset *rs, enum nft_parse_type type, const char *data); +int nft_ruleset_fparse(struct nft_ruleset *rs, enum nft_parse_type type, FILE *fp); int nft_ruleset_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, uint32_t type, uint32_t flags); int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, uint32_t flags); diff --git a/include/libnftables/set.h b/include/libnftables/set.h index 13ac857..ec12769 100644 --- a/include/libnftables/set.h +++ b/include/libnftables/set.h @@ -61,6 +61,7 @@ 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); int nft_set_parse(struct nft_set *s, enum nft_parse_type type, const char *data); +int nft_set_fparse(struct nft_set *s, enum nft_parse_type type, FILE *fp); /* * Set elements @@ -99,6 +100,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_parse_type type, const char *data); +int nft_set_elem_fparse(struct nft_set_elem *e, enum nft_parse_type type, FILE *fp); 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_fprintf(FILE *fp, struct nft_set_elem *se, uint32_t type, uint32_t flags); diff --git a/include/libnftables/table.h b/include/libnftables/table.h index 1d2be07..8758289 100644 --- a/include/libnftables/table.h +++ b/include/libnftables/table.h @@ -41,6 +41,7 @@ struct nlmsghdr; void nft_table_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nft_table *t); int nft_table_parse(struct nft_table *t, enum nft_parse_type type, const char *data); +int nft_table_fparse(struct nft_table *t, enum nft_parse_type type, FILE *fp); int nft_table_snprintf(char *buf, size_t size, struct nft_table *t, uint32_t type, uint32_t flags); int nft_table_fprintf(FILE *fp, struct nft_table *t, uint32_t type, uint32_t flags); diff --git a/src/chain.c b/src/chain.c index a0004b5..45af8db 100644 --- a/src/chain.c +++ b/src/chain.c @@ -587,13 +587,14 @@ err: } #endif -static int nft_chain_json_parse(struct nft_chain *c, const char *json) +static int nft_chain_json_buildparse(struct nft_chain *c, const char *json, + const struct parse_ops *ops) { #ifdef JSON_PARSING json_t *tree; json_error_t error; - tree = nft_jansson_create_root(json, &error); + tree = ops->jsonbuilder(json, &error); if (tree == NULL) return -1; @@ -702,11 +703,12 @@ int nft_mxml_chain_parse(mxml_node_t *tree, struct nft_chain *c) } #endif -static int nft_chain_xml_parse(struct nft_chain *c, const char *xml) +static int nft_chain_xml_buildparse(struct nft_chain *c, const char *xml, + const struct parse_ops *ops) { #ifdef XML_PARSING int ret; - mxml_node_t *tree = nft_mxml_build_tree(xml, "chain"); + mxml_node_t *tree = ops->xmlbuilder(xml, "chain"); if (tree == NULL) return -1; @@ -719,17 +721,17 @@ static int nft_chain_xml_parse(struct nft_chain *c, const char *xml) #endif } -int nft_chain_parse(struct nft_chain *c, enum nft_parse_type type, - const char *data) +static int nft_chain_do_parse(struct nft_chain *c, enum nft_parse_type type, + const void *data, const struct parse_ops *ops) { int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_chain_xml_parse(c, data); + ret = nft_chain_xml_buildparse(c, data, ops); break; case NFT_PARSE_JSON: - ret = nft_chain_json_parse(c, data); + ret = nft_chain_json_buildparse(c, data, ops); break; default: ret = -1; @@ -739,8 +741,20 @@ int nft_chain_parse(struct nft_chain *c, enum nft_parse_type type, return ret; } + +int nft_chain_parse(struct nft_chain *c, enum nft_parse_type type, const char *data) +{ + return nft_chain_do_parse(c, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_chain_parse); +int nft_chain_fparse(struct nft_chain *c, enum nft_parse_type type, FILE *fp) +{ + return nft_chain_do_parse(c, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_chain_fparse); + + static int nft_chain_snprintf_json(char *buf, size_t size, struct nft_chain *c) { int ret, len = size, offset = 0; diff --git a/src/internal.h b/src/internal.h index a10d874..e0b9761 100644 --- a/src/internal.h +++ b/src/internal.h @@ -32,9 +32,14 @@ enum nft_type { #ifdef XML_PARSING #include <mxml.h> +#else +#define mxml_node_t void +#endif /*XML_PARSING */ + #define NFT_XML_MAND 0 #define NFT_XML_OPT (1 << 0) -mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename); +mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename); +mxml_node_t *nft_mxml_build_tree_file(const void *data, const char *treename); struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node); int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t flags); union nft_data_reg; @@ -53,14 +58,19 @@ struct nft_rule; int nft_mxml_rule_parse(mxml_node_t *tree, struct nft_rule *r); struct nft_set; int nft_mxml_set_parse(mxml_node_t *tree, struct nft_set *s); -#endif #ifdef JSON_PARSING #include <jansson.h> +#else +#define json_t void +#define json_err_t void +#endif /* JSON_PARSING */ + int nft_jansson_parse_val(json_t *root, const char *tag, int type, void *out); const char *nft_jansson_parse_str(json_t *root, const char *tag); bool nft_jansson_node_exist(json_t *root, const char *tag); -json_t *nft_jansson_create_root(const char *json, json_error_t *err); +json_t *nft_jansson_create_root(const void *data, void *err); +json_t *nft_jansson_create_root_file(const void *data, void *err); json_t *nft_jansson_get_node(json_t *root, const char *tag); void nft_jansson_free_root(json_t *root); int nft_jansson_parse_family(json_t *root, void *out); @@ -81,7 +91,29 @@ struct nft_rule; int nft_jansson_parse_rule(struct nft_rule *r, json_t *tree); struct nft_set; int nft_jansson_parse_set(struct nft_set *s, json_t *tree); + +struct parse_ops { + mxml_node_t *(*xmlbuilder)(const void *input_data, const char *treename); + json_t *(*jsonbuilder)(const void *input_data, void *err); +}; + +static const struct parse_ops parse_string_ops = { +#ifdef XML_PARSING + .xmlbuilder = nft_mxml_build_tree, +#endif +#ifdef JSON_PARSING + .jsonbuilder = nft_jansson_create_root +#endif +}; + +static const struct parse_ops parse_stream_ops = { +#ifdef XML_PARSING + .xmlbuilder = nft_mxml_build_tree_file, #endif +#ifdef JSON_PARSING + .jsonbuilder = nft_jansson_create_root_file, +#endif +}; const char *nft_family2str(uint32_t family); int nft_str2family(const char *family); @@ -91,8 +123,13 @@ int nft_str2verdict(const char *verdict); int nft_get_value(enum nft_type type, void *val, void *out); #include <stdio.h> -int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags, int (*snprintf_cb)(char *buf, size_t bufsiz, void *obj, uint32_t type, uint32_t flags)); +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <libnftables/common.h> +int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags, int (*snprintf_cb)(char *buf, size_t bufsiz, void *obj, uint32_t type, uint32_t flags)); void xfree(const void *ptr); struct expr_ops; diff --git a/src/jansson.c b/src/jansson.c index 04146e2..53c9272 100644 --- a/src/jansson.c +++ b/src/jansson.c @@ -76,7 +76,7 @@ bool nft_jansson_node_exist(json_t *root, const char *tag) return json_object_get(root, tag) != NULL; } -json_t *nft_jansson_create_root(const char *json, json_error_t *err) +static json_t *nft_jansson_do_create_root(const char *json, json_error_t *err) { json_t *root; @@ -89,6 +89,29 @@ json_t *nft_jansson_create_root(const char *json, json_error_t *err) return root; } +json_t *nft_jansson_create_root(const void *data, void *err) +{ + return nft_jansson_do_create_root(data, err); +} + +static json_t *nft_jansson_do_create_root_file(FILE *f, json_error_t *err) +{ + json_t *root; + + root = json_loadf(f, 0, err); + if (root == NULL) { + errno = EINVAL; + return NULL; + } + + return root; +} + +json_t *nft_jansson_create_root_file(const void *data, void *err) +{ + return nft_jansson_do_create_root_file((FILE *)data, err); +} + json_t *nft_jansson_get_node(json_t *root, const char *tag) { json_t *node; diff --git a/src/libnftables.map b/src/libnftables.map index 7dc9aee..eb5ed5c 100644 --- a/src/libnftables.map +++ b/src/libnftables.map @@ -13,6 +13,7 @@ global: nft_table_attr_get_u32; nft_table_attr_get_str; nft_table_parse; + nft_table_fparse; nft_table_snprintf; nft_table_fprintf; nft_table_nlmsg_build_payload; @@ -45,6 +46,7 @@ global: nft_chain_attr_get_u64; nft_chain_attr_get_str; nft_chain_parse; + nft_chain_fparse; nft_chain_snprintf; nft_chain_fprintf; nft_chain_nlmsg_build_payload; @@ -74,6 +76,7 @@ global: nft_rule_attr_get_u64; nft_rule_attr_get_str; nft_rule_parse; + nft_rule_fparse; nft_rule_snprintf; nft_rule_fprintf; nft_rule_nlmsg_build_payload; @@ -128,6 +131,7 @@ global: nft_set_nlmsg_build_payload; nft_set_nlmsg_parse; nft_set_parse; + nft_set_fparse; nft_set_snprintf; nft_set_fprintf; @@ -159,6 +163,7 @@ global: nft_set_elem_nlmsg_build_payload; nft_set_elem_nlmsg_parse; nft_set_elem_parse; + nft_set_elem_fparse; nft_set_elem_snprintf; nft_set_elem_fprinf; @@ -179,6 +184,7 @@ global: nft_ruleset_attr_set; nft_ruleset_attr_get; nft_ruleset_parse; + nft_ruleset_fparse; nft_ruleset_snprintf; nft_ruleset_fprintf; diff --git a/src/mxml.c b/src/mxml.c index 82156b7..3457207 100644 --- a/src/mxml.c +++ b/src/mxml.c @@ -22,7 +22,9 @@ #include <libnftables/set.h> #ifdef XML_PARSING -mxml_node_t *nft_mxml_build_tree(const char *xml, const char *treename) + +static mxml_node_t *nft_mxml_do_build_tree(const char *xml, + const char *treename) { mxml_node_t *tree; @@ -39,6 +41,33 @@ err: return NULL; } +mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename) +{ + return nft_mxml_do_build_tree(data, treename); +} + +static mxml_node_t *nft_mxml_do_build_tree_file(FILE *f, const char *treename) +{ + mxml_node_t *tree; + + tree = mxmlLoadFile(NULL, f, MXML_OPAQUE_CALLBACK); + if (tree == NULL) + goto err; + + if (strcmp(tree->value.opaque, treename) == 0) + return tree; + + mxmlDelete(tree); +err: + errno = EINVAL; + return NULL; +} + +mxml_node_t *nft_mxml_build_tree_file(const void *data, const char *treename) +{ + return nft_mxml_do_build_tree_file((void *)data, treename); +} + struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node) { mxml_node_t *tree; diff --git a/src/rule.c b/src/rule.c index 280350a..55312e5 100644 --- a/src/rule.c +++ b/src/rule.c @@ -521,13 +521,14 @@ err: } #endif -static int nft_rule_json_parse(struct nft_rule *r, const char *json) +static int nft_rule_json_buildparse(struct nft_rule *r, const char *json, + const struct parse_ops *ops) { #ifdef JSON_PARSING json_t *tree; json_error_t error; - tree = nft_jansson_create_root(json, &error); + tree = ops->jsonbuilder(json, &error); if (tree == NULL) return -1; @@ -620,11 +621,12 @@ int nft_mxml_rule_parse(mxml_node_t *tree, struct nft_rule *r) } #endif -static int nft_rule_xml_parse(struct nft_rule *r, const char *xml) +static int nft_rule_xml_buildparse(struct nft_rule *r, const char *xml, + const struct parse_ops *ops) { #ifdef XML_PARSING int ret; - mxml_node_t *tree = nft_mxml_build_tree(xml, "rule"); + mxml_node_t *tree = ops->xmlbuilder(xml, "rule"); if (tree == NULL) return -1; @@ -637,17 +639,17 @@ static int nft_rule_xml_parse(struct nft_rule *r, const char *xml) #endif } -int nft_rule_parse(struct nft_rule *r, enum nft_parse_type type, - const char *data) +static int nft_rule_do_parse(struct nft_rule *r, enum nft_parse_type type, + const void *data, const struct parse_ops *ops) { int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_rule_xml_parse(r, data); + ret = nft_rule_xml_buildparse(r, data, ops); break; case NFT_PARSE_JSON: - ret = nft_rule_json_parse(r, data); + ret = nft_rule_json_buildparse(r, data, ops); break; default: ret = -1; @@ -657,8 +659,18 @@ int nft_rule_parse(struct nft_rule *r, enum nft_parse_type type, return ret; } +int nft_rule_parse(struct nft_rule *r, enum nft_parse_type type, const char *data) +{ + return nft_rule_do_parse(r, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_rule_parse); +int nft_rule_fparse(struct nft_rule *r, enum nft_parse_type type, FILE *fp) +{ + return nft_rule_do_parse(r, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_rule_fparse); + static int nft_rule_snprintf_json(char *buf, size_t size, struct nft_rule *r, uint32_t type, uint32_t flags) { diff --git a/src/ruleset.c b/src/ruleset.c index f591382..953d663 100644 --- a/src/ruleset.c +++ b/src/ruleset.c @@ -326,13 +326,14 @@ err: #endif -static int nft_ruleset_json_parse(struct nft_ruleset *rs, const char *json) +static int nft_ruleset_json_buildparse(struct nft_ruleset *rs, const char *json, + const struct parse_ops *ops) { #ifdef JSON_PARSING json_t *root, *array; json_error_t error; - root = nft_jansson_create_root(json, &error); + root = ops->jsonbuilder(json, &error); if (root == NULL) return -1; @@ -525,12 +526,13 @@ err_free: } #endif -static int nft_ruleset_xml_parse(struct nft_ruleset *rs, const char *xml) +static int nft_ruleset_xml_buildparse(struct nft_ruleset *rs, const char *xml, + const struct parse_ops *ops) { #ifdef XML_PARSING mxml_node_t *tree; - tree = nft_mxml_build_tree(xml, "nftables"); + tree = ops->xmlbuilder(xml, "nftables"); if (tree == NULL) return -1; @@ -557,17 +559,17 @@ err: #endif } -int nft_ruleset_parse(struct nft_ruleset *r, enum nft_parse_type type, - const char *data) +static int nft_ruleset_do_parse(struct nft_ruleset *r, enum nft_parse_type type, + const void *data, const struct parse_ops *ops) { int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_ruleset_xml_parse(r, data); + ret = nft_ruleset_xml_buildparse(r, data, ops); break; case NFT_PARSE_JSON: - ret = nft_ruleset_json_parse(r, data); + ret = nft_ruleset_json_buildparse(r, data, ops); break; default: ret = -1; @@ -577,8 +579,20 @@ int nft_ruleset_parse(struct nft_ruleset *r, enum nft_parse_type type, return ret; } + +int nft_ruleset_parse(struct nft_ruleset *rs, enum nft_parse_type type, + const char *data) +{ + return nft_ruleset_do_parse(rs, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_ruleset_parse); +int nft_ruleset_fparse(struct nft_ruleset *rs, enum nft_parse_type type, FILE *fp) +{ + return nft_ruleset_do_parse(rs, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_ruleset_fparse); + static const char *nft_ruleset_o_opentag(uint32_t type) { switch (type) { diff --git a/src/set.c b/src/set.c index c5204cc..624a659 100644 --- a/src/set.c +++ b/src/set.c @@ -371,13 +371,14 @@ err: } #endif -static int nft_set_json_parse(struct nft_set *s, const char *json) +static int nft_set_json_buildparse(struct nft_set *s, const char *json, + const struct parse_ops *ops) { #ifdef JSON_PARSING json_t *tree; json_error_t error; - tree = nft_jansson_create_root(json, &error); + tree = ops->jsonbuilder(json, &error); if (tree == NULL) return -1; @@ -477,11 +478,12 @@ int nft_mxml_set_parse(mxml_node_t *tree, struct nft_set *s) } #endif -static int nft_set_xml_parse(struct nft_set *s, const char *xml) +static int nft_set_xml_buildparse(struct nft_set *s, const void *data, + const struct parse_ops *ops) { #ifdef XML_PARSING int ret; - mxml_node_t *tree = nft_mxml_build_tree(xml, "set"); + mxml_node_t *tree = ops->xmlbuilder(data, "set"); if (tree == NULL) return -1; @@ -494,17 +496,17 @@ static int nft_set_xml_parse(struct nft_set *s, const char *xml) #endif } -int nft_set_parse(struct nft_set *s, enum nft_parse_type type, - const char *data) +static int nft_set_do_parse(struct nft_set *s, enum nft_parse_type type, + const void *data, const struct parse_ops *ops) { int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_set_xml_parse(s, data); + ret = nft_set_xml_buildparse(s, data, ops); break; case NFT_PARSE_JSON: - ret = nft_set_json_parse(s, data); + ret = nft_set_json_buildparse(s, data, ops); break; default: ret = -1; @@ -514,8 +516,19 @@ int nft_set_parse(struct nft_set *s, enum nft_parse_type type, return ret; } + +int nft_set_parse(struct nft_set *s, enum nft_parse_type type, const char *data) +{ + return nft_set_do_parse(s, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_set_parse); +int nft_set_fparse(struct nft_set *s, enum nft_parse_type type, FILE *fp) +{ + return nft_set_do_parse(s, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_set_fparse); + 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 fce9c1d..b5d7f71 100644 --- a/src/set_elem.c +++ b/src/set_elem.c @@ -393,13 +393,14 @@ int nft_mxml_set_elem_parse(mxml_node_t *tree, struct nft_set_elem *e) } #endif -static int nft_set_elem_xml_parse(struct nft_set_elem *e, const char *xml) +static int nft_set_elem_xml_buildparse(struct nft_set_elem *e, const void *data, + const struct parse_ops *ops) { #ifdef XML_PARSING mxml_node_t *tree; int ret; - tree = nft_mxml_build_tree(xml, "set_elem"); + tree = ops->xmlbuilder(data, "set_elem"); if (tree == NULL) return -1; @@ -412,13 +413,36 @@ static int nft_set_elem_xml_parse(struct nft_set_elem *e, const char *xml) #endif } -int nft_set_elem_parse(struct nft_set_elem *e, - enum nft_parse_type type, const char *data) { +static int nft_set_elem_json_buildparse(struct nft_set_elem *e, const void *data, + const struct parse_ops *ops) +{ +#ifdef JSON_PARSING + json_t *tree; + json_error_t error; + + tree = ops->jsonbuilder(data, &error); + if (tree == NULL) + return -1; + + return nft_set_elem_json_parse(e, tree); +#else + errno = EOPNOTSUPP; + return -1; +#endif +} + +static int nft_set_elem_do_parse(struct nft_set_elem *e, + enum nft_parse_type type, const void *data, + const struct parse_ops *ops) +{ int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_set_elem_xml_parse(e, data); + ret = nft_set_elem_xml_buildparse(e, data, ops); + break; + case NFT_PARSE_JSON: + ret = nft_set_elem_json_buildparse(e, data, ops); break; default: errno = EOPNOTSUPP; @@ -428,8 +452,20 @@ int nft_set_elem_parse(struct nft_set_elem *e, return ret; } + +int nft_set_elem_parse(struct nft_set_elem *e, enum nft_parse_type type, + const char *data) +{ + return nft_set_elem_do_parse(e, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_set_elem_parse); +int nft_set_elem_fparse(struct nft_set_elem *e, enum nft_parse_type type, FILE *fp) +{ + return nft_set_elem_do_parse(e, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_set_elem_fparse); + static int nft_set_elem_snprintf_json(char *buf, size_t size, struct nft_set_elem *e, uint32_t flags) { diff --git a/src/table.c b/src/table.c index ba84264..53cb8c1 100644 --- a/src/table.c +++ b/src/table.c @@ -265,11 +265,13 @@ int nft_mxml_table_parse(mxml_node_t *tree, struct nft_table *t) } #endif -static int nft_table_xml_parse(struct nft_table *t, const char *xml) +static int nft_table_xml_buildparse(struct nft_table *t, const void *data, + const struct parse_ops *ops) { #ifdef XML_PARSING int ret; - mxml_node_t *tree = nft_mxml_build_tree(xml, "table"); + mxml_node_t *tree = (mxml_node_t *)ops->xmlbuilder(data, "table"); + if (tree == NULL) return -1; @@ -318,13 +320,14 @@ err: } #endif -static int nft_table_json_parse(struct nft_table *t, const char *json) +static int nft_table_json_buildparse(struct nft_table *t, const void *data, + const struct parse_ops *ops) { #ifdef JSON_PARSING json_t *tree; json_error_t error; - tree = nft_jansson_create_root(json, &error); + tree = (json_t *)ops->jsonbuilder(data, &error); if (tree == NULL) return -1; @@ -335,17 +338,17 @@ static int nft_table_json_parse(struct nft_table *t, const char *json) #endif } -int nft_table_parse(struct nft_table *t, enum nft_parse_type type, - const char *data) +static int nft_table_do_parse(struct nft_table *t, enum nft_parse_type type, + const void *data, const struct parse_ops *ops) { int ret; switch (type) { case NFT_PARSE_XML: - ret = nft_table_xml_parse(t, data); + ret = nft_table_xml_buildparse(t, data, ops); break; case NFT_PARSE_JSON: - ret = nft_table_json_parse(t, data); + ret = nft_table_json_buildparse(t, data, ops); break; default: ret = -1; @@ -355,8 +358,20 @@ int nft_table_parse(struct nft_table *t, enum nft_parse_type type, return ret; } + +int nft_table_parse(struct nft_table *t, enum nft_parse_type type, + const char *data) +{ + return nft_table_do_parse(t, type, data, &parse_string_ops); +} EXPORT_SYMBOL(nft_table_parse); +int nft_table_fparse(struct nft_table *t, enum nft_parse_type type, FILE *fp) +{ + return nft_table_do_parse(t, type, fp, &parse_stream_ops); +} +EXPORT_SYMBOL(nft_table_fparse); + static int nft_table_snprintf_json(char *buf, size_t size, struct nft_table *t) { return snprintf(buf, size, diff --git a/tests/jsonfiles/01-table.json b/tests/jsonfiles/01-table.json deleted file mode 100644 index f217189..0000000 --- a/tests/jsonfiles/01-table.json +++ /dev/null @@ -1 +0,0 @@ -{"table":{"name":"filter","family":"ip","flags":0,"use":0}} diff --git a/tests/nft-parsing-test.c b/tests/nft-parsing-test.c index 6a5ab4d..3b4de75 100644 --- a/tests/nft-parsing-test.c +++ b/tests/nft-parsing-test.c @@ -73,7 +73,7 @@ static void print_detail_error(char *a, char *b) } } -static int compare_test(uint32_t type, void *input, const char *filename) +static int compare_test(uint32_t type, void *input, const char *filename, FILE *fp) { struct nft_table *t = NULL; struct nft_chain *c = NULL; @@ -82,7 +82,6 @@ static int compare_test(uint32_t type, void *input, const char *filename) struct nft_ruleset *rs = NULL; char orig[4096]; char out[4096]; - FILE *fp; switch (type) { case TEST_XML_TABLE: @@ -148,14 +147,8 @@ static int compare_test(uint32_t type, void *input, const char *filename) return -1; } - fp = fopen(filename, "r"); - if (fp == NULL) { - perror("open"); - exit(EXIT_FAILURE); - } - + rewind(fp); fgets(orig, sizeof(orig), fp); - fclose(fp); if (strncmp(orig, out, strlen(out)) == 0) return 0; @@ -179,6 +172,7 @@ static int test_json(const char *filename) json_t *root; json_error_t error; char *json; + FILE *fp; root = json_load_file(filename, 0, &error); if (!root) { @@ -188,11 +182,14 @@ static int test_json(const char *filename) json = json_dumps(root, JSON_INDENT(0)); + fp = fopen(filename, "r"); + if (json_object_get(root, "table") != NULL) { t = nft_table_alloc(); if (t != NULL) { - if (nft_table_parse(t, NFT_PARSE_JSON, json) == 0) - ret = compare_test(TEST_JSON_TABLE, t, filename); + if (nft_table_fparse(t, NFT_PARSE_JSON, fp) == 0) + ret = compare_test(TEST_JSON_TABLE, t, + filename, fp); else goto failparsing; @@ -201,8 +198,9 @@ static int test_json(const char *filename) } else if (json_object_get(root, "chain") != NULL) { c = nft_chain_alloc(); if (c != NULL) { - if (nft_chain_parse(c, NFT_PARSE_JSON, json) == 0) - ret = compare_test(TEST_JSON_CHAIN, c, filename); + if (nft_chain_fparse(c, NFT_PARSE_JSON, fp) == 0) + ret = compare_test(TEST_JSON_CHAIN, c, + filename, fp); else goto failparsing; @@ -211,8 +209,9 @@ static int test_json(const char *filename) } else if (json_object_get(root, "rule") != NULL) { r = nft_rule_alloc(); if (r != NULL) { - if (nft_rule_parse(r, NFT_PARSE_JSON, json) == 0) - ret = compare_test(TEST_JSON_RULE, r, filename); + if (nft_rule_fparse(r, NFT_PARSE_JSON, fp) == 0) + ret = compare_test(TEST_JSON_RULE, r, + filename, fp); else goto failparsing; @@ -221,8 +220,9 @@ static int test_json(const char *filename) } else if (json_object_get(root, "set") != NULL) { s = nft_set_alloc(); if (s != NULL) { - if (nft_set_parse(s, NFT_PARSE_JSON, json) == 0) - ret = compare_test(TEST_JSON_SET, s, filename); + if (nft_set_fparse(s, NFT_PARSE_JSON, fp) == 0) + ret = compare_test(TEST_JSON_SET, s, + filename, fp); else goto failparsing; @@ -231,8 +231,9 @@ static int test_json(const char *filename) } else if (json_object_get(root, "nftables") != NULL) { rs = nft_ruleset_alloc(); if (rs != NULL) { - if (nft_ruleset_parse(rs, NFT_PARSE_JSON, json) == 0) - ret = compare_test(TEST_JSON_RULESET, rs, filename); + if (nft_ruleset_fparse(rs, NFT_PARSE_JSON, fp) == 0) + ret = compare_test(TEST_JSON_RULESET, rs, + filename, fp); else goto failparsing; @@ -240,11 +241,13 @@ static int test_json(const char *filename) } } + fclose(fp); free(json); json_decref(root); return ret; failparsing: + fclose(fp); printf("parsing %s: ", filename); printf("\033[31mFAILED\e[0m (%s)\n", strerror(errno)); free(json); @@ -271,27 +274,28 @@ static int test_xml(const char *filename) fp = fopen(filename, "r"); tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); - fclose(fp); + rewind(fp); if (tree == NULL) { printf("unable to build XML tree from file " "%s \033[31mFAILED\e[0m\n", filename); - return -1; + goto err; } xml = mxmlSaveAllocString(tree, MXML_NO_CALLBACK); if (xml == NULL) { printf("unable to alloc string from XML tree from %s " "\033[31mFAILED\e[0m\n", filename); - return -1; + goto err; } /* Check what parsing should be done */ if (strcmp(tree->value.opaque, "table") == 0) { t = nft_table_alloc(); if (t != NULL) { - if (nft_table_parse(t, NFT_PARSE_XML, xml) == 0) - ret = compare_test(TEST_XML_TABLE, t, filename); + if (nft_table_fparse(t, NFT_PARSE_XML, fp) == 0) + ret = compare_test(TEST_XML_TABLE, t, + filename, fp); else goto failparsing; @@ -300,8 +304,9 @@ static int test_xml(const char *filename) } else if (strcmp(tree->value.opaque, "chain") == 0) { c = nft_chain_alloc(); if (c != NULL) { - if (nft_chain_parse(c, NFT_PARSE_XML, xml) == 0) - ret = compare_test(TEST_XML_CHAIN, c, filename); + if (nft_chain_fparse(c, NFT_PARSE_XML, fp) == 0) + ret = compare_test(TEST_XML_CHAIN, c, + filename, fp); else goto failparsing; @@ -310,8 +315,9 @@ static int test_xml(const char *filename) } else if (strcmp(tree->value.opaque, "rule") == 0) { r = nft_rule_alloc(); if (r != NULL) { - if (nft_rule_parse(r, NFT_PARSE_XML, xml) == 0) - ret = compare_test(TEST_XML_RULE, r, filename); + if (nft_rule_fparse(r, NFT_PARSE_XML, fp) == 0) + ret = compare_test(TEST_XML_RULE, r, + filename, fp); else goto failparsing; @@ -320,8 +326,9 @@ static int test_xml(const char *filename) } else if (strcmp(tree->value.opaque, "set") == 0) { s = nft_set_alloc(); if (s != NULL) { - if (nft_set_parse(s, NFT_PARSE_XML, xml) == 0) - ret = compare_test(TEST_XML_SET, s, filename); + if (nft_set_fparse(s, NFT_PARSE_XML, fp) == 0) + ret = compare_test(TEST_XML_SET, s, + filename, fp); else goto failparsing; @@ -330,10 +337,10 @@ static int test_xml(const char *filename) } else if (strcmp(tree->value.opaque, "nftables") == 0) { rs = nft_ruleset_alloc(); if (rs != NULL) { - if (nft_ruleset_parse(rs, NFT_PARSE_XML, - xml) == 0) + if (nft_ruleset_fparse(rs, NFT_PARSE_XML, + fp) == 0) ret = compare_test(TEST_XML_RULESET, rs, - filename); + filename, fp); else goto failparsing; @@ -341,14 +348,19 @@ static int test_xml(const char *filename) } } + fclose(fp); mxmlDelete(tree); return ret; failparsing: + fclose(fp); mxmlDelete(tree); printf("parsing %s: ", filename); printf("\033[31mFAILED\e[0m (%s)\n", strerror(errno)); return -1; +err: + fclose(fp); + return -1; #else printf("Compiled without support for XML.\n"); return -1; -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html