From c8b97360470c25007d3675474c636ca1ce95599a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Neira=20Ayuso?= Date: Thu, 25 Jul 2013 22:52:15 +0200 Subject: table: Add json parser support Add function for parsing tables in format JSON Signed-off-by: Alvaro Neira Ayuso Signed-off-by: Pablo Neira Ayuso --- configure.ac | 9 +++++- include/libnftables/table.h | 1 + src/Makefile.am | 3 +- src/internal.h | 10 ++++++ src/jansson.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ src/table.c | 69 +++++++++++++++++++++++++++++++++++++++ src/utils.c | 61 ++++++++++++++++++++-------------- 7 files changed, 206 insertions(+), 26 deletions(-) create mode 100644 src/jansson.c diff --git a/configure.ac b/configure.ac index c8075e9..834c0a3 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,10 @@ AC_ARG_WITH([xml-parsing], AS_HELP_STRING([--with-xml-parsing], [XML parsing sup AS_IF([test "x$with_xml_parsing" = "xyes"], [ PKG_CHECK_MODULES([LIBXML], [mxml >= 2.6]) ]) - +AC_ARG_WITH([json-parsing], AS_HELP_STRING([--with-json-parsing], [JSON parsing support])) +AS_IF([test "x$with_json_parsing" = "xyes"], [ + PKG_CHECK_MODULES([LIBJSON], [jansson >= 2.3]) +]) AC_PROG_CC AM_PROG_CC_C_O AC_DISABLE_STATIC @@ -33,6 +36,10 @@ regular_CPPFLAGS="-D_FILE_OFFSET_BITS=64 -D_REENTRANT" AS_IF([test "x$with_xml_parsing" = "xyes"], [ regular_CPPFLAGS="$regular_CPPFLAGS -DXML_PARSING" ]) + +AS_IF([test "x$with_json_parsing" = "xyes"], [ + regular_CPPFLAGS="$regular_CPPFLAGS -DJSON_PARSING" +]) regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ -Wmissing-prototypes -Wshadow -Wstrict-prototypes \ -Wformat=2 -pipe" diff --git a/include/libnftables/table.h b/include/libnftables/table.h index f3f3e89..24ca374 100644 --- a/include/libnftables/table.h +++ b/include/libnftables/table.h @@ -40,6 +40,7 @@ enum { enum nft_table_parse_type { NFT_TABLE_PARSE_NONE = 0, NFT_TABLE_PARSE_XML, + NFT_TABLE_PARSE_JSON, NFT_TABLE_PARSE_MAX, }; diff --git a/src/Makefile.am b/src/Makefile.am index 6496511..51b40a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ include $(top_srcdir)/Make_global.am lib_LTLIBRARIES = libnftables.la -libnftables_la_LIBADD = ${LIBMNL_LIBS} ${LIBXML_LIBS} +libnftables_la_LIBADD = ${LIBMNL_LIBS} ${LIBXML_LIBS} ${LIBJSON_LIBS} libnftables_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnftables.map \ -version-info $(LIBVERSION) libnftables_la_SOURCES = utils.c \ @@ -11,6 +11,7 @@ libnftables_la_SOURCES = utils.c \ set.c \ set_elem.c \ mxml.c \ + jansson.c \ expr.c \ expr_ops.c \ expr/bitwise.c \ diff --git a/src/internal.h b/src/internal.h index b846814..47cd635 100644 --- a/src/internal.h +++ b/src/internal.h @@ -12,6 +12,7 @@ #include "linux_list.h" #include +#include #define BASE_DEC 10 #define BASE_HEX 16 @@ -37,6 +38,14 @@ int nft_mxml_num_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_f const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name, uint32_t mxml_flags); #endif +#ifdef JSON_PARSING +#include +int nft_jansson_value_parse_val(json_t *root, const char *tag, + int type, void *out); +const char *nft_jansson_value_parse_str(json_t *root, const char *tag); +bool nft_jansson_node_exist(json_t *root, const char *tag); +#endif + #define NFT_TABLE_XML_VERSION 0 #define NFT_CHAIN_XML_VERSION 0 #define NFT_RULE_XML_VERSION 0 @@ -51,6 +60,7 @@ int nft_str2family(const char *family); int nft_strtoi(const char *string, int base, void *number, enum nft_type type); const char *nft_verdict2str(uint32_t verdict); int nft_str2verdict(const char *verdict); +int nft_get_value(enum nft_type type, void *val, void *out); struct expr_ops; diff --git a/src/jansson.c b/src/jansson.c new file mode 100644 index 0000000..2b15240 --- /dev/null +++ b/src/jansson.c @@ -0,0 +1,79 @@ +/* + * (C) 2013 by Álvaro Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef JSON_PARSING + +static int nft_jansson_load_int_node(json_t *root, const char *tag, + json_int_t *val) +{ + json_t *node; + + node = json_object_get(root, tag); + if (node == NULL) { + errno = EINVAL; + return -1; + } + + if (!json_is_integer(node)) { + errno = ERANGE; + goto err; + } + + *val = json_integer_value(node); + + return 0; +err: + return -1; +} + +const char *nft_jansson_value_parse_str(json_t *root, const char *tag) +{ + json_t *node; + const char *val; + + node = json_object_get(root, tag); + if (node == NULL) + return NULL; + + val = json_string_value(node); + + return val; +} + +int nft_jansson_value_parse_val(json_t *root, const char *tag, int type, + void *out) +{ + json_int_t val; + + if (nft_jansson_load_int_node(root, tag, &val) == -1) + goto err; + + if (nft_get_value(type, &val, out) == -1) + goto err; + + return 0; +err: + errno = ERANGE; + return -1; +} + +bool nft_jansson_node_exist(json_t *root, const char *tag) +{ + return json_object_get(root, tag) != NULL; +} +#endif diff --git a/src/table.c b/src/table.c index d814668..65797e8 100644 --- a/src/table.c +++ b/src/table.c @@ -295,6 +295,72 @@ static int nft_table_xml_parse(struct nft_table *t, char *xml) #endif } +static int nft_table_json_parse(struct nft_table *t, char *json) +{ +#ifdef JSON_PARSING + json_t *root; + json_error_t error; + uint64_t version; + uint32_t table_flag; + const char *str = NULL; + + root = json_loadb(json, strlen(json), 0, &error); + if (!root) { + errno = EINVAL; + return -1; + } + + root = json_object_get(root, "table"); + if (root == NULL) { + errno = ERANGE; + return -1; + } + + if (nft_jansson_value_parse_val(root, "version", + NFT_TYPE_U64, &version) == -1) + goto err; + + if (version != NFT_TABLE_JSON_VERSION || version == -1) + goto err; + + str = nft_jansson_value_parse_str(root, "name"); + if (str == NULL) + goto err; + + nft_table_attr_set_str(t, NFT_TABLE_ATTR_NAME, strdup(str)); + + root = json_object_get(root, "properties"); + if (root == NULL) + goto err; + + str = nft_jansson_value_parse_str(root, "family"); + if (str == NULL) + goto err; + + if (nft_str2family(str) < 0) + goto err; + + nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FAMILY, nft_str2family(str)); + + if (nft_jansson_value_parse_val(root, "table_flags", + NFT_TYPE_U32, &table_flag) == -1) + goto err; + + nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, table_flag); + + free(root); + return 0; +err: + free(root); + errno = ERANGE; + return -1; + +#else + errno = EOPNOTSUPP; + return -1; +#endif +} + int nft_table_parse(struct nft_table *t, enum nft_table_parse_type type, char *data) { @@ -304,6 +370,9 @@ int nft_table_parse(struct nft_table *t, enum nft_table_parse_type type, case NFT_TABLE_PARSE_XML: ret = nft_table_xml_parse(t, data); break; + case NFT_TABLE_PARSE_JSON: + ret = nft_table_json_parse(t, data); + break; default: ret = -1; errno = EOPNOTSUPP; diff --git a/src/utils.c b/src/utils.c index ebd40b5..c6bf9ff 100644 --- a/src/utils.c +++ b/src/utils.c @@ -66,57 +66,70 @@ static struct { [NFT_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX }, }; -int nft_strtoi(const char *string, int base, void *out, enum nft_type type) + +int nft_get_value(enum nft_type type, void *val, void *out) { - int64_t sval = 0; - uint64_t uval = -1; - char *endptr; + int64_t sval; + uint64_t uval; switch (type) { case NFT_TYPE_U8: case NFT_TYPE_U16: case NFT_TYPE_U32: case NFT_TYPE_U64: - uval = strtoll(string, &endptr, base); + uval = *((uint64_t *)val); + if (uval > basetype[type].max) { + errno = ERANGE; + return -1; + } + memcpy(out, &uval, basetype[type].len); break; case NFT_TYPE_S8: case NFT_TYPE_S16: case NFT_TYPE_S32: case NFT_TYPE_S64: - sval = strtoull(string, &endptr, base); + sval = *((int64_t *)val); + if (sval < basetype[type].min || + sval > (int64_t)basetype[type].max) { + errno = ERANGE; + return -1; + } + memcpy(out, &sval, basetype[type].len); break; - default: - errno = EINVAL; - return -1; } - if (*endptr) { - errno = EINVAL; - return -1; - } + return 0; +} + +int nft_strtoi(const char *string, int base, void *out, enum nft_type type) +{ + int64_t sval = 0; + uint64_t uval = -1; + char *endptr; switch (type) { case NFT_TYPE_U8: case NFT_TYPE_U16: case NFT_TYPE_U32: case NFT_TYPE_U64: - if (uval > basetype[type].max) { - errno = ERANGE; - return -1; - } - memcpy(out, &uval, basetype[type].len); + uval = strtoll(string, &endptr, base); + nft_get_value(type, &uval, out); break; case NFT_TYPE_S8: case NFT_TYPE_S16: case NFT_TYPE_S32: case NFT_TYPE_S64: - if (sval < basetype[type].min || - sval > (int64_t)basetype[type].max) { - errno = ERANGE; - return -1; - } - memcpy(out, &sval, basetype[type].len); + sval = strtoull(string, &endptr, base); + nft_get_value(type, &sval, out); break; + default: + errno = EINVAL; + return -1; + } + + if (*endptr) { + errno = EINVAL; + return -1; } return 0; -- cgit v1.2.3