summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/datatype.c72
-rw-r--r--src/intervals.c2
-rw-r--r--src/json.c39
-rw-r--r--src/mergesort.c2
-rw-r--r--src/meta.c1
-rw-r--r--src/netlink_delinearize.c22
-rw-r--r--src/parser_bison.y47
-rw-r--r--src/parser_json.c67
-rw-r--r--src/rt.c1
-rw-r--r--src/rule.c12
10 files changed, 207 insertions, 58 deletions
diff --git a/src/datatype.c b/src/datatype.c
index 3205b214..d398a9c8 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -1015,9 +1015,9 @@ const struct datatype mark_type = {
.print = mark_type_print,
.json = mark_type_json,
.parse = mark_type_parse,
- .flags = DTYPE_F_PREFIX,
};
+/* symbol table for private datatypes for reject statement. */
static const struct symbol_table icmp_code_tbl = {
.base = BASE_DECIMAL,
.symbols = {
@@ -1033,16 +1033,17 @@ static const struct symbol_table icmp_code_tbl = {
},
};
-const struct datatype icmp_code_type = {
- .type = TYPE_ICMP_CODE,
+/* private datatype for reject statement. */
+const struct datatype reject_icmp_code_type = {
.name = "icmp_code",
- .desc = "icmp code",
+ .desc = "reject icmp code",
.size = BITS_PER_BYTE,
.byteorder = BYTEORDER_BIG_ENDIAN,
.basetype = &integer_type,
.sym_tbl = &icmp_code_tbl,
};
+/* symbol table for private datatypes for reject statement. */
static const struct symbol_table icmpv6_code_tbl = {
.base = BASE_DECIMAL,
.symbols = {
@@ -1056,16 +1057,17 @@ static const struct symbol_table icmpv6_code_tbl = {
},
};
-const struct datatype icmpv6_code_type = {
- .type = TYPE_ICMPV6_CODE,
+/* private datatype for reject statement. */
+const struct datatype reject_icmpv6_code_type = {
.name = "icmpv6_code",
- .desc = "icmpv6 code",
+ .desc = "reject icmpv6 code",
.size = BITS_PER_BYTE,
.byteorder = BYTEORDER_BIG_ENDIAN,
.basetype = &integer_type,
.sym_tbl = &icmpv6_code_tbl,
};
+/* symbol table for private datatypes for reject statement. */
static const struct symbol_table icmpx_code_tbl = {
.base = BASE_DECIMAL,
.symbols = {
@@ -1077,6 +1079,60 @@ static const struct symbol_table icmpx_code_tbl = {
},
};
+/* private datatype for reject statement. */
+const struct datatype reject_icmpx_code_type = {
+ .name = "icmpx_code",
+ .desc = "reject icmpx code",
+ .size = BITS_PER_BYTE,
+ .byteorder = BYTEORDER_BIG_ENDIAN,
+ .basetype = &integer_type,
+ .sym_tbl = &icmpx_code_tbl,
+};
+
+/* Backward compatible parser for the reject statement. */
+static struct error_record *icmp_code_parse(struct parse_ctx *ctx,
+ const struct expr *sym,
+ struct expr **res)
+{
+ return symbolic_constant_parse(ctx, sym, &icmp_code_tbl, res);
+}
+
+const struct datatype icmp_code_type = {
+ .type = TYPE_ICMP_CODE,
+ .name = "icmp_code",
+ .desc = "icmp code",
+ .size = BITS_PER_BYTE,
+ .byteorder = BYTEORDER_BIG_ENDIAN,
+ .basetype = &integer_type,
+ .parse = icmp_code_parse,
+};
+
+/* Backward compatible parser for the reject statement. */
+static struct error_record *icmpv6_code_parse(struct parse_ctx *ctx,
+ const struct expr *sym,
+ struct expr **res)
+{
+ return symbolic_constant_parse(ctx, sym, &icmpv6_code_tbl, res);
+}
+
+const struct datatype icmpv6_code_type = {
+ .type = TYPE_ICMPV6_CODE,
+ .name = "icmpv6_code",
+ .desc = "icmpv6 code",
+ .size = BITS_PER_BYTE,
+ .byteorder = BYTEORDER_BIG_ENDIAN,
+ .basetype = &integer_type,
+ .parse = icmpv6_code_parse,
+};
+
+/* Backward compatible parser for the reject statement. */
+static struct error_record *icmpx_code_parse(struct parse_ctx *ctx,
+ const struct expr *sym,
+ struct expr **res)
+{
+ return symbolic_constant_parse(ctx, sym, &icmpx_code_tbl, res);
+}
+
const struct datatype icmpx_code_type = {
.type = TYPE_ICMPX_CODE,
.name = "icmpx_code",
@@ -1084,7 +1140,7 @@ const struct datatype icmpx_code_type = {
.size = BITS_PER_BYTE,
.byteorder = BYTEORDER_BIG_ENDIAN,
.basetype = &integer_type,
- .sym_tbl = &icmpx_code_tbl,
+ .parse = icmpx_code_parse,
};
void time_print(uint64_t ms, struct output_ctx *octx)
diff --git a/src/intervals.c b/src/intervals.c
index 68728349..6c3f36fe 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -466,7 +466,7 @@ static int __set_delete(struct list_head *msgs, struct expr *i, struct set *set,
unsigned int debug_mask)
{
i->flags |= EXPR_F_REMOVE;
- list_move(&i->list, &existing_set->init->expressions);
+ list_move_tail(&i->list, &existing_set->init->expressions);
list_expr_sort(&existing_set->init->expressions);
return setelem_delete(msgs, set, init, existing_set->init, debug_mask);
diff --git a/src/json.c b/src/json.c
index 29fbd0cf..b4fad0ab 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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;
@@ -540,11 +549,26 @@ json_t *flagcmp_expr_json(const struct expr *expr, struct output_ctx *octx)
"right", expr_print_json(expr->flagcmp.value, octx));
}
+static json_t *
+__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_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));
+ }
+ return a;
+}
+
json_t *binop_expr_json(const struct expr *expr, struct output_ctx *octx)
{
- return json_pack("{s:[o, o]}", expr_op_symbols[expr->op],
- expr_print_json(expr->left, octx),
- expr_print_json(expr->right, octx));
+ return json_pack("{s:o}", expr_op_symbols[expr->op],
+ __binop_expr_json(expr->op, expr, octx));
}
json_t *relational_expr_json(const struct expr *expr, struct output_ctx *octx)
@@ -1730,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;
}
@@ -1739,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) {
@@ -1747,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/mergesort.c b/src/mergesort.c
index 4d0e280f..5e676be1 100644
--- a/src/mergesort.c
+++ b/src/mergesort.c
@@ -78,7 +78,7 @@ void list_splice_sorted(struct list_head *list, struct list_head *head)
while (l != list) {
if (h == head ||
expr_msort_cmp(list_entry(l, typeof(struct expr), list),
- list_entry(h, typeof(struct expr), list)) < 0) {
+ list_entry(h, typeof(struct expr), list)) <= 0) {
l = l->next;
list_add_tail(l->prev, h);
continue;
diff --git a/src/meta.c b/src/meta.c
index eca8dac7..a17bacf0 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -363,7 +363,6 @@ const struct datatype devgroup_type = {
.print = devgroup_type_print,
.json = devgroup_type_json,
.parse = devgroup_type_parse,
- .flags = DTYPE_F_PREFIX,
};
const struct datatype ifname_type = {
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 5a4cf1b8..da9f7a91 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2858,14 +2858,10 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
* is a cross-day range.
*/
if (mpz_cmp(range->left->value,
- range->right->value) <= 0) {
- if (expr->op == OP_NEQ) {
- range_expr_swap_values(range);
- expr->op = OP_IMPLICIT;
- } else if (expr->op == OP_IMPLICIT) {
- range_expr_swap_values(range);
- expr->op = OP_NEG;
- }
+ range->right->value) <= 0 &&
+ expr->op == OP_NEQ) {
+ range_expr_swap_values(range);
+ expr->op = OP_IMPLICIT;
}
}
/* fallthrough */
@@ -2952,7 +2948,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
switch (dl->pctx.family) {
case NFPROTO_IPV4:
stmt->reject.family = dl->pctx.family;
- datatype_set(stmt->reject.expr, &icmp_code_type);
+ datatype_set(stmt->reject.expr, &reject_icmp_code_type);
if (stmt->reject.type == NFT_REJECT_TCP_RST &&
payload_dependency_exists(&dl->pdctx,
PROTO_BASE_TRANSPORT_HDR))
@@ -2961,7 +2957,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
break;
case NFPROTO_IPV6:
stmt->reject.family = dl->pctx.family;
- datatype_set(stmt->reject.expr, &icmpv6_code_type);
+ datatype_set(stmt->reject.expr, &reject_icmpv6_code_type);
if (stmt->reject.type == NFT_REJECT_TCP_RST &&
payload_dependency_exists(&dl->pdctx,
PROTO_BASE_TRANSPORT_HDR))
@@ -2972,7 +2968,7 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
case NFPROTO_BRIDGE:
case NFPROTO_NETDEV:
if (stmt->reject.type == NFT_REJECT_ICMPX_UNREACH) {
- datatype_set(stmt->reject.expr, &icmpx_code_type);
+ datatype_set(stmt->reject.expr, &reject_icmpx_code_type);
break;
}
@@ -2988,12 +2984,12 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
case NFPROTO_IPV4: /* INET */
case __constant_htons(ETH_P_IP): /* BRIDGE, NETDEV */
stmt->reject.family = NFPROTO_IPV4;
- datatype_set(stmt->reject.expr, &icmp_code_type);
+ datatype_set(stmt->reject.expr, &reject_icmp_code_type);
break;
case NFPROTO_IPV6: /* INET */
case __constant_htons(ETH_P_IPV6): /* BRIDGE, NETDEV */
stmt->reject.family = NFPROTO_IPV6;
- datatype_set(stmt->reject.expr, &icmpv6_code_type);
+ datatype_set(stmt->reject.expr, &reject_icmpv6_code_type);
break;
default:
break;
diff --git a/src/parser_bison.y b/src/parser_bison.y
index bdb73911..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
@@ -3740,40 +3749,40 @@ reject_opts : /* empty */
$<stmt>0->reject.family = NFPROTO_IPV4;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
}
| WITH ICMP reject_with_expr
{
$<stmt>0->reject.family = NFPROTO_IPV4;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
}
| WITH ICMP6 TYPE reject_with_expr close_scope_type close_scope_icmp
{
$<stmt>0->reject.family = NFPROTO_IPV6;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
}
| WITH ICMP6 reject_with_expr
{
$<stmt>0->reject.family = NFPROTO_IPV6;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
}
| WITH ICMPX TYPE reject_with_expr close_scope_type
{
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
}
| WITH ICMPX reject_with_expr
{
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
}
| WITH TCP close_scope_tcp RESET close_scope_reset
{
diff --git a/src/parser_json.c b/src/parser_json.c
index 4fc0479c..8b7efaf2 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1204,6 +1204,18 @@ static struct expr *json_parse_binop_expr(struct json_ctx *ctx,
return NULL;
}
+ if (json_array_size(root) > 2) {
+ left = json_parse_primary_expr(ctx, json_array_get(root, 0));
+ right = json_parse_primary_expr(ctx, json_array_get(root, 1));
+ left = binop_expr_alloc(int_loc, thisop, left, right);
+ for (i = 2; i < json_array_size(root); i++) {
+ jright = json_array_get(root, i);
+ right = json_parse_primary_expr(ctx, jright);
+ left = binop_expr_alloc(int_loc, thisop, left, right);
+ }
+ return left;
+ }
+
if (json_unpack_err(ctx, root, "[o, o!]", &jleft, &jright))
return NULL;
@@ -2331,17 +2343,17 @@ static struct stmt *json_parse_reject_stmt(struct json_ctx *ctx,
stmt->reject.icmp_code = 0;
} else if (!strcmp(type, "icmpx")) {
stmt->reject.type = NFT_REJECT_ICMPX_UNREACH;
- dtype = &icmpx_code_type;
+ dtype = &reject_icmpx_code_type;
stmt->reject.icmp_code = 0;
} else if (!strcmp(type, "icmp")) {
stmt->reject.type = NFT_REJECT_ICMP_UNREACH;
stmt->reject.family = NFPROTO_IPV4;
- dtype = &icmp_code_type;
+ dtype = &reject_icmp_code_type;
stmt->reject.icmp_code = 0;
} else if (!strcmp(type, "icmpv6")) {
stmt->reject.type = NFT_REJECT_ICMP_UNREACH;
stmt->reject.family = NFPROTO_IPV6;
- dtype = &icmpv6_code_type;
+ dtype = &reject_icmpv6_code_type;
stmt->reject.icmp_code = 0;
}
}
@@ -2954,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)
{
@@ -2962,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))
@@ -2972,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)) {
@@ -2985,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)
diff --git a/src/rt.c b/src/rt.c
index d8f3352f..9320b832 100644
--- a/src/rt.c
+++ b/src/rt.c
@@ -61,7 +61,6 @@ const struct datatype realm_type = {
.basetype = &integer_type,
.print = realm_type_print,
.parse = realm_type_parse,
- .flags = DTYPE_F_PREFIX,
};
const struct rt_template rt_templates[] = {
diff --git a/src/rule.c b/src/rule.c
index 45289cc0..65ff0fbb 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -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)
{