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/jansson.c | 83 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 26 deletions(-) (limited to 'src/jansson.c') diff --git a/src/jansson.c b/src/jansson.c index 539f9ab..54a56b9 100644 --- a/src/jansson.c +++ b/src/jansson.c @@ -24,17 +24,21 @@ #ifdef JSON_PARSING static int nft_jansson_load_int_node(json_t *root, const char *node_name, - json_int_t *val) + json_int_t *val, struct nft_parse_err *err) { json_t *node; node = json_object_get(root, node_name); if (node == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = node_name; errno = EINVAL; return -1; } if (!json_is_integer(node)) { + err->error = NFT_PARSE_EBADTYPE; + err->node_name = node_name; errno = ERANGE; return -1; } @@ -43,27 +47,35 @@ static int nft_jansson_load_int_node(json_t *root, const char *node_name, return 0; } -const char *nft_jansson_parse_str(json_t *root, const char *node_name) +const char *nft_jansson_parse_str(json_t *root, const char *node_name, + struct nft_parse_err *err) { json_t *node; const char *val; node = json_object_get(root, node_name); if (node == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = node_name; errno = EINVAL; return NULL; } + val = json_string_value(node); + if (val == NULL) { + err->error = NFT_PARSE_EBADTYPE; + err->node_name = node_name; + } return val; } int nft_jansson_parse_val(json_t *root, const char *node_name, int type, - void *out) + void *out, struct nft_parse_err *err) { json_int_t val; - if (nft_jansson_load_int_node(root, node_name, &val) == -1) + if (nft_jansson_load_int_node(root, node_name, &val, err) == -1) return -1; if (nft_get_value(type, &val, out) == -1) @@ -77,12 +89,17 @@ bool nft_jansson_node_exist(json_t *root, const char *node_name) return json_object_get(root, node_name) != NULL; } -json_t *nft_jansson_create_root(const char *json, json_error_t *err) +json_t *nft_jansson_create_root(const char *json, json_error_t *error, + struct nft_parse_err *err) { json_t *root; - root = json_loadb(json, strlen(json), 0, err); + root = json_loadb(json, strlen(json), 0, error); if (root == NULL) { + err->error = NFT_PARSE_EBADINPUT; + err->line = error->line; + err->column = error->column; + err->node_name = error->source; errno = EINVAL; return NULL; } @@ -90,12 +107,15 @@ json_t *nft_jansson_create_root(const char *json, json_error_t *err) return root; } -json_t *nft_jansson_get_node(json_t *root, const char *node_name) +json_t *nft_jansson_get_node(json_t *root, const char *node_name, + struct nft_parse_err *err) { json_t *node; node = json_object_get(root, node_name); if (node == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = node_name; errno = EINVAL; return NULL; } @@ -108,17 +128,18 @@ void nft_jansson_free_root(json_t *root) json_decref(root); } -int nft_jansson_parse_family(json_t *root, void *out) +int nft_jansson_parse_family(json_t *root, void *out, struct nft_parse_err *err) { const char *str; int family; - str = nft_jansson_parse_str(root, "family"); + str = nft_jansson_parse_str(root, "family", err); if (str == NULL) return -1; family = nft_str2family(str); if (family < 0) { + err->node_name = "family"; errno = EINVAL; return -1; } @@ -128,9 +149,9 @@ int nft_jansson_parse_family(json_t *root, void *out) } int nft_jansson_parse_reg(json_t *root, const char *node_name, int type, - void *out) + void *out, struct nft_parse_err *err) { - if (nft_jansson_parse_val(root, node_name, type, out) < 0) + if (nft_jansson_parse_val(root, node_name, type, out, err) < 0) return -1; if (*((uint32_t *)out) > NFT_REG_MAX){ @@ -142,38 +163,42 @@ int nft_jansson_parse_reg(json_t *root, const char *node_name, int type, } int nft_jansson_str2num(json_t *root, const char *node_name, int base, - void *out, enum nft_type type) + void *out, enum nft_type type, struct nft_parse_err *err) { const char *str; - str = nft_jansson_parse_str(root, node_name); + str = nft_jansson_parse_str(root, node_name, err); if (str == NULL) return -1; return nft_strtoi(str, base, out, type); } -struct nft_rule_expr *nft_jansson_expr_parse(json_t *root) +struct nft_rule_expr *nft_jansson_expr_parse(json_t *root, + struct nft_parse_err *err) { struct nft_rule_expr *e; const char *type; int ret; - type = nft_jansson_parse_str(root, "type"); + type = nft_jansson_parse_str(root, "type", err); if (type == NULL) return NULL; e = nft_rule_expr_alloc(type); - if (e == NULL) - return NULL;; + if (e == NULL) { + err->node_name = "type"; + return NULL; + } - ret = e->ops->json_parse(e, root); + ret = e->ops->json_parse(e, root, err); return ret < 0 ? NULL : e; } int nft_jansson_data_reg_parse(json_t *root, const char *node_name, - union nft_data_reg *data_reg) + union nft_data_reg *data_reg, + struct nft_parse_err *err) { json_t *data; const char *type; @@ -181,24 +206,27 @@ int nft_jansson_data_reg_parse(json_t *root, const char *node_name, data = json_object_get(root, node_name); if (data == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = node_name; errno = EINVAL; return -1; } data = json_object_get(data, "data_reg"); if (data == NULL) { + err->error = NFT_PARSE_EMISSINGNODE; + err->node_name = "data_reg"; errno = EINVAL; return -1; } - ret = nft_data_reg_json_parse(data_reg, data); - + ret = nft_data_reg_json_parse(data_reg, data, err); if (ret < 0) { errno = EINVAL; return -1; } - type = nft_jansson_parse_str(data, "type"); + type = nft_jansson_parse_str(data, "type", err); if (type == NULL) return -1; @@ -209,29 +237,32 @@ int nft_jansson_data_reg_parse(json_t *root, const char *node_name, else if (strcmp(type, "chain") == 0) return DATA_CHAIN; else { + err->error = NFT_PARSE_EBADTYPE; + err->node_name = "type"; errno = EINVAL; return -1; } } -int nft_set_elem_json_parse(struct nft_set_elem *e, json_t *root) +int nft_set_elem_json_parse(struct nft_set_elem *e, json_t *root, + struct nft_parse_err *err) { uint32_t uval32; int set_elem_data; - if (nft_jansson_parse_val(root, "flags", NFT_TYPE_U32, &uval32) < 0) + if (nft_jansson_parse_val(root, "flags", NFT_TYPE_U32, &uval32, err) < 0) return -1; nft_set_elem_attr_set_u32(e, NFT_SET_ELEM_ATTR_FLAGS, uval32); - if (nft_jansson_data_reg_parse(root, "key", &e->key) != DATA_VALUE) + if (nft_jansson_data_reg_parse(root, "key", &e->key, err) != DATA_VALUE) return -1; e->flags |= (1 << NFT_SET_ELEM_ATTR_KEY); if (nft_jansson_node_exist(root, "data")) { set_elem_data = nft_jansson_data_reg_parse(root, "data", - &e->data); + &e->data, err); switch (set_elem_data) { case DATA_VALUE: e->flags |= (1 << NFT_SET_ELEM_ATTR_DATA); -- cgit v1.2.3