diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/json.c | 24 | ||||
-rw-r--r-- | src/parser_bison.y | 35 | ||||
-rw-r--r-- | src/parser_json.c | 49 | ||||
-rw-r--r-- | src/rule.c | 12 |
4 files changed, 97 insertions, 23 deletions
@@ -42,6 +42,15 @@ }) #endif +static int json_array_extend_new(json_t *array, json_t *other_array) +{ + int ret; + + ret = json_array_extend(array, other_array); + json_decref(other_array); + return ret; +} + static json_t *expr_print_json(const struct expr *expr, struct output_ctx *octx) { const struct expr_ops *ops; @@ -546,8 +555,10 @@ __binop_expr_json(int op, const struct expr *expr, struct output_ctx *octx) json_t *a = json_array(); if (expr->etype == EXPR_BINOP && expr->op == op) { - json_array_extend(a, __binop_expr_json(op, expr->left, octx)); - json_array_extend(a, __binop_expr_json(op, expr->right, octx)); + json_array_extend_new(a, + __binop_expr_json(op, expr->left, octx)); + json_array_extend_new(a, + __binop_expr_json(op, expr->right, octx)); } else { json_array_append_new(a, expr_print_json(expr, octx)); } @@ -1743,8 +1754,7 @@ static json_t *table_print_json_full(struct netlink_ctx *ctx, } } - json_array_extend(root, rules); - json_decref(rules); + json_array_extend_new(root, rules); return root; } @@ -1752,7 +1762,7 @@ static json_t *table_print_json_full(struct netlink_ctx *ctx, static json_t *do_list_ruleset_json(struct netlink_ctx *ctx, struct cmd *cmd) { unsigned int family = cmd->handle.family; - json_t *root = json_array(), *tmp; + json_t *root = json_array(); struct table *table; list_for_each_entry(table, &ctx->nft->cache.table_cache.list, cache.list) { @@ -1760,9 +1770,7 @@ static json_t *do_list_ruleset_json(struct netlink_ctx *ctx, struct cmd *cmd) table->handle.family != family) continue; - tmp = table_print_json_full(ctx, table); - json_array_extend(root, tmp); - json_decref(tmp); + json_array_extend_new(root, table_print_json_full(ctx, table)); } return root; diff --git a/src/parser_bison.y b/src/parser_bison.y index 61bed761..53f45315 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -742,6 +742,8 @@ int nft_lex(void *, void *, void *); %type <rule> rule rule_alloc %destructor { rule_free($$); } rule +%type <val> table_flags table_flag + %type <val> set_flag_list set_flag %type <val> set_policy_spec @@ -1905,20 +1907,9 @@ table_block_alloc : /* empty */ } ; -table_options : FLAGS STRING +table_options : FLAGS table_flags { - if (strcmp($2, "dormant") == 0) { - $<table>0->flags |= TABLE_F_DORMANT; - free_const($2); - } else if (strcmp($2, "owner") == 0) { - $<table>0->flags |= TABLE_F_OWNER; - free_const($2); - } else { - erec_queue(error(&@2, "unknown table option %s", $2), - state->msgs); - free_const($2); - YYERROR; - } + $<table>0->flags |= $2; } | comment_spec { @@ -1930,6 +1921,24 @@ table_options : FLAGS STRING } ; +table_flags : table_flag + | table_flags COMMA table_flag + { + $$ = $1 | $3; + } + ; +table_flag : STRING + { + $$ = parse_table_flag($1); + free_const($1); + if ($$ == 0) { + erec_queue(error(&@1, "unknown table option %s", $1), + state->msgs); + YYERROR; + } + } + ; + table_block : /* empty */ { $$ = $<table>-1; } | table_block common_block | table_block stmt_separator diff --git a/src/parser_json.c b/src/parser_json.c index 418d4ad7..8b7efaf2 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -2966,6 +2966,45 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) return NULL; } +static int json_parse_table_flags(struct json_ctx *ctx, json_t *root, + enum table_flags *flags) +{ + json_t *tmp, *tmp2; + size_t index; + int flag; + + if (json_unpack(root, "{s:o}", "flags", &tmp)) + return 0; + + if (json_is_string(tmp)) { + flag = parse_table_flag(json_string_value(tmp)); + if (flag) { + *flags = flag; + return 0; + } + json_error(ctx, "Invalid table flag '%s'.", + json_string_value(tmp)); + return 1; + } + if (!json_is_array(tmp)) { + json_error(ctx, "Unexpected table flags value."); + return 1; + } + json_array_foreach(tmp, index, tmp2) { + if (json_is_string(tmp2)) { + flag = parse_table_flag(json_string_value(tmp2)); + + if (flag) { + *flags |= flag; + continue; + } + } + json_error(ctx, "Invalid table flag at index %zu.", index); + return 1; + } + return 0; +} + static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, enum cmd_ops op, enum cmd_obj obj) { @@ -2974,6 +3013,7 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, .table.location = *int_loc, }; struct table *table = NULL; + enum table_flags flags = 0; if (json_unpack_err(ctx, root, "{s:s}", "family", &family)) @@ -2984,6 +3024,9 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, return NULL; json_unpack(root, "{s:s}", "comment", &comment); + if (json_parse_table_flags(ctx, root, &flags)) + return NULL; + } else if (op == CMD_DELETE && json_unpack(root, "{s:s}", "name", &h.table.name) && json_unpack(root, "{s:I}", "handle", &h.handle.id)) { @@ -2997,10 +3040,12 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root, if (h.table.name) h.table.name = xstrdup(h.table.name); - if (comment) { + if (comment || flags) { table = table_alloc(); handle_merge(&table->handle, &h); - table->comment = xstrdup(comment); + if (comment) + table->comment = xstrdup(comment); + table->flags = flags; } if (op == CMD_ADD) @@ -1215,6 +1215,7 @@ struct table *table_lookup_fuzzy(const struct handle *h, static const char *table_flags_name[TABLE_FLAGS_MAX] = { "dormant", "owner", + "persist", }; const char *table_flag_name(uint32_t flag) @@ -1225,6 +1226,17 @@ const char *table_flag_name(uint32_t flag) return table_flags_name[flag]; } +unsigned int parse_table_flag(const char *name) +{ + int i; + + for (i = 0; i < TABLE_FLAGS_MAX; i++) { + if (!strcmp(name, table_flags_name[i])) + return 1 << i; + } + return 0; +} + static void table_print_flags(const struct table *table, const char **delim, struct output_ctx *octx) { |