Add NFT_CTX_OUTPUT_STATELESS flag and enable stateless printing from new output flags interface. This patch adds nft_output_save_flags() and nft_output_restore_flags() to temporarily disable stateful printing Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- v3: Use nft_output_save_flags() and nft_output_restore_flags(). Problem reported by Phil. doc/libnftables.adoc | 17 +++-------------- include/nftables.h | 20 +++++++++++++++++++- include/nftables/libnftables.h | 3 +-- src/expression.c | 2 +- src/json.c | 9 +++++---- src/libnftables.c | 10 ---------- src/main.c | 2 +- src/rule.c | 6 +++--- src/statement.c | 22 ++++++++++++++-------- 9 files changed, 47 insertions(+), 44 deletions(-) diff --git a/doc/libnftables.adoc b/doc/libnftables.adoc index 9655834f6d87..896fbf608a69 100644 --- a/doc/libnftables.adoc +++ b/doc/libnftables.adoc @@ -25,9 +25,6 @@ enum nft_numeric_level nft_ctx_output_get_numeric(struct nft_ctx* '\*ctx'*); void nft_ctx_output_set_numeric(struct nft_ctx* '\*ctx'*, enum nft_numeric_level* 'level'*); -bool nft_ctx_output_get_stateless(struct nft_ctx* '\*ctx'*); -void nft_ctx_output_set_stateless(struct nft_ctx* '\*ctx'*, bool* 'val'*); - unsigned int nft_ctx_output_get_debug(struct nft_ctx* '\*ctx'*); void nft_ctx_output_set_debug(struct nft_ctx* '\*ctx'*, unsigned int* 'mask'*); @@ -98,6 +95,7 @@ The flags setting controls the output format. enum { NFT_CTX_OUTPUT_REVERSEDNS = (1 << 0), NFT_CTX_OUTPUT_SERVICE = (1 << 1), + NFT_CTX_OUTPUT_STATELESS = (1 << 2), }; ---- @@ -105,6 +103,8 @@ NFT_CTX_OUTPUT_REVERSEDNS:: Reverse DNS lookups are performed for IP addresses when printing. Note that this may add significant delay to *list* commands depending on DNS resolver speed. NFT_CTX_OUTPUT_SERVICE:: Print port numbers as services as described in the /etc/services file. +NFT_CTX_OUTPUT_STATELESS:: + If stateless output has been requested then stateful data is not printed. Stateful data refers to those objects that carry run-time data, eg. the *counter* statement holds packet and byte counter values, making it stateful. The *nft_ctx_output_get_flags*() function returns the output flags setting's value in 'ctx'. @@ -141,17 +141,6 @@ The *nft_ctx_output_get_numeric*() function returns the numeric output setting's The *nft_ctx_output_set_numeric*() function sets the numeric output setting in 'ctx' to the value of 'level'. -=== nft_ctx_output_get_stateless() and nft_ctx_output_set_stateless() -In nftables, there are stateful objects, i.e. ruleset elements which carry run-time data. -For example the *counter* statement holds packet and byte counter values, making it stateful. -If stateless output has been requested, this data is omitted when printing ruleset elements. -The default setting is *false*. - - -The *nft_ctx_output_get_stateless*() function returns the stateless output setting's value in 'ctx'. - -The *nft_ctx_output_set_stateless*() function sets the stateless output setting in 'ctx' to the value of 'val'. - === nft_ctx_output_get_debug() and nft_ctx_output_set_debug() Libnftables supports separate debugging of different parts of its internals. To facilitate this, debugging output is controlled via a bit mask. diff --git a/include/nftables.h b/include/nftables.h index 86b44f17d6e2..46a27f19e205 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -18,7 +18,6 @@ struct cookie { struct output_ctx { unsigned int flags; unsigned int numeric; - unsigned int stateless; unsigned int handle; unsigned int echo; unsigned int json; @@ -32,6 +31,20 @@ struct output_ctx { }; }; +static inline void nft_output_save_flags(struct output_ctx *octx, + unsigned int *saved_flags, + unsigned int flag) +{ + *saved_flags = octx->flags; + octx->flags |= flag; +} + +static inline void nft_output_restore_flags(struct output_ctx *octx, + unsigned int restore_flags) +{ + octx->flags = restore_flags; +} + static inline bool nft_output_reversedns(const struct output_ctx *octx) { return octx->flags & NFT_CTX_OUTPUT_REVERSEDNS; @@ -42,6 +55,11 @@ static inline bool nft_output_service(const struct output_ctx *octx) return octx->flags & NFT_CTX_OUTPUT_SERVICE; } +static inline bool nft_output_stateless(const struct output_ctx *octx) +{ + return octx->flags & NFT_CTX_OUTPUT_STATELESS; +} + struct nft_cache { uint16_t genid; struct list_head list; diff --git a/include/nftables/libnftables.h b/include/nftables/libnftables.h index 321441b03ca8..4f1c10901b1b 100644 --- a/include/nftables/libnftables.h +++ b/include/nftables/libnftables.h @@ -47,6 +47,7 @@ void nft_ctx_set_dry_run(struct nft_ctx *ctx, bool dry); enum { NFT_CTX_OUTPUT_REVERSEDNS = (1 << 0), NFT_CTX_OUTPUT_SERVICE = (1 << 1), + NFT_CTX_OUTPUT_STATELESS = (1 << 2), }; unsigned int nft_ctx_output_get_flags(struct nft_ctx *ctx); @@ -54,8 +55,6 @@ void nft_ctx_output_set_flags(struct nft_ctx *ctx, unsigned int flags); enum nft_numeric_level nft_ctx_output_get_numeric(struct nft_ctx *ctx); void nft_ctx_output_set_numeric(struct nft_ctx *ctx, enum nft_numeric_level level); -bool nft_ctx_output_get_stateless(struct nft_ctx *ctx); -void nft_ctx_output_set_stateless(struct nft_ctx *ctx, bool val); unsigned int nft_ctx_output_get_debug(struct nft_ctx *ctx); void nft_ctx_output_set_debug(struct nft_ctx *ctx, unsigned int mask); bool nft_ctx_output_get_handle(struct nft_ctx *ctx); diff --git a/src/expression.c b/src/expression.c index 0bd5112287e7..857ac633fa46 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1041,7 +1041,7 @@ static void set_elem_expr_print(const struct expr *expr, nft_print(octx, " timeout "); time_print(expr->timeout, octx); } - if (!octx->stateless && expr->expiration) { + if (!nft_output_stateless(octx) && expr->expiration) { nft_print(octx, " expires "); time_print(expr->expiration, octx); } diff --git a/src/json.c b/src/json.c index 5ddf6ef4da3a..39a47da8420a 100644 --- a/src/json.c +++ b/src/json.c @@ -1074,7 +1074,7 @@ json_t *quota_stmt_json(const struct stmt *stmt, struct output_ctx *octx) if (stmt->quota.flags & NFT_QUOTA_F_INV) json_object_set_new(root, "inv", json_true()); - if (!octx->stateless && stmt->quota.used) { + if (!nft_output_stateless(octx) && stmt->quota.used) { data_unit = get_rate(stmt->quota.used, &bytes); json_object_set_new(root, "used", json_integer(bytes)); json_object_set_new(root, "used_unit", json_string(data_unit)); @@ -1323,7 +1323,7 @@ json_t *reject_stmt_json(const struct stmt *stmt, struct output_ctx *octx) json_t *counter_stmt_json(const struct stmt *stmt, struct output_ctx *octx) { - if (octx->stateless) + if (nft_output_stateless(octx)) return json_pack("{s:n}", "counter"); return json_pack("{s:{s:I, s:I}}", "counter", @@ -1354,10 +1354,11 @@ json_t *objref_stmt_json(const struct stmt *stmt, struct output_ctx *octx) json_t *meter_stmt_json(const struct stmt *stmt, struct output_ctx *octx) { json_t *root, *tmp; + unsigned int flags; - octx->stateless++; + nft_output_save_flags(octx, &flags, NFT_CTX_OUTPUT_STATELESS); tmp = stmt_print_json(stmt->meter.stmt, octx); - octx->stateless--; + nft_output_restore_flags(octx, flags); root = json_pack("{s:o, s:o, s:i}", "key", expr_print_json(stmt->meter.key, octx), diff --git a/src/libnftables.c b/src/libnftables.c index 06d7c177cde3..35e755e9cc9d 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -323,16 +323,6 @@ void nft_ctx_output_set_numeric(struct nft_ctx *ctx, ctx->output.numeric = level; } -bool nft_ctx_output_get_stateless(struct nft_ctx *ctx) -{ - return ctx->output.stateless; -} - -void nft_ctx_output_set_stateless(struct nft_ctx *ctx, bool val) -{ - ctx->output.stateless = val; -} - unsigned int nft_ctx_output_get_flags(struct nft_ctx *ctx) { return ctx->output.flags; diff --git a/src/main.c b/src/main.c index f92ce82a4529..caea072f405a 100644 --- a/src/main.c +++ b/src/main.c @@ -228,7 +228,7 @@ int main(int argc, char * const *argv) nft_ctx_output_set_numeric(nft, numeric + 1); break; case OPT_STATELESS: - nft_ctx_output_set_stateless(nft, true); + output_flags |= NFT_CTX_OUTPUT_STATELESS; break; case OPT_IP2NAME: output_flags |= NFT_CTX_OUTPUT_REVERSEDNS; diff --git a/src/rule.c b/src/rule.c index 63da3306db3b..35c60de4a8db 100644 --- a/src/rule.c +++ b/src/rule.c @@ -486,7 +486,7 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts, { set_print_declaration(set, opts, octx); - if (set->flags & NFT_SET_EVAL && octx->stateless) { + if (set->flags & NFT_SET_EVAL && nft_output_stateless(octx)) { nft_print(octx, "%s}%s", opts->tab, opts->nl); return; } @@ -1683,7 +1683,7 @@ static void obj_print_data(const struct obj *obj, if (octx->handle > 0) nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); - if (octx->stateless) { + if (nft_output_stateless(octx)) { nft_print(octx, "packets 0 bytes 0"); break; } @@ -1702,7 +1702,7 @@ static void obj_print_data(const struct obj *obj, nft_print(octx, "%s%" PRIu64 " %s", obj->quota.flags & NFT_QUOTA_F_INV ? "over " : "", bytes, data_unit); - if (!octx->stateless && obj->quota.used) { + if (!nft_output_stateless(octx) && obj->quota.used) { data_unit = get_rate(obj->quota.used, &bytes); nft_print(octx, " used %" PRIu64 " %s", bytes, data_unit); diff --git a/src/statement.c b/src/statement.c index e50ac706402d..06068441e404 100644 --- a/src/statement.c +++ b/src/statement.c @@ -112,6 +112,8 @@ struct stmt *verdict_stmt_alloc(const struct location *loc, struct expr *expr) static void meter_stmt_print(const struct stmt *stmt, struct output_ctx *octx) { + unsigned int flags; + nft_print(octx, "meter "); if (stmt->meter.set) { expr_print(stmt->meter.set, octx); @@ -121,9 +123,9 @@ static void meter_stmt_print(const struct stmt *stmt, struct output_ctx *octx) expr_print(stmt->meter.key, octx); nft_print(octx, " "); - octx->stateless++; + nft_output_save_flags(octx, &flags, NFT_CTX_OUTPUT_STATELESS); stmt_print(stmt->meter.stmt, octx); - octx->stateless--; + nft_output_restore_flags(octx, flags); nft_print(octx, "} "); @@ -175,7 +177,7 @@ static void counter_stmt_print(const struct stmt *stmt, struct output_ctx *octx) { nft_print(octx, "counter"); - if (octx->stateless) + if (nft_output_stateless(octx)) return; nft_print(octx, " packets %" PRIu64 " bytes %" PRIu64, @@ -463,7 +465,7 @@ static void quota_stmt_print(const struct stmt *stmt, struct output_ctx *octx) nft_print(octx, "quota %s%" PRIu64 " %s", inv ? "over " : "", bytes, data_unit); - if (!octx->stateless && stmt->quota.used) { + if (!nft_output_stateless(octx) && stmt->quota.used) { data_unit = get_rate(stmt->quota.used, &used); nft_print(octx, " used %" PRIu64 " %s", used, data_unit); } @@ -631,15 +633,17 @@ const char * const set_stmt_op_names[] = { static void set_stmt_print(const struct stmt *stmt, struct output_ctx *octx) { + unsigned int flags; + nft_print(octx, "%s ", set_stmt_op_names[stmt->set.op]); expr_print(stmt->set.set, octx); nft_print(octx, " { "); expr_print(stmt->set.key, octx); if (stmt->set.stmt) { nft_print(octx, " "); - octx->stateless++; + nft_output_save_flags(octx, &flags, NFT_CTX_OUTPUT_STATELESS); stmt_print(stmt->set.stmt, octx); - octx->stateless--; + nft_output_restore_flags(octx, flags); } nft_print(octx, " }"); } @@ -665,15 +669,17 @@ struct stmt *set_stmt_alloc(const struct location *loc) static void map_stmt_print(const struct stmt *stmt, struct output_ctx *octx) { + unsigned int flags; + nft_print(octx, "%s ", set_stmt_op_names[stmt->map.op]); expr_print(stmt->map.set, octx); nft_print(octx, " { "); expr_print(stmt->map.key, octx); if (stmt->map.stmt) { nft_print(octx, " "); - octx->stateless++; + nft_output_save_flags(octx, &flags, NFT_CTX_OUTPUT_STATELESS); stmt_print(stmt->map.stmt, octx); - octx->stateless--; + nft_output_restore_flags(octx, flags); } nft_print(octx, " : "); expr_print(stmt->map.data, octx); -- 2.11.0