This patch uses the flag option of each output function to print an event wrapper string in each object. In order to use this functionality, the caller must pass a flag with either NFT_OUTPUT_FLAG_EVENTNEW or NFT_OUTPUT_FLAG_EVENTDEL activated. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> --- v2: address comments from Pablo: factorize code and fix output flags. include/libnftnl/common.h | 6 +++ src/chain.c | 24 ++++++++++-- src/internal.h | 6 +++ src/rule.c | 30 +++++++++++++-- src/ruleset.c | 38 +++++++++++++++---- src/set.c | 30 +++++++++++++-- src/set_elem.c | 24 ++++++++++-- src/table.c | 23 +++++++++--- src/utils.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 237 insertions(+), 34 deletions(-) diff --git a/include/libnftnl/common.h b/include/libnftnl/common.h index f0c20f0..04d2906 100644 --- a/include/libnftnl/common.h +++ b/include/libnftnl/common.h @@ -15,6 +15,12 @@ enum nft_output_type { NFT_OUTPUT_JSON, }; +enum nft_output_flags { + NFT_OF_EVENT_NEW = (1 << 0), + NFT_OF_EVENT_DEL = (1 << 1), + NFT_OF_EVENT_ANY = (NFT_OF_EVENT_NEW | NFT_OF_EVENT_DEL), +}; + enum nft_parse_type { NFT_PARSE_NONE = 0, NFT_PARSE_XML, diff --git a/src/chain.c b/src/chain.c index 472203e..5311af6 100644 --- a/src/chain.c +++ b/src/chain.c @@ -924,17 +924,31 @@ static int nft_chain_snprintf_default(char *buf, size_t size, int nft_chain_snprintf(char *buf, size_t size, struct nft_chain *c, uint32_t type, uint32_t flags) { + int ret, len = size, offset = 0; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_chain_snprintf_default(buf, size, c); + ret = nft_chain_snprintf_default(buf+offset, len, c); + break; case NFT_OUTPUT_XML: - return nft_chain_snprintf_xml(buf, size, c); + ret = nft_chain_snprintf_xml(buf+offset, len, c); + break; case NFT_OUTPUT_JSON: - return nft_chain_snprintf_json(buf, size, c); - default: + ret = nft_chain_snprintf_json(buf+offset, len, c); break; + default: + return -1; } - return -1; + + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + return offset; } EXPORT_SYMBOL(nft_chain_snprintf); diff --git a/src/internal.h b/src/internal.h index ba994c8..6595e70 100644 --- a/src/internal.h +++ b/src/internal.h @@ -136,6 +136,12 @@ 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)); +int nft_event_header_snprintf(char *buf, size_t bufsize, + uint32_t format, uint32_t flags); +int nft_event_header_fprintf(FILE *fp, uint32_t format, uint32_t flags); +int nft_event_footer_snprintf(char *buf, size_t bufsize, + uint32_t format, uint32_t flags); +int nft_event_footer_fprintf(FILE *fp, uint32_t format, uint32_t flags); void xfree(const void *ptr); diff --git a/src/rule.c b/src/rule.c index df9dd80..ac88abb 100644 --- a/src/rule.c +++ b/src/rule.c @@ -967,17 +967,37 @@ static int nft_rule_snprintf_default(char *buf, size_t size, struct nft_rule *r, int nft_rule_snprintf(char *buf, size_t size, struct nft_rule *r, uint32_t type, uint32_t flags) { + int ret, len = size, offset = 0; + uint32_t inner_flags = flags; + + inner_flags &= ~NFT_OF_EVENT_ANY; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_rule_snprintf_default(buf, size, r, type, flags); + ret = nft_rule_snprintf_default(buf+offset, len, r, type, + inner_flags); + break; case NFT_OUTPUT_XML: - return nft_rule_snprintf_xml(buf, size, r, type, flags); + ret = nft_rule_snprintf_xml(buf+offset, len, r, type, + inner_flags); + break; case NFT_OUTPUT_JSON: - return nft_rule_snprintf_json(buf, size, r, type, flags); - default: + ret = nft_rule_snprintf_json(buf+offset, len, r, type, + inner_flags); break; + default: + return -1; } - return -1; + + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + return offset; } EXPORT_SYMBOL(nft_rule_snprintf); diff --git a/src/ruleset.c b/src/ruleset.c index 3cbec09..98c4367 100644 --- a/src/ruleset.c +++ b/src/ruleset.c @@ -765,14 +765,21 @@ nft_ruleset_do_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, { int ret, len = size, offset = 0; void *prev = NULL; + uint32_t inner_flags = flags; - ret = snprintf(buf+offset, size, "%s", nft_ruleset_o_opentag(type)); + /* dont pass events flags to child calls of _snprintf() */ + inner_flags &= ~NFT_OF_EVENT_ANY; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = snprintf(buf+offset, len, "%s", nft_ruleset_o_opentag(type)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST) && (!nft_table_list_is_empty(rs->table_list))) { ret = nft_ruleset_snprintf_table(buf+offset, len, rs, - type, flags); + type, inner_flags); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); if (ret > 0) @@ -786,7 +793,7 @@ nft_ruleset_do_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, SNPRINTF_BUFFER_SIZE(ret, size, len, offset); ret = nft_ruleset_snprintf_chain(buf+offset, len, rs, - type, flags); + type, inner_flags); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); if (ret > 0) @@ -800,7 +807,7 @@ nft_ruleset_do_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, SNPRINTF_BUFFER_SIZE(ret, size, len, offset); ret = nft_ruleset_snprintf_set(buf+offset, len, rs, - type, flags); + type, inner_flags); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); if (ret > 0) @@ -814,13 +821,16 @@ nft_ruleset_do_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, SNPRINTF_BUFFER_SIZE(ret, size, len, offset); ret = nft_ruleset_snprintf_rule(buf+offset, len, rs, - type, flags); + type, inner_flags); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } ret = snprintf(buf+offset, size, "%s", nft_ruleset_o_closetag(type)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + return offset; } @@ -989,13 +999,20 @@ int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, { int len = 0, ret = 0; void *prev = NULL; + uint32_t inner_flags = flags; + + /* dont pass events flags to child calls of _snprintf() */ + inner_flags &= ~NFT_OF_EVENT_ANY; + + ret = nft_event_header_fprintf(fp, type, flags); + NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); ret = fprintf(fp, "%s", nft_ruleset_o_opentag(type)); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); if ((nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST)) && (!nft_table_list_is_empty(rs->table_list))) { - ret = nft_ruleset_fprintf_tables(fp, rs, type, flags); + ret = nft_ruleset_fprintf_tables(fp, rs, type, inner_flags); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) @@ -1007,7 +1024,7 @@ int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type)); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); - ret = nft_ruleset_fprintf_chains(fp, rs, type, flags); + ret = nft_ruleset_fprintf_chains(fp, rs, type, inner_flags); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) @@ -1019,7 +1036,7 @@ int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type)); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); - ret = nft_ruleset_fprintf_sets(fp, rs, type, flags); + ret = nft_ruleset_fprintf_sets(fp, rs, type, inner_flags); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); if (ret > 0) @@ -1031,13 +1048,16 @@ int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type)); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); - ret = nft_ruleset_fprintf_rules(fp, rs, type, flags); + ret = nft_ruleset_fprintf_rules(fp, rs, type, inner_flags); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); } ret = fprintf(fp, "%s", nft_ruleset_o_closetag(type)); NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); + ret = nft_event_footer_fprintf(fp, type, flags); + NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len); + return len; } EXPORT_SYMBOL(nft_ruleset_fprintf); diff --git a/src/set.c b/src/set.c index 550c262..7c15857 100644 --- a/src/set.c +++ b/src/set.c @@ -704,17 +704,37 @@ static int nft_set_snprintf_xml(char *buf, size_t size, struct nft_set *s, int nft_set_snprintf(char *buf, size_t size, struct nft_set *s, uint32_t type, uint32_t flags) { + int ret, len = size, offset = 0; + uint32_t inner_flags = flags; + + /* prevent set_elems to print as events */ + inner_flags &= ~NFT_OF_EVENT_ANY; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_set_snprintf_default(buf, size, s, type, flags); + ret = nft_set_snprintf_default(buf+offset, len, s, type, + inner_flags); + break; case NFT_OUTPUT_XML: - return nft_set_snprintf_xml(buf, size, s, flags); + ret = nft_set_snprintf_xml(buf+offset, len, s, inner_flags); + break; case NFT_OUTPUT_JSON: - return nft_set_snprintf_json(buf, size, s, type, flags); - default: + ret = nft_set_snprintf_json(buf+offset, len, s, type, + inner_flags); break; + default: + return -1; } - return -1; + + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + return offset; } EXPORT_SYMBOL(nft_set_snprintf); diff --git a/src/set_elem.c b/src/set_elem.c index a747ba6..9b40752 100644 --- a/src/set_elem.c +++ b/src/set_elem.c @@ -591,17 +591,31 @@ static int nft_set_elem_snprintf_xml(char *buf, size_t size, int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *e, uint32_t type, uint32_t flags) { + int ret, len = size, offset = 0; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_set_elem_snprintf_default(buf, size, e); + ret = nft_set_elem_snprintf_default(buf+offset, len, e); + break; case NFT_OUTPUT_XML: - return nft_set_elem_snprintf_xml(buf, size, e, flags); + ret = nft_set_elem_snprintf_xml(buf+offset, len, e, flags); + break; case NFT_OUTPUT_JSON: - return nft_set_elem_snprintf_json(buf, size, e, flags); - default: + ret = nft_set_elem_snprintf_json(buf+offset, len, e, flags); break; + default: + return -1; } - return -1; + + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + return offset; } EXPORT_SYMBOL(nft_set_elem_snprintf); diff --git a/src/table.c b/src/table.c index 44e9a7b..b4d1663 100644 --- a/src/table.c +++ b/src/table.c @@ -441,17 +441,30 @@ static int nft_table_snprintf_default(char *buf, size_t size, struct nft_table * int nft_table_snprintf(char *buf, size_t size, struct nft_table *t, uint32_t type, uint32_t flags) { + int ret, len = size, offset = 0; + + ret = nft_event_header_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_table_snprintf_default(buf, size, t); + ret = nft_table_snprintf_default(buf+offset, len, t); + break; case NFT_OUTPUT_XML: - return nft_table_snprintf_xml(buf, size, t); + ret = nft_table_snprintf_xml(buf+offset, len, t); + break; case NFT_OUTPUT_JSON: - return nft_table_snprintf_json(buf, size, t); - default: + ret = nft_table_snprintf_json(buf+offset, len, t); break; + default: + return -1; } - return -1; + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + ret = nft_event_footer_snprintf(buf+offset, len, type, flags); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + + return offset; } EXPORT_SYMBOL(nft_table_snprintf); diff --git a/src/utils.c b/src/utils.c index 18917f5..29a958d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -212,6 +212,96 @@ int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags, return ret; } +static const char *nft_event_opentag(uint32_t event, uint32_t format) +{ + switch (format) { + case NFT_OUTPUT_XML: + switch (event) { + case NFT_OF_EVENT_NEW: + return "<event><type>new</type>"; + case NFT_OF_EVENT_DEL: + return "<event><type>destroy</type>"; + default: + return "[unknown]"; + } + case NFT_OUTPUT_JSON: + switch (event) { + case NFT_OF_EVENT_NEW: + return "{event:{type:\"new\",{\""; + case NFT_OF_EVENT_DEL: + return "{event:{type:\"destroy\",{\""; + default: + return "[unknown]"; + } + default: + switch (event) { + case NFT_OF_EVENT_NEW: + return "[NEW] "; + case NFT_OF_EVENT_DEL: + return "[DELETE] "; + default: + return "[unknown]"; + } + } +} + +int nft_event_header_snprintf(char *buf, size_t bufsize, + uint32_t format, uint32_t flags) +{ + if (flags & NFT_OF_EVENT_NEW) + return snprintf(buf, bufsize, "%9s", + nft_event_opentag(NFT_OF_EVENT_NEW, format)); + + if (flags & NFT_OF_EVENT_DEL) + return snprintf(buf, bufsize, "%9s", + nft_event_opentag(NFT_OF_EVENT_DEL, format)); + + return 0; +} + +int nft_event_header_fprintf(FILE *fp, uint32_t format, uint32_t flags) +{ + if (flags & NFT_OF_EVENT_NEW) + return fprintf(fp, "%9s", + nft_event_opentag(NFT_OF_EVENT_NEW, format)); + + if (flags & NFT_OF_EVENT_DEL) + return fprintf(fp, "%9s", + nft_event_opentag(NFT_OF_EVENT_DEL, format)); + + return 0; +} + +static const char *nft_event_closetag(uint32_t format) +{ + switch (format) { + case NFT_OUTPUT_XML: + return "</event>"; + case NFT_OUTPUT_JSON: + return "}}}"; + default: + return ""; + } +} + +int nft_event_footer_snprintf(char *buf, size_t bufsize, + uint32_t format, uint32_t flags) +{ + if (flags & NFT_OF_EVENT_ANY) + return snprintf(buf, bufsize, "%s", + nft_event_closetag(format)); + + return 0; +} + +int nft_event_footer_fprintf(FILE *fp, uint32_t format, uint32_t flags) +{ + if (flags & NFT_OF_EVENT_ANY) + return fprintf(fp, "%s", nft_event_closetag(format)); + + return 0; +} + void __nft_assert_fail(uint16_t attr, const char *filename, int line) { fprintf(stderr, "libnftnl: attribute %d assertion failed in %s:%d\n", -- 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