diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/datatype.c | 72 | ||||
-rw-r--r-- | src/intervals.c | 2 | ||||
-rw-r--r-- | src/json.c | 39 | ||||
-rw-r--r-- | src/mergesort.c | 2 | ||||
-rw-r--r-- | src/meta.c | 1 | ||||
-rw-r--r-- | src/netlink_delinearize.c | 22 | ||||
-rw-r--r-- | src/parser_bison.y | 47 | ||||
-rw-r--r-- | src/parser_json.c | 67 | ||||
-rw-r--r-- | src/rt.c | 1 | ||||
-rw-r--r-- | src/rule.c | 12 |
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); @@ -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; @@ -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) @@ -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[] = { @@ -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) { |